toga-ai 1.0.84 → 1.0.85
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.
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# webhook (Webhook) — 1.0 knowledge
|
|
2
|
+
|
|
3
|
+
| Doc | Summary | Files |
|
|
4
|
+
|-----|---------|-------|
|
|
5
|
+
| [NetSuite → ClickUp Opportunity Sync](features/netsuite-clickup-opportunity-sync.md) | NetSuite Opportunities are pushed into the ClickUp **Opportunities** list (list id `901111987449`, in the Opportunity/RFP Hub space `90113928591`) as tasks name | webhook/_/webhook/netsuite.php, webhook/api.php, api2/Webhook/Netsuite.php, worker2/Worker/Netsuite.php, api2/Controller/Index.php |
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: NetSuite → ClickUp Opportunity Sync
|
|
3
|
+
framework: "1.0"
|
|
4
|
+
repo: webhook
|
|
5
|
+
project: Webhook
|
|
6
|
+
client: shared
|
|
7
|
+
type: feature
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-06-15
|
|
10
|
+
owners: ["dfranks"]
|
|
11
|
+
files:
|
|
12
|
+
- webhook/_/webhook/netsuite.php
|
|
13
|
+
- webhook/api.php
|
|
14
|
+
- api2/Webhook/Netsuite.php
|
|
15
|
+
- worker2/Worker/Netsuite.php
|
|
16
|
+
- api2/Controller/Index.php
|
|
17
|
+
related: []
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Summary
|
|
21
|
+
NetSuite Opportunities are pushed into the ClickUp **Opportunities** list (list id `901111987449`,
|
|
22
|
+
in the Opportunity/RFP Hub space `90113928591`) as tasks named `<oppNumber> — <customerNumber>
|
|
23
|
+
<customer> — <title>` (e.g. `60533 — 560 Endeavor Health — Data Center Facility Consolidation
|
|
24
|
+
Services`). The trigger and the entire task payload are **built on the NetSuite side**; TOGA only
|
|
25
|
+
relays the payload to the ClickUp API verbatim.
|
|
26
|
+
|
|
27
|
+
## Key files / entry points
|
|
28
|
+
- **Live receiver:** `webhook/_/webhook/netsuite.php` → `Webhook_NetSuite::post()` → `createTask()`,
|
|
29
|
+
reached at `https://webhook.togahub.com/netsuite` and routed by `webhook/api.php` (the legacy
|
|
30
|
+
PHP 7.2 / `App_` webhook project). This is the path NetSuite actually hits.
|
|
31
|
+
- **Inactive copies (triplicated, identical relay logic):** `api2/Webhook/Netsuite.php`
|
|
32
|
+
(`_Webhook_NetSuite::post`) and `worker2/Worker/Netsuite.php` (`_Worker_NetSuite::Webhook`).
|
|
33
|
+
The api2 webhook route (`Controller/Index.php`, `case 'webhook'`) logs inbound payloads to
|
|
34
|
+
`Logs.Api`; the worker2 Lambda path logs to `Logs.Webhook`. **Neither shows any `/netsuite`
|
|
35
|
+
traffic** — confirming the legacy `webhook/` project is the live receiver, not api2/worker2.
|
|
36
|
+
- The ClickUp call uses a token carried in the inbound payload (`$body->token`); in production
|
|
37
|
+
that token belongs to `dfranks@togatech.com`, so all integration-created tasks show that creator.
|
|
38
|
+
|
|
39
|
+
## How it works
|
|
40
|
+
1. A NetSuite event/process POSTs a JSON body to `webhook.togahub.com/netsuite`.
|
|
41
|
+
2. `createTask()` resolves the ClickUp user id for `$body->presalesLead` (cached in the client DB
|
|
42
|
+
`Users.c_clickupUserIdentifier`, else fetched from the ClickUp `/team` members list).
|
|
43
|
+
3. It POSTs a new task to `list/901111987449/task` with `name => $body->name` **verbatim**,
|
|
44
|
+
`description => $body->description`, and custom fields for sales rep / presales email / presales
|
|
45
|
+
user id / opportunity number / customer number.
|
|
46
|
+
|
|
47
|
+
There are (at least) two NetSuite-side triggers feeding this one webhook:
|
|
48
|
+
- **Real-time** UserEventScript on the Opportunity "Presales Lead" field
|
|
49
|
+
(`custbody_ctc_solution_architect`, employee ref) — fires on empty→set and posts a fully-populated
|
|
50
|
+
payload. Produces correctly-named tasks. Verified 2026-06-15: touching one opp via REST PATCH
|
|
51
|
+
(an `xedit`) produced the correct `60533 — 560 Endeavor Health — …` task.
|
|
52
|
+
- **A scheduled/batch process** (runs ~:01 past the hour) — source of the degenerate tasks below.
|
|
53
|
+
|
|
54
|
+
## Data model
|
|
55
|
+
- ClickUp Opportunities list `901111987449`; custom-item id `1009`.
|
|
56
|
+
- Custom field UUIDs: SALES_REP `f2bf421f-e24c-4e1c-bea4-98a227abe087`, PRESALES_EMAIL
|
|
57
|
+
`440e2f9c-07bc-482b-9bf1-39b0e673b989`, PRESALES_USER_ID `b755ca44-7d7f-4e4b-9b93-6ee95d0ea8da`,
|
|
58
|
+
OPPORTUNITY_NUMBER `a5529cdc-8dbb-4165-8bc5-9f5cc691796a`, CUSTOMER_NUMBER `170dc118-b3fa-413b-826b-2753e9405851`.
|
|
59
|
+
- Client DB `Users` table caches `c_clickupUserIdentifier` by email.
|
|
60
|
+
|
|
61
|
+
## Client variations
|
|
62
|
+
None — single internal Agilant/True integration.
|
|
63
|
+
|
|
64
|
+
## Gotchas / known issues
|
|
65
|
+
- **`OPP <internalId>` degenerate tasks (root cause).** Occasionally a task is named just
|
|
66
|
+
`OPP 7147699` with no description/fields. The name is built entirely by NetSuite; TOGA relays it.
|
|
67
|
+
The opportunities involved are **fully populated in NetSuite** (verified via SuiteQL — `OPP 7147699`
|
|
68
|
+
is internal id 7147699 = tranid 74197, "7904 Froedtert South", "Seal Shield Opportunity Assessment"),
|
|
69
|
+
so this is **not** missing data and **not** a TOGA bug — a NetSuite-side process sent a fallback
|
|
70
|
+
payload (`name = "OPP " + record.id`, descriptive fields empty) without loading `tranid`/`entity`/
|
|
71
|
+
`title`. The four observed (Jun 2026) all created at ~:01 past the hour by the dfranks token →
|
|
72
|
+
a NetSuite **scheduled** script, distinct from the working real-time presales-lead trigger
|
|
73
|
+
(~3% failure: 4 degenerate vs 122 correct from the same token). Fix is NetSuite-side
|
|
74
|
+
(load the record / saved-search columns before building the name); the offending script lives in
|
|
75
|
+
the NetSuite File Cabinet, not this repo. Optional TOGA backstop: in `createTask()`, if `name` is
|
|
76
|
+
empty or matches `^OPP \d+$`, look the opp up by internal id and rebuild the name before POSTing.
|
|
77
|
+
- **No inbound logging.** `Webhook_NetSuite::post()` has a `// Log payload to file` comment but does
|
|
78
|
+
**nothing** — the raw NetSuite payload is persisted nowhere, which is why this was hard to trace.
|
|
79
|
+
Adding real request logging here would make recurrences diagnosable immediately.
|
|
80
|
+
- **Opp#/Cust# fields swapped (separate bug, all copies).** `OPPORTUNITY_NUMBER` custom field is set
|
|
81
|
+
from `$body->customerNumber` and `CUSTOMER_NUMBER` from `$body->opportunityNumber`
|
|
82
|
+
(e.g. api2 `Netsuite.php` lines 116–122).
|
|
83
|
+
- Handler is triplicated; a fix must be applied to the live `webhook/` copy (and ideally the others
|
|
84
|
+
to avoid drift).
|
|
85
|
+
|
|
86
|
+
## Change history
|
|
87
|
+
- 2026-06-15 — Documented integration + root-caused `OPP <internalId>` degenerate tasks to a NetSuite
|
|
88
|
+
scheduled (~:01 hourly) fallback payload; confirmed live receiver is `webhook/`, not api2/worker2;
|
|
89
|
+
noted no-op inbound logging and the Opp#/Cust# swap. (dfranks)
|
|
90
|
+
|
|
91
|
+
## Related docs
|
|
92
|
+
- `test/@dave/touch_opportunity_presales_lead.php` re-fires the real-time presales-lead trigger
|
|
93
|
+
(blank→restore `custbody_ctc_solution_architect`).
|
package/knowledge/INDEX.md
CHANGED
|
@@ -8,6 +8,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
|
|
|
8
8
|
- **worker** (Worker) — 4 doc(s) → [1.0/apps/worker/INDEX.md](1.0/apps/worker/INDEX.md)
|
|
9
9
|
- **togadesk** (TOGa Desk) — 7 doc(s) → [1.0/apps/togadesk/INDEX.md](1.0/apps/togadesk/INDEX.md)
|
|
10
10
|
- **togaview** (TOGa View) — 5 doc(s) → [1.0/apps/togaview/INDEX.md](1.0/apps/togaview/INDEX.md)
|
|
11
|
+
- **webhook** (Webhook) — 1 doc(s) → [1.0/apps/webhook/INDEX.md](1.0/apps/webhook/INDEX.md)
|
|
11
12
|
|
|
12
13
|
## 2.0 framework
|
|
13
14
|
|
package/knowledge/registry.json
CHANGED
|
@@ -11,6 +11,6 @@
|
|
|
11
11
|
{ "repo": "togadesk", "project": "TOGa Desk", "framework": "1.0", "role": "app", "dependsOn": [] },
|
|
12
12
|
{ "repo": "togaview", "project": "TOGa View", "framework": "1.0", "role": "app", "dependsOn": [] },
|
|
13
13
|
{ "repo": "toga2-hub", "project": "TOGa Hub", "framework": "2.0", "role": "app", "dependsOn": ["api2"] },
|
|
14
|
-
{ "repo": "togatech", "project": "TOGA Technology Website", "framework": "standalone", "role": "app", "dependsOn": [] }
|
|
15
|
-
|
|
14
|
+
{ "repo": "togatech", "project": "TOGA Technology Website", "framework": "standalone", "role": "app", "dependsOn": [] },
|
|
15
|
+
{ "repo": "webhook", "project": "Webhook", "framework": "1.0", "role": "app", "dependsOn": ["library"] }
|
|
16
16
|
]
|
package/package.json
CHANGED