@ingenx-io/valets-schema-mcp-server 0.1.5 → 0.1.7

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.
Files changed (55) hide show
  1. package/data/docs/enums/attention-status.md +1 -1
  2. package/data/docs/enums/booking-status.md +1 -1
  3. package/data/docs/enums/customer-payment-status.md +1 -1
  4. package/data/docs/enums/customer-payment-target-type.md +1 -1
  5. package/data/docs/enums/delivery-type.md +1 -1
  6. package/data/docs/enums/deployment-link-type.md +1 -1
  7. package/data/docs/enums/event-status.md +1 -1
  8. package/data/docs/enums/fulfillment-status.md +1 -1
  9. package/data/docs/enums/loyalty-transaction-type.md +1 -1
  10. package/data/docs/enums/order-status.md +1 -1
  11. package/data/docs/enums/payment-method.md +1 -1
  12. package/data/docs/enums/payment-proof-status.md +1 -1
  13. package/data/docs/enums/payment-status.md +1 -1
  14. package/data/docs/enums/pending-issue.md +1 -1
  15. package/data/docs/enums/return-status.md +1 -1
  16. package/data/docs/enums/session-status.md +1 -1
  17. package/data/docs/enums/site-status.md +1 -1
  18. package/data/docs/enums/stocktake-frequency.md +24 -0
  19. package/data/docs/enums/stocktake-item-status.md +24 -0
  20. package/data/docs/enums/stocktake-status.md +24 -0
  21. package/data/docs/enums/ticket-status.md +2 -2
  22. package/data/docs/enums/waba-label.md +22 -0
  23. package/data/docs/index.md +9 -2
  24. package/data/docs/models/allowed-user.md +1 -1
  25. package/data/docs/models/analytics-backfill.md +1 -1
  26. package/data/docs/models/analytics-daily.md +1 -1
  27. package/data/docs/models/analytics-event.md +1 -1
  28. package/data/docs/models/analytics-hourly.md +1 -1
  29. package/data/docs/models/booking-version.md +1 -1
  30. package/data/docs/models/booking.md +1 -1
  31. package/data/docs/models/customer-payment-allocation.md +1 -1
  32. package/data/docs/models/customer-payment.md +1 -1
  33. package/data/docs/models/customer.md +1 -1
  34. package/data/docs/models/event.md +1 -1
  35. package/data/docs/models/loyalty-config.md +1 -1
  36. package/data/docs/models/loyalty-reward.md +1 -1
  37. package/data/docs/models/loyalty-status.md +1 -1
  38. package/data/docs/models/loyalty-transaction.md +1 -1
  39. package/data/docs/models/magic-link-request.md +1 -1
  40. package/data/docs/models/metrics-current.md +1 -1
  41. package/data/docs/models/metrics-daily.md +1 -1
  42. package/data/docs/models/metrics-monthly.md +1 -1
  43. package/data/docs/models/order-item.md +1 -1
  44. package/data/docs/models/order.md +1 -1
  45. package/data/docs/models/sale.md +1 -1
  46. package/data/docs/models/site-payment.md +1 -1
  47. package/data/docs/models/site.md +1 -1
  48. package/data/docs/models/stocktake-item.md +500 -0
  49. package/data/docs/models/stocktake.md +649 -0
  50. package/data/docs/models/ticket.md +2 -2
  51. package/data/docs/models/whatsapp-inbound-message.md +369 -0
  52. package/data/static/llms.txt +153 -1
  53. package/data/static/openapi.yaml +489 -0
  54. package/data/static/schemas.json +611 -1
  55. package/package.json +1 -1
