toga-ai 1.0.962 → 1.0.964
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/knowledge/1.0/apps/toga/INDEX.md +1 -0
- package/knowledge/1.0/apps/toga/features/bundleconfirmation-cart-preservation.md +1 -0
- package/knowledge/1.0/apps/toga/features/odp-esd-mcafee-descriptions.md +46 -0
- package/knowledge/2.0/apps/dbchanges2/architecture.md +11 -7
- package/knowledge/2.0/standards/framework-rules.md +3 -1
- package/knowledge/INDEX.md +1 -1
- package/knowledge/clients/nycdoe/features/asn-sftp-ingestion-2-0.md +9 -10
- package/knowledge/clients/office-depot/profile.md +4 -2
- package/package.json +1 -1
|
@@ -4,3 +4,4 @@
|
|
|
4
4
|
|-----|---------|
|
|
5
5
|
| [Bundle Confirmation — Cart Preservation When Adding Add-On Services](features/bundleconfirmation-cart-preservation.md) | ODP TOGa Refresh 2026 fix — adding an add-on service no longer strips the 1-year tech support SKU from the cart (`bundleconfirmation.php` `?services=` block); o |
|
|
6
6
|
| [ODP Customer Search — Loyalty Number (merchantId) Persistence](features/odp-customer-search-loyalty-persistence.md) | Fixes so the ODP loyalty number (`memberId` → `Customers.merchantId`) and the validated standardized address persist through the togarefresh2026 customer-search |
|
|
7
|
+
| [ODP Retail ESD — McAfee Product Descriptions](features/odp-esd-mcafee-descriptions.md) | Where ODP Retail ESD McAfee card text comes from (`TOGA_ODP.Services`, not code) and the hardcoded-override trap in `bundleservices.php`; open before changing a |
|
|
@@ -12,6 +12,7 @@ files:
|
|
|
12
12
|
- toga/app/togarefresh2026/servicerequests/bundleconfirmation.php
|
|
13
13
|
related:
|
|
14
14
|
- ../../../clients/office-depot/features/togarefresh2026-linkbuilder-routing.md
|
|
15
|
+
- ./odp-esd-mcafee-descriptions.md
|
|
15
16
|
---
|
|
16
17
|
|
|
17
18
|
ODP TOGa Refresh 2026 fix — adding an add-on service no longer strips the 1-year tech support SKU from the cart (`bundleconfirmation.php` `?services=` block); open when a cart item vanishes or a new tech support SKU is added.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: ODP Retail ESD — McAfee Product Descriptions
|
|
3
|
+
framework: "1.0"
|
|
4
|
+
repo: toga
|
|
5
|
+
project: TOGa
|
|
6
|
+
client: office-depot
|
|
7
|
+
type: client-feature
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-10-06
|
|
10
|
+
owners: [mhammontree]
|
|
11
|
+
files:
|
|
12
|
+
- toga/app/togarefresh2026/servicerequests/bundleservices.php
|
|
13
|
+
- toga/app/togarefresh2026/servicerequests/mcafeeupdates.php
|
|
14
|
+
- toga/app/togarefresh2026/servicerequests/bundleconfirmation.php
|
|
15
|
+
related:
|
|
16
|
+
- ./bundleconfirmation-cart-preservation.md
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
Where ODP Retail ESD McAfee card text comes from (`TOGA_ODP.Services`, not code) and the hardcoded-override trap in `bundleservices.php`; open before changing any McAfee/ESD name, description, SKU, or price.
|
|
20
|
+
|
|
21
|
+
## Summary
|
|
22
|
+
McAfee offerings on the togarefresh2026 bundle screens are DB-driven. To change text/price, edit `TOGA_ODP.Services` rows — no code change. Check the screen does not overwrite the DB value in PHP.
|
|
23
|
+
|
|
24
|
+
## How it works
|
|
25
|
+
- Query: `TOGA_ODP.Services` (legacy DB, link `db_toga`), `active > 0`, filtered by `clientServiceCategoryId`; joined `ServiceTags` → `TOGA.Tags.icon` for the card image.
|
|
26
|
+
- Category picks the price tier:
|
|
27
|
+
- `185` — computer bought in store (default).
|
|
28
|
+
- `186` — `computerBoughtInStore=no`; sets `$_SESSION['itemBoughtInStore'] = false`.
|
|
29
|
+
- `183` — ids 101873/101875/101876.
|
|
30
|
+
- Rows (prod, 2026-10-06):
|
|
31
|
+
|
|
32
|
+
| Product | SKU | cat 185 id / price | cat 186 id / price |
|
|
33
|
+
|---|---|---|---|
|
|
34
|
+
| Total Protection 1-Device | 8960105 | 101877 / $9.99 | 101880 / $19.99 |
|
|
35
|
+
| McAfee+ Premium Individual | 9786195 | 101878 / $29.99 | 101881 / $39.99 |
|
|
36
|
+
| McAfee+ Advanced Individual | 9264758 | 101879 / $49.99 | 101882 / $59.99 |
|
|
37
|
+
|
|
38
|
+
- Each row has its own `shortDescription` / `longDescription` (Total = 1 device; Premium = unlimited devices + privacy/data-removal; Advanced = unlimited + $1M identity theft coverage/restoration).
|
|
39
|
+
- `bundleservices.php` McAfee loop (~line 1020) shows `shortDescription` on the card and passes the same variable to `openDetailsModal`. `mcafeeupdates.php` (~349) and `bundleconfirmation.php` (~198) read DB text directly. togarefresh2023 `bundleservices.php` reads DB (short, then long) with no override.
|
|
40
|
+
|
|
41
|
+
## Gotchas
|
|
42
|
+
- A hardcoded `$mcafeeShortDescription = 'McAfee Total Protection for 1 device.'` after the DB load made every card and Details modal show the same text. Removed in TRUE-82542. If DB edits do not show up, look for a PHP override first.
|
|
43
|
+
- Card echoes DB text unescaped (`<p class="bunldeMicrosoft"><?php echo $mcafeeShortDescription ?>`). Some `Services` rows store HTML-encoded text (e.g. id 193 `We'll`), so do not escape-fix without checking stored data. Details modal uses `textContent` (safe). Not fixed — out of scope.
|
|
44
|
+
|
|
45
|
+
## Change history
|
|
46
|
+
- 2026-10-06 — Removed hardcoded McAfee short-description override in togarefresh2026 `bundleservices.php`; cards + Details modal now show per-product DB text (TRUE-82542) (mhammontree)
|
|
@@ -6,7 +6,7 @@ project: Database Changes
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: architecture
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-10-
|
|
9
|
+
updated: 2026-10-06
|
|
10
10
|
owners: [jcardinal, mhammontree, bala, ajean]
|
|
11
11
|
files:
|
|
12
12
|
- Core/
|
|
@@ -28,7 +28,7 @@ The 2.0 SQL change-set repo: folder→database layout, the filename execution co
|
|
|
28
28
|
|
|
29
29
|
Because execution order is purely alphabetical, **file naming is the contract.** Files are named with a leading **`YYYY-MM-DD`** date so alphabetical sort = chronological = intended execution order.
|
|
30
30
|
|
|
31
|
-
**Critical rules:** every new `.sql` file **must** be named `YYYY-MM-DD<letter> - <Description>.sql` with a **mandatory lower-case letter** right after the date (`a` for the first file of that day in a folder, then `b`, `c`, …). One folder per database; place client changes under the matching `Client_<Name>` folder. Never edit an already-run migration — add a new dated file instead. The `Client/` **blank must carry the baseline DATA seed** (roles, full ACL, reference/lookup tables, UI config) — **not just schema**; a schema-only blank produces non-functional clients. **A file may only reference tables in the ONE database its folder targets** — `Core`, `Client_*`, `Archive_*`, `Logs*`, and `Cache` are on **separate production clusters**, so any `OtherDatabase.Table` reference is unrunnable in production even though it works locally (see *Database isolation* below; enforced by the `dbchanges2-cluster-isolation` hook). **`Core.Records` and `Core.RecordFields` are the only two tables platform-wide with team-maintained `id`s** — ask the developer for the next value before inserting (never `AUTO_INCREMENT`), and hardcode those `id`s wherever they are referenced, foreign keys included.
|
|
31
|
+
**Critical rules:** every new `.sql` file **must** be named `YYYY-MM-DD<letter> - <Description>.sql` with a **mandatory lower-case letter** right after the date (`a` for the first file of that day in a folder, then `b`, `c`, …). One folder per database; place client changes under the matching `Client_<Name>` folder. **One file per database folder per change** — all of a change's SQL for one database goes in a single file (see *One file per database folder per change*). Never edit an already-run migration — add a new dated file instead. The `Client/` **blank must carry the baseline DATA seed** (roles, full ACL, reference/lookup tables, UI config) — **not just schema**; a schema-only blank produces non-functional clients. **A file may only reference tables in the ONE database its folder targets** — `Core`, `Client_*`, `Archive_*`, `Logs*`, and `Cache` are on **separate production clusters**, so any `OtherDatabase.Table` reference is unrunnable in production even though it works locally (see *Database isolation* below; enforced by the `dbchanges2-cluster-isolation` hook). **`Core.Records` and `Core.RecordFields` are the only two tables platform-wide with team-maintained `id`s** — ask the developer for the next value before inserting (never `AUTO_INCREMENT`), and hardcode those `id`s wherever they are referenced, foreign keys included.
|
|
32
32
|
|
|
33
33
|
## File naming convention (the execution contract)
|
|
34
34
|
|
|
@@ -40,13 +40,17 @@ Because execution order is purely alphabetical, **file naming is the contract.**
|
|
|
40
40
|
|
|
41
41
|
> Naming is loose in punctuation (some files have ` - `, some a bare space, occasionally a trailing-space quirk like `2026-06-03- BLANK_CLIENT_DATABASE.sql`). The **only** hard rule is the leading `YYYY-MM-DD<letter>` so ordering holds.
|
|
42
42
|
|
|
43
|
-
## One file per
|
|
43
|
+
## One file per database folder per change (HARD RULE)
|
|
44
44
|
|
|
45
|
-
**
|
|
45
|
+
**A change (ticket/branch) gets at most ONE `.sql` file per database folder.** All its SQL for that database — every table, `ALTER`, index, seed — goes in that file (e.g. one `Client_Nycdoe/…sql` + one `Core/…sql`). Never one file per statement or table. Why: the deployment team applies each file by hand in each environment — fewer files = fewer steps and less chance of a missed file (deployment team via Mark, 2026-10-06).
|
|
46
46
|
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
-
|
|
47
|
+
- Statements in run order, each with a one-line `#` comment (no prose preamble — see [backend-php](../../standards/backend-php.md)).
|
|
48
|
+
- End **every** statement with `;` — single-statement files often omit it; a combined file needs it.
|
|
49
|
+
- Different database folders stay in separate files — required by *Database isolation*.
|
|
50
|
+
- **Exception — cross-database run order:** when statements must run in a specific order *between* databases (e.g. a `Core` change, then a `Client_<Name>` change that needs it, then another `Core` change), split that database's SQL into more than one dated file so the run order stays correct — and say why in each file's comment. This is the only reason for a second file in the same folder.
|
|
51
|
+
- More SQL for the same branch: add it to the branch's existing file while that file has not run anywhere; once it has run, rule 5 applies (new dated file).
|
|
52
|
+
- The `dbchanges2-file-sprawl` hook warns on a second same-folder file in one turn; it does not see earlier turns — check the branch.
|
|
53
|
+
- Example: TRUE-80519 merged 9 never-run files (5 `Client_Nycdoe`, 4 `Core` CronJobs) into `Client_Nycdoe/2026-10-06a` + `Core/2026-10-06a`.
|
|
50
54
|
|
|
51
55
|
## Folder → database mapping
|
|
52
56
|
|
|
@@ -5,7 +5,7 @@ project: _Underscore
|
|
|
5
5
|
client: shared
|
|
6
6
|
type: standard
|
|
7
7
|
status: active
|
|
8
|
-
updated: 2026-10-
|
|
8
|
+
updated: 2026-10-06
|
|
9
9
|
owners: [jcardinal, ajean, apeterson, mhammontree]
|
|
10
10
|
files: []
|
|
11
11
|
related:
|
|
@@ -111,6 +111,8 @@ migration or schema files.** All schema changes for any 2.0 database — table c
|
|
|
111
111
|
File naming in `dbchanges2`: `YYYY-MM-DD<letter> - <Description>.sql`
|
|
112
112
|
(e.g. `2026-06-30a - Add WorkerJobs failureCode column.sql`).
|
|
113
113
|
|
|
114
|
+
**One file per database folder per change.** All of a change's SQL for one database goes in a single file in that folder — statements in run order, one `#` comment line each, every statement ending in `;`. Never one file per statement or table (the deployment team applies each file by hand), unless files in different databases must run in a specific order. Full rule: `2.0/apps/dbchanges2/architecture.md` → *One file per database folder per change*.
|
|
115
|
+
|
|
114
116
|
This rule applies regardless of which application repo the feature lives in. Even if you
|
|
115
117
|
are adding a column that only `worker2` reads, the `.sql` file goes in `dbchanges2`.
|
|
116
118
|
|
package/knowledge/INDEX.md
CHANGED
|
@@ -13,7 +13,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
|
|
|
13
13
|
- **webhook** (Webhook) — 1 doc(s) → [1.0/apps/webhook/INDEX.md](1.0/apps/webhook/INDEX.md)
|
|
14
14
|
- **walmarttechservices** (Walmart Tech Services) — 1 doc(s) → [1.0/apps/walmarttechservices/INDEX.md](1.0/apps/walmarttechservices/INDEX.md)
|
|
15
15
|
- **test** (Test) — 16 doc(s) → [1.0/apps/test/INDEX.md](1.0/apps/test/INDEX.md)
|
|
16
|
-
- **toga** (TOGa) —
|
|
16
|
+
- **toga** (TOGa) — 4 doc(s) → [1.0/apps/toga/INDEX.md](1.0/apps/toga/INDEX.md)
|
|
17
17
|
- **store** (Store) — 3 doc(s) → [1.0/apps/store/INDEX.md](1.0/apps/store/INDEX.md)
|
|
18
18
|
- **tools** (Tools) — 25 doc(s) → [1.0/apps/tools/INDEX.md](1.0/apps/tools/INDEX.md)
|
|
19
19
|
|
|
@@ -14,12 +14,10 @@ files:
|
|
|
14
14
|
- _underscore/Model/Nycdoe/File.php
|
|
15
15
|
- _underscore/Model/Nycdoe/Case.php
|
|
16
16
|
- _underscore/Model/Nycdoe/ServiceRequest.php
|
|
17
|
-
- dbchanges2/Client_Nycdoe/2026-
|
|
18
|
-
- dbchanges2/
|
|
17
|
+
- dbchanges2/Client_Nycdoe/2026-10-06a - NYCDOE SFTP ASN import schema.sql
|
|
18
|
+
- dbchanges2/Core/2026-10-06a - NYCDOE SFTP Import cron jobs.sql
|
|
19
19
|
- worker2/tests/Integration/ParseCest.php
|
|
20
20
|
- worker2/tests/Integration/ImportDecisionCest.php
|
|
21
|
-
- dbchanges2/Client_Nycdoe/2026-09-14a - Add SFTP import status fields to Files.sql
|
|
22
|
-
- dbchanges2/Core/2026-09-14a - Add SFTP Import cron - NYCDOE Lenovo.sql
|
|
23
21
|
related:
|
|
24
22
|
- servicenow-integration.md
|
|
25
23
|
- ../profile.md
|
|
@@ -35,7 +33,7 @@ The 2.0 replacement for 1.0's `legacy_import_asn.php` + `asnprocessor/*` (see [S
|
|
|
35
33
|
|
|
36
34
|
## How it works
|
|
37
35
|
|
|
38
|
-
1. **`Sftp/Import/Run`** — one `Core.CronJobs` row per client+manufacturer (`dbchanges2/Core/2026-
|
|
36
|
+
1. **`Sftp/Import/Run`** — one `Core.CronJobs` row per client+manufacturer (`dbchanges2/Core/2026-10-06a - NYCDOE SFTP Import cron jobs.sql`). Connects (secret by reference via `_Component_Secrets::resolve`), lists files matching `fileNamePattern`, dedupes (size/mtime, then checksum), saves each new file as a `Files` row (`Files.data` is `FIELD_STORAGE` → auto S3), `c_status='pending'`, then `_Worker::runTask('Sftp/Parse/<adapter>', …)`. Client-agnostic; the client's `Files` model class is passed per CronJobs row. `RunLocalTest()` swaps SFTP listing for a local folder (local SFTP is blocked: dev AWS SSO cannot assume WorkloadsRuntime).
|
|
39
37
|
2. **`Sftp/Parse/{Lenovo,Lexmark,Acer,Apple}`** — loads the `Files` row, **validates the header by exact name match** (mismatch → `c_status='failed'` + throw; never a column-count guess — the direct fix for 1.0's "Lenovo Off-Layout ASN File"), parses rows, then:
|
|
40
38
|
- **Case = one per customer PO** (`Cases.c_customerPurchaseOrder`; `Cases.number` is `FIELD_AUTOINCREMENT`, not settable). One file can hold several POs.
|
|
41
39
|
- **ServiceRequest = one per line**, `serviceRequestTypeId` = `Onsite`, stage = `New` (both looked up by name, never hardcoded ids). Fields: `c_partNumber`, `c_serialNumber`, `c_ritmNumber`, `c_filesId`.
|
|
@@ -73,9 +71,9 @@ The 2.0 replacement for 1.0's `legacy_import_asn.php` + `asnprocessor/*` (see [S
|
|
|
73
71
|
- **Manual ASN files** are uploaded to the Lenovo folder (e.g. `WR260197522-RPL Manual ASN.csv`, 2026-09-14). 2.0 KEEPS them (no pattern) and imports nothing — decide how 2.0 handles manual files.
|
|
74
72
|
- Separate tickets (not done): SSH host-key pinning in `Sftp/Import` `connect()`; rotate the FTP passwords old `DeleteSftpFile` jobs likely stored in `Core.WorkerJobs.parameters` (see [worker2 secrets register](../../../2.0/apps/worker2/features/committed-secrets-and-config-debt.md)).
|
|
75
73
|
|
|
76
|
-
Schema (`dbchanges2/Client_Nycdoe
|
|
74
|
+
Schema (`dbchanges2/Client_Nycdoe/2026-10-06a - NYCDOE SFTP ASN import schema.sql`, statements in run order): Files `c_status` (ENUM `pending`/`processing`/`succeeded`/`failed`/`released`) + non-unique index on `Files.checksum`/`c_manufacturer`/`c_dtProcessed`; ServiceRequestStages seed (New/Scheduled/On Hold/Delivered/Cancelled); ServiceRequests fields; Cases `c_customerPurchaseOrder`; Cases `longDescription`.
|
|
77
75
|
|
|
78
|
-
|
|
76
|
+
Lenovo row (Core file) carries `retiredFileNamePatterns`. The two files replace 9 never-run originals (Client_Nycdoe `2026-09-14a`/`22a`/`22b`/`22c`/`25a`, Core `2026-09-14a` ×4; none ran in prod, verified 2026-10-06), merged per the one-file-per-database rule in the [dbchanges2 architecture](../../../2.0/apps/dbchanges2/architecture.md).
|
|
79
77
|
|
|
80
78
|
Tests: `ParseCest.php` (all 4 mfrs, header rejection, comma repair, claim, kept `failed` status) + `ImportDecisionCest.php` (RunForFile decisions, path check, retired names) — see [worker2 Codeception integration tests](../../../2.0/apps/worker2/features/codeception-integration-tests.md).
|
|
81
79
|
|
|
@@ -83,8 +81,8 @@ Tests: `ParseCest.php` (all 4 mfrs, header rejection, comma repair, claim, kept
|
|
|
83
81
|
PRs open 2026-10-06: library, worker2, dbchanges2, _underscore (worker optional for Part A).
|
|
84
82
|
|
|
85
83
|
**Part A — inert (no 1.0 behavior change):**
|
|
86
|
-
1.
|
|
87
|
-
2.
|
|
84
|
+
1. Run `Client_Nycdoe/2026-10-06a - NYCDOE SFTP ASN import schema.sql` on the NYCDOE client DB.
|
|
85
|
+
2. Then run `Core/2026-10-06a - NYCDOE SFTP Import cron jobs.sql` on Core (Acer/Apple/Lenovo/Lexmark CronJobs, `isActive=0`).
|
|
88
86
|
3. Confirm `Files` has `c_status`/`c_manufacturer`/`c_dtProcessed` + checksum index, and 4 inactive `Sftp/Import/Run` rows.
|
|
89
87
|
4. Deploy `_underscore` (Rohan's weekly window; `Model/Nycdoe` File/Case/ServiceRequest — commits `05a98743`, `1223e2a9`).
|
|
90
88
|
5. Deploy worker2.
|
|
@@ -113,9 +111,10 @@ PRs open 2026-10-06: library, worker2, dbchanges2, _underscore (worker optional
|
|
|
113
111
|
- **worker2 runs each job in one transaction** (`Route.php` `transactionStart`; `Controller/Index.php` rolls back on throw). A status save followed by `throw` is rolled back — the Phase 2 bug left rejected files `pending` forever. Save failure status after the rollback, outside the job transaction.
|
|
114
112
|
- **`connect()` must not chain the phpseclib exception** — phpseclib `login()` frames carry the first 15 chars of the password, and worker2 stores job traces in `Core.WorkerJobs`. It rethrows a fresh exception with no `previous`.
|
|
115
113
|
- **Locks and just-committed rows must read the writer** — see the read-host gotcha in [Per-Client Database Connections](../../../2.0/apps/_underscore/features/per-client-database-connections.md).
|
|
116
|
-
- **Schema drift: `_Model_Client_Case` declares `longDescription` but `Client_Nycdoe.Cases` lacked the column** → any direct-model Case load/save 1054s. Fixed for DOE (
|
|
114
|
+
- **Schema drift: `_Model_Client_Case` declares `longDescription` but `Client_Nycdoe.Cases` lacked the column** → any direct-model Case load/save 1054s. Fixed for DOE (Client_Nycdoe schema file). Other tenants' `Cases` may have the same gap — unchecked (ask Rohan).
|
|
117
115
|
|
|
118
116
|
## Change history
|
|
117
|
+
- 2026-10-06 — 9 dbchanges2 files merged into one Client_Nycdoe + one Core file; runbook Part A updated (mhammontree)
|
|
119
118
|
- 2026-10-06 — Activation/deployment runbook (Part A inert, Part B shadow mode, rollback, failed-file release) (mhammontree)
|
|
120
119
|
- 2026-10-06 — Gated delete built (RunForFile/DeleteSource, Parse claim + status-outside-transaction fix, retired names, `released` status); open cutover items (mhammontree)
|
|
121
120
|
- 2026-09-29 — Activation plan: gated-delete decision, proposed RunForFile/DeleteSource design, CronJobs rows set isActive=0 (mhammontree)
|
|
@@ -3,18 +3,20 @@ title: Office Depot
|
|
|
3
3
|
framework: "2.0"
|
|
4
4
|
apps:
|
|
5
5
|
- voice-to-voice
|
|
6
|
+
- toga
|
|
6
7
|
project: TOGa Voice
|
|
7
8
|
client: office-depot
|
|
8
9
|
type: profile
|
|
9
10
|
status: active
|
|
10
|
-
updated: 2026-
|
|
11
|
-
owners: [akhokhani]
|
|
11
|
+
updated: 2026-10-06
|
|
12
|
+
owners: [akhokhani, mhammontree]
|
|
12
13
|
files: []
|
|
13
14
|
related:
|
|
14
15
|
- features/odp-tech-support.md
|
|
15
16
|
- ../../2.0/apps/voice-to-voice/architecture.md
|
|
16
17
|
- ../../2.0/apps/voice-to-voice/features/ticket-api-integration.md
|
|
17
18
|
- ../../1.0/apps/togadesk/architecture.md
|
|
19
|
+
- ../../1.0/apps/toga/features/odp-esd-mcafee-descriptions.md
|
|
18
20
|
---
|
|
19
21
|
|
|
20
22
|
Office Depot — first TOGa Voice (`voice-to-voice`) tenant: inbound phone tech-support for ODP store associates writing tickets to TOGa Desk 1.0 via the Agilant Ticket API; open for ODP voice config, identifiers, and call flow.
|
package/package.json
CHANGED