toga-ai 1.0.109 → 1.0.110
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.
|
@@ -75,7 +75,24 @@ second, independently-gated concern in the same handler.
|
|
|
75
75
|
`_Worker::runTask('Netsuite/Opportunity/<verb>', {internalId})`.
|
|
76
76
|
5. **Handle (worker2):** `_Worker_Netsuite_Opportunity` fetches the record from NetSuite by id
|
|
77
77
|
and upserts it into `Forecast.Opportunities` (+ `OpportunityItems`), and — only when a
|
|
78
|
-
Presales Lead is set — creates the ClickUp opportunity task.
|
|
78
|
+
Presales Lead is set — creates the ClickUp opportunity task. **Both `POST` (create) and `PUT`
|
|
79
|
+
(edit) create the task** (since 2026-06-16); `DELETE` only removes from Forecast.
|
|
80
|
+
|
|
81
|
+
## ClickUp opportunity task
|
|
82
|
+
|
|
83
|
+
Created by `maybeCreateClickupTask()` → `createTask()` (ported verbatim from the legacy
|
|
84
|
+
`webhook/` handler), gated on a **Presales Lead** (`custbody_ctc_solution_architect` employee →
|
|
85
|
+
email; empty email = skip). Posts to list `901111987449` with `custom_item_id` = `1009`.
|
|
86
|
+
|
|
87
|
+
- **Task name** = `{opportunityNumber} — {customer} — {title}`, e.g.
|
|
88
|
+
`60533 — 560 Endeavor Health — Data Center Facility Consolidation Services` (empty parts dropped).
|
|
89
|
+
- **Custom-field value mapping** (the non-obvious part — these were swapped before 2026-06-16):
|
|
90
|
+
`Opportunity #` (`a5529cdc-…`) ← `tranId`; `Customer #` (`170dc118-…`) ← `entity->refName`
|
|
91
|
+
(the customer **name**, deliberately — not the NetSuite customer number). Plus `Sales Rep`,
|
|
92
|
+
`Presales Lead Email`, and `Presales Lead` (users field, resolved via a cached
|
|
93
|
+
`Client_True.Users.c_clickupUserIdentifier` lookup, falling back to a `GET /team` scan).
|
|
94
|
+
- The ClickUp token comes from `[clickup] token` in the worker2 config (legacy webhook received
|
|
95
|
+
it on the payload; the new contract drops it).
|
|
79
96
|
|
|
80
97
|
## Data model
|
|
81
98
|
|
|
@@ -128,7 +145,26 @@ None — platform-wide Forecast sync.
|
|
|
128
145
|
- **No WebhookIngestion Lambda locally.** Dev points the enqueuer at an ngrok tunnel to local
|
|
129
146
|
worker2 via the `DEV_OVERRIDE` block, which also wraps the body in worker2's legacy
|
|
130
147
|
`{action,parameters}` envelope (since there's no Lambda to convert `/netsuite` → an action).
|
|
131
|
-
|
|
148
|
+
- **`debugWrap` is the dev/prod body-shape switch — not just the URL.** `debugWrap=true` (dev)
|
|
149
|
+
nests the raw `{recordType,internalId,…}` contract inside worker2's legacy `{action,parameters}`
|
|
150
|
+
envelope (`action='Netsuite/Webhook'`); the local `worker()` legacy path needs this because
|
|
151
|
+
there's no Lambda. `debugWrap=false` (prod) sends the raw contract — the WebhookIngestion Lambda
|
|
152
|
+
derives the `Netsuite/Webhook` action from the `/netsuite` URL path itself. Changing only the
|
|
153
|
+
endpoint to prod while leaving `debugWrap` on double-wraps the body and breaks the handler.
|
|
154
|
+
- **Prod cutover: flip `DEV_OVERRIDE.enabled=false` — do NOT comment out the block.** `getConfig()`
|
|
155
|
+
reads `DEV_OVERRIDE.enabled/.endpoint/.debugWrap`; deleting the `const` throws `ReferenceError`,
|
|
156
|
+
which `afterSubmit`'s catch swallows as `AMQ enqueue FAILED` → **no row enqueued, sync silently
|
|
157
|
+
stops.** Flipping `enabled=false` makes `getConfig()` fall through to `DEFAULTS.endpoint`
|
|
158
|
+
(`https://webhook.togahub.com/netsuite`) with `debugWrap` off. Also flip the enqueuer deployment
|
|
159
|
+
`Testing → Released` (Testing fires only for the deploying user). Full checklist in
|
|
160
|
+
`DEPLOY_RUNBOOK.md` §6.
|
|
161
|
+
- **No ClickUp dedup (deferred).** `maybeCreateClickupTask()` only gates on the Presales Lead — it
|
|
162
|
+
does **not** check whether a task already exists. Since both POST and PUT now create, **every edit
|
|
163
|
+
of an opportunity with a Presales Lead creates a NEW ClickUp task** (and the NetSuite-side
|
|
164
|
+
enqueuer fires on every save). Before this hits production traffic, add dedup — recommended:
|
|
165
|
+
store the created ClickUp task id on the `Forecast.Opportunities` row and skip when present.
|
|
166
|
+
Until 2026-06-16 PUT skipped ClickUp entirely, which masked this (an edit produced no duplicate
|
|
167
|
+
only because the edit path didn't create at all).
|
|
132
168
|
- **NetSuite doubled-prefix ids.** The queue record and its fields were created with the full
|
|
133
169
|
custom prefix typed into the ID box, so the real ids are doubled:
|
|
134
170
|
type `customrecordcustomrecord_api_msg_queue`, fields `custrecordcustrecord_amq_*`. The
|
|
@@ -142,6 +178,11 @@ None — platform-wide Forecast sync.
|
|
|
142
178
|
(`Created`,`Pending`,`Retry`,`Sending`) — omitting `Created` silently matches nothing (`candidates:0`).
|
|
143
179
|
|
|
144
180
|
## Change history
|
|
181
|
+
- 2026-06-16 — ClickUp parity hardening (TRUE-79182): verified the `Opportunity #`/`Customer #`
|
|
182
|
+
custom fields exist on list 901111987449 and **fixed their swapped values**; `PUT` now also
|
|
183
|
+
creates the ClickUp task (was POST-only); task name reformatted to
|
|
184
|
+
`{opp#} — {customer} — {title}`; `createTask()` made private + generic `Exception` throws
|
|
185
|
+
narrowed to `RuntimeException`. Dedup still deferred (see gotcha). (dfranks)
|
|
145
186
|
- 2026-06-16 — Trigger correction: the immediate trigger moved INTO the enqueuer (`task.create`
|
|
146
187
|
the drainer) after discovering a UE can't trigger a UE — `ue_amq_drain` retired. `task.create`
|
|
147
188
|
needs a `Not Scheduled` deployment of `ss_amq_drain` (else `NO_DEPLOYMENTS_AVAILABLE`); submit by
|
package/package.json
CHANGED