@@ -0,0 +1,369 @@
1
+ ---
2
+ title: "WhatsappInboundMessage"
3
+ sidebar_label: "WhatsappInboundMessage"
4
+ sidebar_position: 28
5
+ ---
6
+
7
+ # WhatsappInboundMessage
8
+
9
+ <details>
10
+ <summary>Example JSON</summary>
11
+
12
+ ```json
13
+ {
14
+ "id": null,
15
+ "wabaId": "wab_ref123",
16
+ "waba": "waba",
17
+ "messageId": "mes_ref123",
18
+ "from": "from",
19
+ "type": "phone",
20
+ "timestamp": "timestamp",
21
+ "receivedAt": "receivedAt",
22
+ "text": null,
23
+ "mediaId": null,
24
+ "caption": null,
25
+ "storageUrl": null,
26
+ "context": null
27
+ }
28
+ ```
29
+
30
+ </details>
31
+
32
+
33
+ - [1. Property `id`](#id)
34
+ - [2. Property `wabaId`](#wabaId)
35
+ - [3. Property `waba`](#waba)
36
+ - [4. Property `messageId`](#messageId)
37
+ - [5. Property `from`](#from)
38
+ - [6. Property `type`](#type)
39
+ - [6.1. Property `item 0`](#type_anyOf_i0)
40
+ - [6.2. Property `item 1`](#type_anyOf_i1)
41
+ - [7. Property `timestamp`](#timestamp)
42
+ - [7.1. Property `_seconds`](#timestamp__seconds)
43
+ - [7.2. Property `_nanoseconds`](#timestamp__nanoseconds)
44
+ - [8. Property `receivedAt`](#receivedAt)
45
+ - [8.1. Property `_seconds`](#timestamp__seconds)
46
+ - [8.2. Property `_nanoseconds`](#timestamp__nanoseconds)
47
+ - [9. Property `text`](#text)
48
+ - [10. Property `mediaId`](#mediaId)
49
+ - [11. Property `caption`](#caption)
50
+ - [12. Property `storageUrl`](#storageUrl)
51
+ - [13. Property `context`](#context)
52
+ - [13.1. Property `id`](#context_id)
53
+ - [13.2. Property `from`](#context_from)
54
+ - [13.3. Property `forwarded`](#context_forwarded)
55
+
56
+ | | |
57
+ | ------------------------- | -------------------------------------- |
58
+ | **Type** | `object` |
59
+ | **Required** | No |
60
+ | **Additional properties** | Not allowed |
61
+ | **Defined in** | #/definitions/whatsapp-inbound-message |
62
+
63
+ **Description:** WhatsappInboundMessage — inbound WhatsApp message persisted from Meta Cloud API webhook (GH#36). Collection: whatsapp_inbound_messages/\{docId\} in ratenplate project. Top-level scope: company resolution happens post-ingestion.
64
+
65
+ | Property | Pattern | Type | Deprecated | Definition | Title/Description |
66
+ | ---------------------------- | ------- | ---------------- | ---------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------- |
67
+ | - [id](#id ) | No | string or null | No | - | (Read-only) Firestore document ID — wamid from Meta Cloud API. |
68
+ | + [wabaId](#wabaId ) | No | string | No | - | (Immutable) Meta WABA ID identifying which business number received the message. |
69
+ | + [waba](#waba ) | No | enum (of string) | No | In #/definitions/waba-label | (Immutable) Human-readable WABA label (cmz \| val). See WabaLabel enum. |
70
+ | + [messageId](#messageId ) | No | string | No | - | (Immutable) WhatsApp message ID (wamid) returned by Meta — mirrors the document ID. |
71
+ | + [from](#from ) | No | string | No | - | (Immutable) Sender phone number in E.164 format. |
72
+ | + [type](#type ) | No | Combination | No | - | (Immutable) Meta message type. |
73
+ | + [timestamp](#timestamp ) | No | object | No | In #/definitions/firestore-timestamp | (Immutable) Message timestamp as reported by Meta. |
74
+ | + [receivedAt](#receivedAt ) | No | object | No | In #/definitions/firestore-timestamp | (Read-only) Server-side ingestion time set by the Cloud Function. |
75
+ | - [text](#text ) | No | string or null | No | - | Message body text. Present on type=text messages only. |
76
+ | - [mediaId](#mediaId ) | No | string or null | No | - | Meta media ID. Present on image, audio, video, document, sticker messages. |
77
+ | - [caption](#caption ) | No | string or null | No | - | Media caption text. Present when the sender included a caption. |
78
+ | - [storageUrl](#storageUrl ) | No | string or null | No | - | Durable Cloud Storage URL for the downloaded media binary. Present after the CF downloads and stores the media. |
79
+ | - [context](#context ) | No | object or null | No | - | Reply/forward context. Present on replies and forwarded messages. |
80
+
81
+ ## <a name="id"></a>1. Property `id`
82
+
83
+ | | |
84
+ | ------------ | ---------------- |
85
+ | **Type** | `string or null` |
86
+ | **Required** | No |
87
+
88
+ **Description:** (Read-only) Firestore document ID — wamid from Meta Cloud API.
89
+
90
+ :::warning Server-set
91
+ Do not include in write requests. This field is set exclusively by the server (Firestore trigger or Admin SDK). Clients that send it will have the value silently ignored or may receive a validation error.
92
+ :::
93
+
94
+ ## <a name="wabaId"></a>2. Property `wabaId`
95
+
96
+ | | |
97
+ | ------------ | -------- |
98
+ | **Type** | `string` |
99
+ | **Required** | Yes |
100
+
101
+ **Description:** (Immutable) Meta WABA ID identifying which business number received the message.
102
+
103
+ :::info Immutable
104
+ Set at creation only. This field cannot be modified after the document is created. Include it in CREATE payloads; omit it (or leave unchanged) in UPDATE payloads.
105
+ :::
106
+
107
+ ## <a name="waba"></a>3. Property `waba`
108
+
109
+ | | |
110
+ | -------------- | ------------------------ |
111
+ | **Type** | `enum (of string)` |
112
+ | **Required** | Yes |
113
+ | **Defined in** | #/definitions/waba-label |
114
+
115
+ **Description:** (Immutable) Human-readable WABA label (cmz | val). See WabaLabel enum.
116
+
117
+ Must be one of:
118
+ * "cmz"
119
+ * "val"
120
+
121
+ :::info Immutable
122
+ Set at creation only. This field cannot be modified after the document is created. Include it in CREATE payloads; omit it (or leave unchanged) in UPDATE payloads.
123
+ :::
124
+
125
+ ## <a name="messageId"></a>4. Property `messageId`
126
+
127
+ | | |
128
+ | ------------ | -------- |
129
+ | **Type** | `string` |
130
+ | **Required** | Yes |
131
+
132
+ **Description:** (Immutable) WhatsApp message ID (wamid) returned by Meta — mirrors the document ID.
133
+
134
+ :::info Immutable
135
+ Set at creation only. This field cannot be modified after the document is created. Include it in CREATE payloads; omit it (or leave unchanged) in UPDATE payloads.
136
+ :::
137
+
138
+ ## <a name="from"></a>5. Property `from`
139
+
140
+ | | |
141
+ | ------------ | -------- |
142
+ | **Type** | `string` |
143
+ | **Required** | Yes |
144
+
145
+ **Description:** (Immutable) Sender phone number in E.164 format.
146
+
147
+ :::info Immutable
148
+ Set at creation only. This field cannot be modified after the document is created. Include it in CREATE payloads; omit it (or leave unchanged) in UPDATE payloads.
149
+ :::
150
+
151
+ ## <a name="type"></a>6. Property `type`
152
+
153
+ | | |
154
+ | ------------------------- | ---------------- |
155
+ | **Type** | `combining` |
156
+ | **Required** | Yes |
157
+ | **Additional properties** | Any type allowed |
158
+
159
+ **Description:** (Immutable) Meta message type.
160
+
161
+ | Any of(Option) |
162
+ | ------------------------ |
163
+ | [item 0](#type_anyOf_i0) |
164
+ | [item 1](#type_anyOf_i1) |
165
+
166
+ ### <a name="type_anyOf_i0"></a>6.1. Property `item 0`
167
+
168
+ | | |
169
+ | ------------ | ------------------ |
170
+ | **Type** | `enum (of string)` |
171
+ | **Required** | No |
172
+
173
+ Must be one of:
174
+ * "text"
175
+ * "image"
176
+ * "audio"
177
+ * "video"
178
+ * "document"
179
+ * "sticker"
180
+ * "reaction"
181
+ * "location"
182
+ * "contacts"
183
+ * "interactive"
184
+ * "button"
185
+ * "order"
186
+ * "system"
187
+ * "unsupported"
188
+
189
+ ### <a name="type_anyOf_i1"></a>6.2. Property `item 1`
190
+
191
+ | | |
192
+ | ------------ | -------- |
193
+ | **Type** | `string` |
194
+ | **Required** | No |
195
+
196
+ :::info Immutable
197
+ Set at creation only. This field cannot be modified after the document is created. Include it in CREATE payloads; omit it (or leave unchanged) in UPDATE payloads.
198
+ :::
199
+
200
+ ## <a name="timestamp"></a>7. Property `timestamp`
201
+
202
+ | | |
203
+ | ------------------------- | --------------------------------- |
204
+ | **Type** | `object` |
205
+ | **Required** | Yes |
206
+ | **Additional properties** | Not allowed |
207
+ | **Defined in** | #/definitions/firestore-timestamp |
208
+
209
+ **Description:** (Immutable) Message timestamp as reported by Meta.
210
+
211
+ | Property | Pattern | Type | Deprecated | Definition | Title/Description |
212
+ | ------------------------------------------ | ------- | ------- | ---------- | ---------- | ----------------- |
213
+ | + [_seconds](#timestamp__seconds ) | No | integer | No | - | - |
214
+ | + [_nanoseconds](#timestamp__nanoseconds ) | No | integer | No | - | - |
215
+
216
+ ### <a name="timestamp__seconds"></a>7.1. Property `_seconds`
217
+
218
+ | | |
219
+ | ------------ | --------- |
220
+ | **Type** | `integer` |
221
+ | **Required** | Yes |
222
+
223
+ | Restrictions | |
224
+ | ------------ | ---------------------- |
225
+ | **Minimum** | &ge; -9007199254740991 |
226
+ | **Maximum** | &le; 9007199254740991 |
227
+
228
+ ### <a name="timestamp__nanoseconds"></a>7.2. Property `_nanoseconds`
229
+
230
+ | | |
231
+ | ------------ | --------- |
232
+ | **Type** | `integer` |
233
+ | **Required** | Yes |
234
+
235
+ | Restrictions | |
236
+ | ------------ | ---------------------- |
237
+ | **Minimum** | &ge; -9007199254740991 |
238
+ | **Maximum** | &le; 9007199254740991 |
239
+
240
+ :::info Immutable
241
+ Set at creation only. This field cannot be modified after the document is created. Include it in CREATE payloads; omit it (or leave unchanged) in UPDATE payloads.
242
+ :::
243
+
244
+ ## <a name="receivedAt"></a>8. Property `receivedAt`
245
+
246
+ | | |
247
+ | ------------------------- | --------------------------------- |
248
+ | **Type** | `object` |
249
+ | **Required** | Yes |
250
+ | **Additional properties** | Not allowed |
251
+ | **Defined in** | #/definitions/firestore-timestamp |
252
+
253
+ **Description:** (Read-only) Server-side ingestion time set by the Cloud Function.
254
+
255
+ | Property | Pattern | Type | Deprecated | Definition | Title/Description |
256
+ | ------------------------------------------ | ------- | ------- | ---------- | ---------- | ----------------- |
257
+ | + [_seconds](#timestamp__seconds ) | No | integer | No | - | - |
258
+ | + [_nanoseconds](#timestamp__nanoseconds ) | No | integer | No | - | - |
259
+
260
+ ### <a name="timestamp__seconds"></a>8.1. Property `_seconds`
261
+
262
+ | | |
263
+ | ------------ | --------- |
264
+ | **Type** | `integer` |
265
+ | **Required** | Yes |
266
+
267
+ | Restrictions | |
268
+ | ------------ | ---------------------- |
269
+ | **Minimum** | &ge; -9007199254740991 |
270
+ | **Maximum** | &le; 9007199254740991 |
271
+
272
+ ### <a name="timestamp__nanoseconds"></a>8.2. Property `_nanoseconds`
273
+
274
+ | | |
275
+ | ------------ | --------- |
276
+ | **Type** | `integer` |
277
+ | **Required** | Yes |
278
+
279
+ | Restrictions | |
280
+ | ------------ | ---------------------- |
281
+ | **Minimum** | &ge; -9007199254740991 |
282
+ | **Maximum** | &le; 9007199254740991 |
283
+
284
+ :::warning Server-set
285
+ Do not include in write requests. This field is set exclusively by the server (Firestore trigger or Admin SDK). Clients that send it will have the value silently ignored or may receive a validation error.
286
+ :::
287
+
288
+ ## <a name="text"></a>9. Property `text`
289
+
290
+ | | |
291
+ | ------------ | ---------------- |
292
+ | **Type** | `string or null` |
293
+ | **Required** | No |
294
+
295
+ **Description:** Message body text. Present on type=text messages only.
296
+
297
+ ## <a name="mediaId"></a>10. Property `mediaId`
298
+
299
+ | | |
300
+ | ------------ | ---------------- |
301
+ | **Type** | `string or null` |
302
+ | **Required** | No |
303
+
304
+ **Description:** Meta media ID. Present on image, audio, video, document, sticker messages.
305
+
306
+ ## <a name="caption"></a>11. Property `caption`
307
+
308
+ | | |
309
+ | ------------ | ---------------- |
310
+ | **Type** | `string or null` |
311
+ | **Required** | No |
312
+
313
+ **Description:** Media caption text. Present when the sender included a caption.
314
+
315
+ ## <a name="storageUrl"></a>12. Property `storageUrl`
316
+
317
+ | | |
318
+ | ------------ | ---------------- |
319
+ | **Type** | `string or null` |
320
+ | **Required** | No |
321
+
322
+ **Description:** Durable Cloud Storage URL for the downloaded media binary. Present after the CF downloads and stores the media.
323
+
324
+ ## <a name="context"></a>13. Property `context`
325
+
326
+ | | |
327
+ | ------------ | ---------------- |
328
+ | **Type** | `object or null` |
329
+ | **Required** | No |
330
+
331
+ **Description:** Reply/forward context. Present on replies and forwarded messages.
332
+
333
+ | Property | Pattern | Type | Deprecated | Definition | Title/Description |
334
+ | ---------------------------------- | ------- | ------ | ---------- | ---------- | -------------------------------------------------------- |
335
+ | - [id](#context_id ) | No | string | No | - | wamid of the quoted/replied-to message. |
336
+ | - [from](#context_from ) | No | string | No | - | Sender phone number of the quoted message. |
337
+ | - [forwarded](#context_forwarded ) | No | const | No | - | Present (true) when Meta marks the message as forwarded. |
338
+
339
+ ### <a name="context_id"></a>13.1. Property `id`
340
+
341
+ | | |
342
+ | ------------ | -------- |
343
+ | **Type** | `string` |
344
+ | **Required** | No |
345
+
346
+ **Description:** wamid of the quoted/replied-to message.
347
+
348
+ ### <a name="context_from"></a>13.2. Property `from`
349
+
350
+ | | |
351
+ | ------------ | -------- |
352
+ | **Type** | `string` |
353
+ | **Required** | No |
354
+
355
+ **Description:** Sender phone number of the quoted message.
356
+
357
+ ### <a name="context_forwarded"></a>13.3. Property `forwarded`
358
+
359
+ | | |
360
+ | ------------ | ------- |
361
+ | **Type** | `const` |
362
+ | **Required** | No |
363
+
364
+ **Description:** Present (true) when Meta marks the message as forwarded.
365
+
366
+ Specific value: `true`
367
+
368
+ ----------------------------------------------------------------------------------------------------------------------------
369
+ Generated using [json-schema-for-humans](https://github.com/coveooss/json-schema-for-humans) on 2026-05-15 at 16:32:39 +0000
@@ -4,7 +4,7 @@
4
4
  > Source of truth: Zod schemas in packages/schema/src/
5
5
  > All Firestore documents are scoped under companies/{companyId}/
6
6
 
7
- > Generated: 2026-04-18
7
+ > Generated: 2026-05-15
8
8
 
9
9
  ---
10
10
 
@@ -78,10 +78,26 @@ Values: PENDING, CONFIRMED, CANCELLATION_REQUESTED, COMPLETED, NO_SHOW, CANCELLE
78
78
  Lifecycle status for a Site (D41). Drives whether the site is reachable and whether analytics/payments flow.
79
79
  Values: ACTIVE, INACTIVE, EXPIRED, ARCHIVED
80
80
 
81
+ ### StocktakeFrequency
82
+ Recurrence cadence of a Stocktake session (GH#29 §4).
83
+ Values: DAILY, WEEKLY, MONTHLY, AD_HOC
84
+
85
+ ### StocktakeItemStatus
86
+ Per-line workflow status inside a Stocktake (GH#29 §4, audit Q21).
87
+ Values: PENDING, COUNTED, VERIFIED, ADJUSTED
88
+
89
+ ### StocktakeStatus
90
+ Lifecycle status of a Stocktake session (GH#29 §3, §4).
91
+ Values: PENDING, IN_PROGRESS, COMPLETED, CANCELLED
92
+
81
93
  ### TicketStatus
82
94
  Event ticket status (D32). VALID = active and unused.
83
95
  Values: VALID, USED, CANCELLED
84
96
 
97
+ ### WabaLabel
98
+ Human-readable WABA label identifying which Meta business number received the message (GH#36).
99
+ Values: cmz, val
100
+
85
101
  ---
86
102
 
87
103
  ## Models
@@ -1314,6 +1330,104 @@ Example:
1314
1330
  }
1315
1331
  ```
1316
1332
 
1333
+ ### Stocktake
1334
+ Fields: 21 (11 required)
1335
+
1336
+ | Field | Type | Required | Description |
1337
+ |-------|------|----------|-------------|
1338
+ | id | ['string', 'null'] | no | (Read-only) Firestore document ID, auto-generated. |
1339
+ | companyId | string | yes | (Immutable) FK → Company document ID. Tenant scope. |
1340
+ | stocktakeNumber | string | yes | Human-readable session number, e.g. "STK-2026-001". Embedded as `referenceNumber` on the StockMovement rows the session emits, so the ledger remains traceable to the originating stocktake. |
1341
+ | stocktakeDate | FirestoreTimestamp | yes | Effective date of the count. Distinct from createdAt; can be backdated. |
1342
+ | warehouseId | any | no | FK → Warehouse document ID. Null = whole-company stocktake (no warehouse partition). |
1343
+ | frequency | any | no | Recurrence cadence. Optional — leave unset for ad-hoc sessions, or set to indicate this stocktake is part of a recurring schedule. |
1344
+ | scheduledStocktakeId | any | no | FK to a recurring stocktake schedule, if this session was emitted from one. Null for ad-hoc sessions. |
1345
+ | status | StocktakeStatus | yes | Lifecycle status. Transitions PENDING → IN_PROGRESS → COMPLETED are server-owned (GH#29 §3 / Q25). |
1346
+ | adjustmentsApplied | boolean | yes | True if completing the session actually emitted StockMovement adjustments. False for record-only counts. |
1347
+ | notes | any | no | Free-text session-level notes. |
1348
+ | totalItemsCount | integer | yes | (Read-only) Total number of StocktakeItem rows under this session. |
1349
+ | totalDiscrepancies | integer | yes | (Read-only) Sum of absolute deltas across counted items. |
1350
+ | totalDeltaValue | number | yes | (Read-only) Net valuation impact of the count, in XOF integer minor units. |
1351
+ | startedAt | FirestoreTimestamp | yes | When the counting session physically opened. Typically equal to createdAt for ad-hoc sessions. |
1352
+ | completedAt | any | no | (Read-only) When the session transitioned to COMPLETED. |
1353
+ | createdAt | any | no | (Read-only) Server-generated creation timestamp. |
1354
+ | createdBy | string | yes | (Immutable) FK → User UID who created the session. |
1355
+ | createdByName | string | yes | (Denormalized) Snapshot of the creator's display name at session creation. |
1356
+ | completedBy | any | no | (Read-only) FK → User UID who completed the session, set by server on COMPLETED. |
1357
+ | completedByName | any | no | (Denormalized) Snapshot of the completer's display name. |
1358
+ | updatedAt | any | no | (Read-only) Server-generated update timestamp. |
1359
+
1360
+ Example:
1361
+ ```json
1362
+ {
1363
+ "id": null,
1364
+ "companyId": "comp_xyz789",
1365
+ "stocktakeNumber": "stocktakeNumber",
1366
+ "stocktakeDate": "stocktakeDate",
1367
+ "warehouseId": "war_ref123",
1368
+ "frequency": "frequency",
1369
+ "scheduledStocktakeId": "sch_ref123",
1370
+ "status": "status",
1371
+ "adjustmentsApplied": true,
1372
+ "notes": "VIP customer, handle with care",
1373
+ "totalItemsCount": 2,
1374
+ "totalDiscrepancies": 0,
1375
+ "totalDeltaValue": 0,
1376
+ "startedAt": "startedAt",
1377
+ "completedAt": "completedAt",
1378
+ "createdAt": "createdAt",
1379
+ "createdBy": "staff_k0f1",
1380
+ "createdByName": "Kofi Mensah",
1381
+ "completedBy": "completedBy",
1382
+ "completedByName": "completedByName",
1383
+ "updatedAt": "updatedAt"
1384
+ }
1385
+ ```
1386
+
1387
+ ### StocktakeItem
1388
+ Fields: 16 (8 required)
1389
+
1390
+ | Field | Type | Required | Description |
1391
+ |-------|------|----------|-------------|
1392
+ | stockItemId | string | yes | FK → StockItem document ID. Doubles as the item document ID. |
1393
+ | stockItemName | string | yes | (Denormalized) Snapshot of StockItem.name at session time. |
1394
+ | theoreticalQuantity | number | yes | (Immutable) System belief at session start, snapshotted when this item row was created. |
1395
+ | actualQuantity | any | no | Physical count entered by the counter. Null until counted; set when the line moves to status COUNTED. |
1396
+ | delta | number | yes | (Read-only) Signed difference between actual and theoretical. Drives the StockMovement(type=INVENTORY) emitted on session COMPLETED. |
1397
+ | unit | string | yes | (Immutable) Snapshot of StockItem.unit at session start. Locks the unit against later catalog changes. |
1398
+ | costPerUnit | number | yes | (Immutable) Snapshot of StockItem.costPerUnit at session start, in XOF integer minor units. |
1399
+ | totalValue | number | yes | (Read-only) Per-line valuation in XOF integer minor units. |
1400
+ | status | StocktakeItemStatus | yes | Per-line workflow status. Server transitions ADJUSTED on parent COMPLETED. |
1401
+ | notes | any | no | Optional per-line note from the counter (e.g. "damaged carton, 3 unsellable"). |
1402
+ | countedBy | any | no | UID of the staff member who entered actualQuantity. |
1403
+ | countedByName | any | no | (Denormalized) Snapshot of the counter's display name at count time. |
1404
+ | countedAt | any | no | When the line was counted. |
1405
+ | verifiedBy | any | no | UID of a second staff member who verified the count. Nullable per GH#29 Q21. |
1406
+ | verifiedByName | any | no | (Denormalized) Snapshot of the verifier's display name. |
1407
+ | verifiedAt | any | no | When the line was verified, if a second-eye flow was used. |
1408
+
1409
+ Example:
1410
+ ```json
1411
+ {
1412
+ "stockItemId": "sto_ref123",
1413
+ "stockItemName": "stockItemName",
1414
+ "theoreticalQuantity": 2,
1415
+ "actualQuantity": "actualQuantity",
1416
+ "delta": 0,
1417
+ "unit": "unit",
1418
+ "costPerUnit": 15000,
1419
+ "totalValue": 0,
1420
+ "status": "status",
1421
+ "notes": "VIP customer, handle with care",
1422
+ "countedBy": "countedBy",
1423
+ "countedByName": "countedByName",
1424
+ "countedAt": "countedAt",
1425
+ "verifiedBy": "verifiedBy",
1426
+ "verifiedByName": "verifiedByName",
1427
+ "verifiedAt": "verifiedAt"
1428
+ }
1429
+ ```
1430
+
1317
1431
  ### Ticket
1318
1432
  Fields: 16 (6 required)
1319
1433
 
@@ -1358,6 +1472,44 @@ Example:
1358
1472
  }
1359
1473
  ```
1360
1474
 
1475
+ ### WhatsappInboundMessage
1476
+ Fields: 13 (7 required)
1477
+
1478
+ | Field | Type | Required | Description |
1479
+ |-------|------|----------|-------------|
1480
+ | id | ['string', 'null'] | no | (Read-only) Firestore document ID — wamid from Meta Cloud API. |
1481
+ | wabaId | string | yes | (Immutable) Meta WABA ID identifying which business number received the message. |
1482
+ | waba | WabaLabel | yes | (Immutable) Human-readable WABA label (cmz | val). See WabaLabel enum. |
1483
+ | messageId | string | yes | (Immutable) WhatsApp message ID (wamid) returned by Meta — mirrors the document ID. |
1484
+ | from | string | yes | (Immutable) Sender phone number in E.164 format. |
1485
+ | type | any | yes | (Immutable) Meta message type. |
1486
+ | timestamp | FirestoreTimestamp | yes | (Immutable) Message timestamp as reported by Meta. |
1487
+ | receivedAt | FirestoreTimestamp | yes | (Read-only) Server-side ingestion time set by the Cloud Function. |
1488
+ | text | ['string', 'null'] | no | Message body text. Present on type=text messages only. |
1489
+ | mediaId | ['string', 'null'] | no | Meta media ID. Present on image, audio, video, document, sticker messages. |
1490
+ | caption | ['string', 'null'] | no | Media caption text. Present when the sender included a caption. |
1491
+ | storageUrl | ['string', 'null'] | no | Durable Cloud Storage URL for the downloaded media binary. Present after the CF downloads and stores the media. |
1492
+ | context | ['object', 'null'] | no | Reply/forward context. Present on replies and forwarded messages. |
1493
+
1494
+ Example:
1495
+ ```json
1496
+ {
1497
+ "id": null,
1498
+ "wabaId": "wab_ref123",
1499
+ "waba": "waba",
1500
+ "messageId": "mes_ref123",
1501
+ "from": "from",
1502
+ "type": "phone",
1503
+ "timestamp": "timestamp",
1504
+ "receivedAt": "receivedAt",
1505
+ "text": null,
1506
+ "mediaId": null,
1507
+ "caption": null,
1508
+ "storageUrl": null,
1509
+ "context": null
1510
+ }
1511
+ ```
1512
+
1361
1513
  ---
1362
1514
 
1363
1515
  ## Proposed (Work In Progress)