@ingenx-io/valets-schema-mcp-server 0.2.4 → 0.2.6
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/data/docs/collections/firestore-paths.md +32 -20
- package/data/docs/enums/app-status.md +24 -0
- package/data/docs/enums/attention-status.md +2 -2
- package/data/docs/enums/booking-status.md +2 -2
- package/data/docs/enums/contract-status.md +24 -0
- package/data/docs/enums/customer-payment-status.md +2 -2
- package/data/docs/enums/customer-payment-target-type.md +2 -2
- package/data/docs/enums/delivery-type.md +2 -2
- package/data/docs/enums/deployment-link-type.md +2 -2
- package/data/docs/enums/event-status.md +2 -2
- package/data/docs/enums/fulfillment-status.md +2 -2
- package/data/docs/enums/loyalty-transaction-type.md +2 -2
- package/data/docs/enums/milestone-status.md +23 -0
- package/data/docs/enums/notification-channel.md +2 -2
- package/data/docs/enums/notification-entity-type.md +2 -2
- package/data/docs/enums/notification-status.md +2 -2
- package/data/docs/enums/order-status.md +2 -2
- package/data/docs/enums/outbound-message-format.md +2 -2
- package/data/docs/enums/outbound-message-purpose.md +2 -2
- package/data/docs/enums/outbound-message-status.md +2 -2
- package/data/docs/enums/payment-method.md +2 -2
- package/data/docs/enums/payment-proof-status.md +2 -2
- package/data/docs/enums/payment-status.md +2 -2
- package/data/docs/enums/pending-issue.md +2 -2
- package/data/docs/enums/return-status.md +2 -2
- package/data/docs/enums/session-status.md +2 -2
- package/data/docs/enums/site-status.md +2 -2
- package/data/docs/enums/stocktake-frequency.md +2 -2
- package/data/docs/enums/stocktake-item-status.md +2 -2
- package/data/docs/enums/stocktake-status.md +2 -2
- package/data/docs/enums/ticket-status.md +2 -2
- package/data/docs/enums/waba-label.md +3 -3
- package/data/docs/enums/whatsapp-button-sub-type.md +2 -2
- package/data/docs/enums/whatsapp-template-component.md +2 -2
- package/data/docs/enums/whatsapp-template-status.md +2 -2
- package/data/docs/index.md +17 -7
- package/data/docs/models/allowed-user.md +7 -7
- package/data/docs/models/analytics-backfill.md +7 -7
- package/data/docs/models/analytics-daily.md +6 -6
- package/data/docs/models/analytics-event.md +7 -7
- package/data/docs/models/analytics-hourly.md +6 -6
- package/data/docs/models/app-payment.md +200 -0
- package/data/docs/models/app.md +585 -0
- package/data/docs/models/booking-version.md +2 -2
- package/data/docs/models/booking.md +127 -127
- package/data/docs/models/contract.md +454 -0
- package/data/docs/models/customer-payment-allocation.md +20 -20
- package/data/docs/models/customer-payment.md +23 -23
- package/data/docs/models/customer.md +11 -11
- package/data/docs/models/event.md +22 -22
- package/data/docs/models/loyalty-config.md +4 -4
- package/data/docs/models/loyalty-reward.md +3 -3
- package/data/docs/models/loyalty-status.md +6 -6
- package/data/docs/models/loyalty-transaction.md +2 -2
- package/data/docs/models/magic-link-request.md +9 -9
- package/data/docs/models/metrics-current.md +169 -37
- package/data/docs/models/metrics-daily.md +172 -40
- package/data/docs/models/metrics-monthly.md +172 -40
- package/data/docs/models/notification-record.md +3 -3
- package/data/docs/models/order-item.md +6 -6
- package/data/docs/models/order.md +314 -294
- package/data/docs/models/outbound-payment-allocation.md +195 -0
- package/data/docs/models/outbound-payment.md +318 -0
- package/data/docs/models/payment-webhook-endpoint.md +191 -0
- package/data/docs/models/sale.md +18 -18
- package/data/docs/models/site-payment.md +2 -2
- package/data/docs/models/site.md +2 -2
- package/data/docs/models/stocktake-item.md +4 -4
- package/data/docs/models/stocktake.md +5 -5
- package/data/docs/models/ticket.md +3 -3
- package/data/docs/models/user.md +249 -0
- package/data/docs/models/whatsapp-inbound-message.md +6 -2
- package/data/docs/models/whatsapp-outbound-lifecycle-event.md +2 -2
- package/data/docs/models/whatsapp-outbound-message.md +43 -27
- package/data/docs/models/whatsapp-template.md +6 -2
- package/data/static/llms.txt +322 -36
- package/data/static/openapi.yaml +1074 -66
- package/data/static/schemas.json +1183 -104
- package/package.json +1 -1
package/data/static/openapi.yaml
CHANGED
|
@@ -20,6 +20,16 @@ info:
|
|
|
20
20
|
paths: {}
|
|
21
21
|
components:
|
|
22
22
|
schemas:
|
|
23
|
+
AppStatus:
|
|
24
|
+
type: string
|
|
25
|
+
enum:
|
|
26
|
+
- ACTIVE
|
|
27
|
+
- INACTIVE
|
|
28
|
+
- EXPIRED
|
|
29
|
+
- ARCHIVED
|
|
30
|
+
description: 'Lifecycle status for an App (formerly Site — renamed per decision
|
|
31
|
+
#40 / D44). Drives whether the app is reachable and whether analytics/payments
|
|
32
|
+
flow.'
|
|
23
33
|
AttentionStatus:
|
|
24
34
|
type: string
|
|
25
35
|
enum:
|
|
@@ -41,6 +51,16 @@ components:
|
|
|
41
51
|
- COMPLETED_MIXED
|
|
42
52
|
description: Booking lifecycle status. COMPLETED_MIXED = some sessions completed,
|
|
43
53
|
others cancelled/no-show.
|
|
54
|
+
ContractStatus:
|
|
55
|
+
type: string
|
|
56
|
+
enum:
|
|
57
|
+
- DRAFT
|
|
58
|
+
- ACTIVE
|
|
59
|
+
- COMPLETED
|
|
60
|
+
- TERMINATED
|
|
61
|
+
description: Lifecycle status of a Contract. DRAFT = not yet signed. ACTIVE
|
|
62
|
+
= in force. COMPLETED = all milestones paid and obligations met. TERMINATED
|
|
63
|
+
= ended early by either party.
|
|
44
64
|
CustomerPaymentStatus:
|
|
45
65
|
type: string
|
|
46
66
|
enum:
|
|
@@ -110,6 +130,14 @@ components:
|
|
|
110
130
|
- BONUS
|
|
111
131
|
- REFUND
|
|
112
132
|
description: Loyalty point transaction type (D07). SCREAMING_SNAKE past tense.
|
|
133
|
+
MilestoneStatus:
|
|
134
|
+
type: string
|
|
135
|
+
enum:
|
|
136
|
+
- PENDING
|
|
137
|
+
- INVOICED
|
|
138
|
+
- PAID
|
|
139
|
+
description: Status of a ContractMilestone (#17). PENDING = created, not yet
|
|
140
|
+
invoiced. INVOICED = invoice issued, awaiting payment. PAID = payment received.
|
|
113
141
|
NotificationChannel:
|
|
114
142
|
type: string
|
|
115
143
|
enum:
|
|
@@ -299,8 +327,9 @@ components:
|
|
|
299
327
|
enum:
|
|
300
328
|
- cmz
|
|
301
329
|
- val
|
|
302
|
-
description:
|
|
303
|
-
|
|
330
|
+
description: WABA label identifying which Meta Business Account sent/received
|
|
331
|
+
the message. cmz = Chez Miss Zahoui sender; val = Valets sender. See WhatsApp
|
|
332
|
+
platform constraints doc (#50).
|
|
304
333
|
WhatsappButtonSubType:
|
|
305
334
|
type: string
|
|
306
335
|
enum:
|
|
@@ -345,7 +374,9 @@ components:
|
|
|
345
374
|
- _seconds
|
|
346
375
|
- _nanoseconds
|
|
347
376
|
additionalProperties: false
|
|
348
|
-
description: Firestore Timestamp
|
|
377
|
+
description: 'Firestore Timestamp — Admin SDK form: { _seconds, _nanoseconds
|
|
378
|
+
}. See types/firestore.ts for REST API v1 and client SDK serialization notes
|
|
379
|
+
(#10).'
|
|
349
380
|
AllowedUser:
|
|
350
381
|
type: object
|
|
351
382
|
properties:
|
|
@@ -360,10 +391,11 @@ components:
|
|
|
360
391
|
type: string
|
|
361
392
|
x-immutable: true
|
|
362
393
|
description: (Immutable) FK → Company document ID.
|
|
363
|
-
|
|
394
|
+
appId:
|
|
364
395
|
type: string
|
|
365
396
|
x-immutable: true
|
|
366
|
-
description: (Immutable) FK →
|
|
397
|
+
description: (Immutable) FK → App document ID (D40 sub-tenant scope, renamed
|
|
398
|
+
per D44).
|
|
367
399
|
contact:
|
|
368
400
|
type: string
|
|
369
401
|
description: Email or E.164 phone number. Canonical identifier for this
|
|
@@ -388,7 +420,7 @@ components:
|
|
|
388
420
|
description: RFC3339Nano UTC when payment was completed.
|
|
389
421
|
required:
|
|
390
422
|
- companyId
|
|
391
|
-
-
|
|
423
|
+
- appId
|
|
392
424
|
- contact
|
|
393
425
|
- tier
|
|
394
426
|
- amount
|
|
@@ -396,7 +428,7 @@ components:
|
|
|
396
428
|
- transactionId
|
|
397
429
|
- paidAt
|
|
398
430
|
additionalProperties: false
|
|
399
|
-
description: 'AllowedUser model (D40 / ING-304). Collection: companies/{companyId}/
|
|
431
|
+
description: 'AllowedUser model (D40 / ING-304). Collection: companies/{companyId}/apps/{appId}/allowed_users/{contactId}.
|
|
400
432
|
Authoritative paid-access allowlist. Upsert semantics — tier upgrades overwrite.
|
|
401
433
|
Source of truth for access checks and referral code resolution.'
|
|
402
434
|
AllowedUserCreate:
|
|
@@ -407,7 +439,7 @@ components:
|
|
|
407
439
|
may be set once at creation.
|
|
408
440
|
required:
|
|
409
441
|
- companyId
|
|
410
|
-
-
|
|
442
|
+
- appId
|
|
411
443
|
- contact
|
|
412
444
|
- tier
|
|
413
445
|
- amount
|
|
@@ -433,7 +465,7 @@ components:
|
|
|
433
465
|
type: string
|
|
434
466
|
x-immutable: true
|
|
435
467
|
description: (Immutable) FK → Company document ID.
|
|
436
|
-
|
|
468
|
+
appId:
|
|
437
469
|
type: string
|
|
438
470
|
x-immutable: true
|
|
439
471
|
description: (Immutable) FK → Site document ID (D40).
|
|
@@ -501,7 +533,7 @@ components:
|
|
|
501
533
|
description: (Read-only) When the run reached a terminal status.
|
|
502
534
|
required:
|
|
503
535
|
- companyId
|
|
504
|
-
-
|
|
536
|
+
- appId
|
|
505
537
|
- status
|
|
506
538
|
- from
|
|
507
539
|
- to
|
|
@@ -511,7 +543,7 @@ components:
|
|
|
511
543
|
- triggeredBy
|
|
512
544
|
- startedAt
|
|
513
545
|
additionalProperties: false
|
|
514
|
-
description: 'AnalyticsBackfill run (D42 / ING-304). Collection: companies/{companyId}/
|
|
546
|
+
description: 'AnalyticsBackfill run (D42 / ING-304). Collection: companies/{companyId}/apps/{appId}/analytics_backfills/{runId}.
|
|
515
547
|
Tracks admin-triggered rollup backfill jobs; supports dry-run.'
|
|
516
548
|
AnalyticsBackfillCreate:
|
|
517
549
|
allOf:
|
|
@@ -521,7 +553,7 @@ components:
|
|
|
521
553
|
may be set once at creation.
|
|
522
554
|
required:
|
|
523
555
|
- companyId
|
|
524
|
-
-
|
|
556
|
+
- appId
|
|
525
557
|
- status
|
|
526
558
|
- from
|
|
527
559
|
- to
|
|
@@ -607,7 +639,7 @@ components:
|
|
|
607
639
|
type: string
|
|
608
640
|
x-immutable: true
|
|
609
641
|
description: (Immutable) FK → Company document ID.
|
|
610
|
-
|
|
642
|
+
appId:
|
|
611
643
|
type: string
|
|
612
644
|
x-immutable: true
|
|
613
645
|
description: (Immutable) FK → Site document ID (D40).
|
|
@@ -641,11 +673,11 @@ components:
|
|
|
641
673
|
- errors
|
|
642
674
|
- eventCounts
|
|
643
675
|
- companyId
|
|
644
|
-
-
|
|
676
|
+
- appId
|
|
645
677
|
- date
|
|
646
678
|
- computedAt
|
|
647
679
|
additionalProperties: false
|
|
648
|
-
description: 'AnalyticsDaily rollup (D42 / ING-304). Collection: companies/{companyId}/
|
|
680
|
+
description: 'AnalyticsDaily rollup (D42 / ING-304). Collection: companies/{companyId}/apps/{appId}/analytics_daily/{YYYY-MM-DD}.
|
|
649
681
|
Idempotent set/merge — reruns overwrite. Fall back to raw analytics_events
|
|
650
682
|
for uncovered slices.'
|
|
651
683
|
AnalyticsDailyCreate:
|
|
@@ -666,7 +698,7 @@ components:
|
|
|
666
698
|
- errors
|
|
667
699
|
- eventCounts
|
|
668
700
|
- companyId
|
|
669
|
-
-
|
|
701
|
+
- appId
|
|
670
702
|
- date
|
|
671
703
|
AnalyticsDailyUpdate:
|
|
672
704
|
allOf:
|
|
@@ -687,10 +719,11 @@ components:
|
|
|
687
719
|
type: string
|
|
688
720
|
x-immutable: true
|
|
689
721
|
description: (Immutable) FK → Company document ID.
|
|
690
|
-
|
|
722
|
+
appId:
|
|
691
723
|
type: string
|
|
692
724
|
x-immutable: true
|
|
693
|
-
description: (Immutable) FK →
|
|
725
|
+
description: (Immutable) FK → App document ID (D40 sub-tenant scope, renamed
|
|
726
|
+
per D44).
|
|
694
727
|
eventId:
|
|
695
728
|
type: string
|
|
696
729
|
x-immutable: true
|
|
@@ -806,7 +839,7 @@ components:
|
|
|
806
839
|
additionalProperties: {}
|
|
807
840
|
required:
|
|
808
841
|
- companyId
|
|
809
|
-
-
|
|
842
|
+
- appId
|
|
810
843
|
- eventId
|
|
811
844
|
- eventName
|
|
812
845
|
- timestamp
|
|
@@ -816,7 +849,7 @@ components:
|
|
|
816
849
|
- properties
|
|
817
850
|
- context
|
|
818
851
|
additionalProperties: false
|
|
819
|
-
description: 'AnalyticsEvent model (D40 / ING-304). Collection: companies/{companyId}/
|
|
852
|
+
description: 'AnalyticsEvent model (D40 / ING-304). Collection: companies/{companyId}/apps/{appId}/analytics_events/{eventId}.
|
|
820
853
|
Append-only, immutable product/behavior event stream. Event names are free
|
|
821
854
|
strings; canonical vocabulary in CANONICAL_ANALYTICS_EVENT_NAMES.'
|
|
822
855
|
AnalyticsEventCreate:
|
|
@@ -827,7 +860,7 @@ components:
|
|
|
827
860
|
may be set once at creation.
|
|
828
861
|
required:
|
|
829
862
|
- companyId
|
|
830
|
-
-
|
|
863
|
+
- appId
|
|
831
864
|
- eventId
|
|
832
865
|
- eventName
|
|
833
866
|
- timestamp
|
|
@@ -913,7 +946,7 @@ components:
|
|
|
913
946
|
type: string
|
|
914
947
|
x-immutable: true
|
|
915
948
|
description: (Immutable) FK → Company document ID.
|
|
916
|
-
|
|
949
|
+
appId:
|
|
917
950
|
type: string
|
|
918
951
|
x-immutable: true
|
|
919
952
|
description: (Immutable) FK → Site document ID (D40).
|
|
@@ -952,12 +985,12 @@ components:
|
|
|
952
985
|
- errors
|
|
953
986
|
- eventCounts
|
|
954
987
|
- companyId
|
|
955
|
-
-
|
|
988
|
+
- appId
|
|
956
989
|
- date
|
|
957
990
|
- hour
|
|
958
991
|
- computedAt
|
|
959
992
|
additionalProperties: false
|
|
960
|
-
description: 'AnalyticsHourly rollup (D42 / ING-304). Collection: companies/{companyId}/
|
|
993
|
+
description: 'AnalyticsHourly rollup (D42 / ING-304). Collection: companies/{companyId}/apps/{appId}/analytics_hourly/{YYYY-MM-DD-HH}.
|
|
961
994
|
Scheduled-CF writer; idempotent set/merge.'
|
|
962
995
|
AnalyticsHourlyCreate:
|
|
963
996
|
allOf:
|
|
@@ -977,7 +1010,7 @@ components:
|
|
|
977
1010
|
- errors
|
|
978
1011
|
- eventCounts
|
|
979
1012
|
- companyId
|
|
980
|
-
-
|
|
1013
|
+
- appId
|
|
981
1014
|
- date
|
|
982
1015
|
- hour
|
|
983
1016
|
AnalyticsHourlyUpdate:
|
|
@@ -986,6 +1019,267 @@ components:
|
|
|
986
1019
|
description: Write payload for partial update (PATCH) of a AnalyticsHourly document.
|
|
987
1020
|
All fields optional. Fields marked `readOnly` or `x-immutable` must not be
|
|
988
1021
|
sent.
|
|
1022
|
+
App:
|
|
1023
|
+
type: object
|
|
1024
|
+
properties:
|
|
1025
|
+
id:
|
|
1026
|
+
readOnly: true
|
|
1027
|
+
description: (Read-only) Firestore document ID, auto-generated.
|
|
1028
|
+
type:
|
|
1029
|
+
- string
|
|
1030
|
+
- 'null'
|
|
1031
|
+
companyId:
|
|
1032
|
+
type: string
|
|
1033
|
+
x-immutable: true
|
|
1034
|
+
description: (Immutable) FK → Company document ID. Scopes all app sub-collections.
|
|
1035
|
+
name:
|
|
1036
|
+
type: string
|
|
1037
|
+
description: Human-readable app name shown in dashboards.
|
|
1038
|
+
description:
|
|
1039
|
+
description: Optional freeform description.
|
|
1040
|
+
type:
|
|
1041
|
+
- string
|
|
1042
|
+
- 'null'
|
|
1043
|
+
status:
|
|
1044
|
+
anyOf:
|
|
1045
|
+
- $ref: '#/components/schemas/AppStatus'
|
|
1046
|
+
- type: 'null'
|
|
1047
|
+
x-note: Real Firestore documents may be missing this field on pre-backfill
|
|
1048
|
+
records (#26). Treat absent as ACTIVE. A backfill script will populate
|
|
1049
|
+
status=ACTIVE on all existing documents; once confirmed, this field will
|
|
1050
|
+
be promoted to required.
|
|
1051
|
+
x-when: Written by operators via dashboard or by server triggers (expiration).
|
|
1052
|
+
Clients must not use server-side `where(status == ACTIVE)` until backfill
|
|
1053
|
+
is complete — filter client-side instead, treating absent as ACTIVE.
|
|
1054
|
+
description: Lifecycle status (D41/D44). Optional pending backfill of pre-existing
|
|
1055
|
+
records (#26) — treat absent as ACTIVE. Clients filter by ACTIVE.
|
|
1056
|
+
x-see:
|
|
1057
|
+
decisions:
|
|
1058
|
+
- D41
|
|
1059
|
+
- D44
|
|
1060
|
+
deploymentLinks:
|
|
1061
|
+
type: array
|
|
1062
|
+
items:
|
|
1063
|
+
type: object
|
|
1064
|
+
properties:
|
|
1065
|
+
label:
|
|
1066
|
+
type: string
|
|
1067
|
+
description: Human-readable label shown in dashboards (e.g. "Production",
|
|
1068
|
+
"Staging").
|
|
1069
|
+
url:
|
|
1070
|
+
type: string
|
|
1071
|
+
description: Absolute URL or store link.
|
|
1072
|
+
type:
|
|
1073
|
+
$ref: '#/components/schemas/DeploymentLinkType'
|
|
1074
|
+
description: Link category — drives icon/handler selection.
|
|
1075
|
+
x-note: Lowercase by convention — deployment link types are display-oriented
|
|
1076
|
+
labels, not lifecycle states.
|
|
1077
|
+
x-see:
|
|
1078
|
+
decisions:
|
|
1079
|
+
- D41
|
|
1080
|
+
isPrimary:
|
|
1081
|
+
description: If true, this link is used as the canonical deployment
|
|
1082
|
+
URL for the App.
|
|
1083
|
+
type: boolean
|
|
1084
|
+
required:
|
|
1085
|
+
- label
|
|
1086
|
+
- url
|
|
1087
|
+
- type
|
|
1088
|
+
additionalProperties: false
|
|
1089
|
+
description: Deployment link entry embedded on App.deploymentLinks[] (D41).
|
|
1090
|
+
description: Ordered list of deployment URLs (web, mobile, PWA, store links).
|
|
1091
|
+
expiresAt:
|
|
1092
|
+
anyOf:
|
|
1093
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
1094
|
+
- type: 'null'
|
|
1095
|
+
description: Optional expiration timestamp. When set and elapsed, `isExpired`
|
|
1096
|
+
flips true and status typically moves to EXPIRED.
|
|
1097
|
+
isExpired:
|
|
1098
|
+
readOnly: true
|
|
1099
|
+
description: (Read-only) Derived — true when `expiresAt` is in the past.
|
|
1100
|
+
Maintained by server trigger.
|
|
1101
|
+
type:
|
|
1102
|
+
- boolean
|
|
1103
|
+
- 'null'
|
|
1104
|
+
createdAt:
|
|
1105
|
+
anyOf:
|
|
1106
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
1107
|
+
- type: 'null'
|
|
1108
|
+
readOnly: true
|
|
1109
|
+
description: (Read-only) Server-generated creation timestamp.
|
|
1110
|
+
updatedAt:
|
|
1111
|
+
anyOf:
|
|
1112
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
1113
|
+
- type: 'null'
|
|
1114
|
+
readOnly: true
|
|
1115
|
+
description: (Read-only) Server-generated update timestamp.
|
|
1116
|
+
createdBy:
|
|
1117
|
+
type: string
|
|
1118
|
+
x-immutable: true
|
|
1119
|
+
description: (Immutable) FK → User/staff UID who created the app.
|
|
1120
|
+
analyticsEnabled:
|
|
1121
|
+
type: boolean
|
|
1122
|
+
description: Feature flag — when false, clients should not emit analytics
|
|
1123
|
+
events for this app.
|
|
1124
|
+
lastAnalyticsSync:
|
|
1125
|
+
anyOf:
|
|
1126
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
1127
|
+
- type: 'null'
|
|
1128
|
+
readOnly: true
|
|
1129
|
+
description: (Read-only) Last time the analytics rollup pipeline refreshed
|
|
1130
|
+
`cachedMetrics`.
|
|
1131
|
+
cachedMetrics:
|
|
1132
|
+
readOnly: true
|
|
1133
|
+
denormalized: true
|
|
1134
|
+
x-note: Updated by the rollup pipeline (D42). Readers should treat this
|
|
1135
|
+
as a hint; authoritative counts live in analytics_daily/analytics_hourly.
|
|
1136
|
+
x-see:
|
|
1137
|
+
decisions:
|
|
1138
|
+
- D41
|
|
1139
|
+
- D42
|
|
1140
|
+
description: (Read-only, Denormalized) Cached metrics snapshot for quick
|
|
1141
|
+
dashboard rendering.
|
|
1142
|
+
type:
|
|
1143
|
+
- object
|
|
1144
|
+
- 'null'
|
|
1145
|
+
properties:
|
|
1146
|
+
totalEvents:
|
|
1147
|
+
type: integer
|
|
1148
|
+
minimum: -9007199254740991
|
|
1149
|
+
maximum: 9007199254740991
|
|
1150
|
+
description: All-time event count cached on the App.
|
|
1151
|
+
totalPageViews:
|
|
1152
|
+
type: integer
|
|
1153
|
+
minimum: -9007199254740991
|
|
1154
|
+
maximum: 9007199254740991
|
|
1155
|
+
description: All-time `page_view` + `screen_view` count.
|
|
1156
|
+
totalSessions:
|
|
1157
|
+
type: integer
|
|
1158
|
+
minimum: -9007199254740991
|
|
1159
|
+
maximum: 9007199254740991
|
|
1160
|
+
description: All-time distinct session count.
|
|
1161
|
+
totalOrders:
|
|
1162
|
+
type: integer
|
|
1163
|
+
minimum: -9007199254740991
|
|
1164
|
+
maximum: 9007199254740991
|
|
1165
|
+
description: All-time order count attributed to this app (via `Order.appId`,
|
|
1166
|
+
D43).
|
|
1167
|
+
lastEventAt:
|
|
1168
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
1169
|
+
description: Timestamp of the most recent analytics event seen for this
|
|
1170
|
+
app.
|
|
1171
|
+
required:
|
|
1172
|
+
- totalEvents
|
|
1173
|
+
- totalPageViews
|
|
1174
|
+
- totalSessions
|
|
1175
|
+
- totalOrders
|
|
1176
|
+
additionalProperties: false
|
|
1177
|
+
required:
|
|
1178
|
+
- companyId
|
|
1179
|
+
- name
|
|
1180
|
+
- deploymentLinks
|
|
1181
|
+
- createdBy
|
|
1182
|
+
- analyticsEnabled
|
|
1183
|
+
additionalProperties: false
|
|
1184
|
+
description: 'App model (D41 / ING-304). Collection: companies/{companyId}/apps/{appId}.
|
|
1185
|
+
Per-company product surface. Sub-collections (magic_link_requests, allowed_users,
|
|
1186
|
+
payments, analytics_events, analytics_daily, analytics_hourly, analytics_backfills)
|
|
1187
|
+
live under this document per D40/D42.'
|
|
1188
|
+
AppCreate:
|
|
1189
|
+
allOf:
|
|
1190
|
+
- $ref: '#/components/schemas/App'
|
|
1191
|
+
description: Write payload for creating a new App document. Fields marked `readOnly`
|
|
1192
|
+
are server-set and must not be included. Fields marked `x-immutable` may be
|
|
1193
|
+
set once at creation.
|
|
1194
|
+
required:
|
|
1195
|
+
- companyId
|
|
1196
|
+
- name
|
|
1197
|
+
- deploymentLinks
|
|
1198
|
+
- createdBy
|
|
1199
|
+
- analyticsEnabled
|
|
1200
|
+
AppUpdate:
|
|
1201
|
+
allOf:
|
|
1202
|
+
- $ref: '#/components/schemas/App'
|
|
1203
|
+
description: Write payload for partial update (PATCH) of a App document. All
|
|
1204
|
+
fields optional. Fields marked `readOnly` or `x-immutable` must not be sent.
|
|
1205
|
+
AppPayment:
|
|
1206
|
+
type: object
|
|
1207
|
+
properties:
|
|
1208
|
+
id:
|
|
1209
|
+
readOnly: true
|
|
1210
|
+
description: (Read-only) Firestore document ID, auto-generated.
|
|
1211
|
+
type:
|
|
1212
|
+
- string
|
|
1213
|
+
- 'null'
|
|
1214
|
+
companyId:
|
|
1215
|
+
type: string
|
|
1216
|
+
x-immutable: true
|
|
1217
|
+
description: (Immutable) FK → Company document ID.
|
|
1218
|
+
appId:
|
|
1219
|
+
type: string
|
|
1220
|
+
x-immutable: true
|
|
1221
|
+
description: (Immutable) FK → App document ID (D40 sub-tenant scope, renamed
|
|
1222
|
+
from siteId per D44).
|
|
1223
|
+
contact:
|
|
1224
|
+
type: string
|
|
1225
|
+
description: Email or E.164 phone number. Matches AllowedUser.contact.
|
|
1226
|
+
sessionId:
|
|
1227
|
+
type: string
|
|
1228
|
+
description: Payment provider checkout session ID (e.g. Wave). Usable for
|
|
1229
|
+
dedup across dual writes.
|
|
1230
|
+
transactionId:
|
|
1231
|
+
type: string
|
|
1232
|
+
description: Payment provider transaction ID.
|
|
1233
|
+
tier:
|
|
1234
|
+
type: string
|
|
1235
|
+
description: Access tier. Free string per app (ING-304 open question).
|
|
1236
|
+
amount:
|
|
1237
|
+
type: number
|
|
1238
|
+
description: Amount paid. Generalized from amount_xof per D40 decision.
|
|
1239
|
+
currency:
|
|
1240
|
+
default: XOF
|
|
1241
|
+
description: Currency code (ISO 4217). Defaults to XOF for legacy SR-Single
|
|
1242
|
+
parity.
|
|
1243
|
+
type: string
|
|
1244
|
+
paidAt:
|
|
1245
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
1246
|
+
description: RFC3339Nano UTC when payment was completed.
|
|
1247
|
+
required:
|
|
1248
|
+
- companyId
|
|
1249
|
+
- appId
|
|
1250
|
+
- contact
|
|
1251
|
+
- sessionId
|
|
1252
|
+
- transactionId
|
|
1253
|
+
- tier
|
|
1254
|
+
- amount
|
|
1255
|
+
- currency
|
|
1256
|
+
- paidAt
|
|
1257
|
+
additionalProperties: false
|
|
1258
|
+
description: 'AppPayment model (D40 / ING-304). Collection: companies/{companyId}/apps/{appId}/payments/{paymentId}.
|
|
1259
|
+
Immutable append-only transaction ledger. Distinct from AllowedUser (access
|
|
1260
|
+
state) and CustomerPayment (D22 — customer-level billing).'
|
|
1261
|
+
AppPaymentCreate:
|
|
1262
|
+
allOf:
|
|
1263
|
+
- $ref: '#/components/schemas/AppPayment'
|
|
1264
|
+
description: Write payload for creating a new AppPayment document. Fields marked
|
|
1265
|
+
`readOnly` are server-set and must not be included. Fields marked `x-immutable`
|
|
1266
|
+
may be set once at creation.
|
|
1267
|
+
required:
|
|
1268
|
+
- companyId
|
|
1269
|
+
- appId
|
|
1270
|
+
- contact
|
|
1271
|
+
- sessionId
|
|
1272
|
+
- transactionId
|
|
1273
|
+
- tier
|
|
1274
|
+
- amount
|
|
1275
|
+
- currency
|
|
1276
|
+
- paidAt
|
|
1277
|
+
AppPaymentUpdate:
|
|
1278
|
+
allOf:
|
|
1279
|
+
- $ref: '#/components/schemas/AppPayment'
|
|
1280
|
+
description: Write payload for partial update (PATCH) of a AppPayment document.
|
|
1281
|
+
All fields optional. Fields marked `readOnly` or `x-immutable` must not be
|
|
1282
|
+
sent.
|
|
989
1283
|
Booking:
|
|
990
1284
|
type: object
|
|
991
1285
|
properties:
|
|
@@ -1062,13 +1356,17 @@ components:
|
|
|
1062
1356
|
type: boolean
|
|
1063
1357
|
_deletedAt:
|
|
1064
1358
|
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
1065
|
-
description: Firestore Timestamp
|
|
1359
|
+
description: 'Firestore Timestamp — Admin SDK form: { _seconds,
|
|
1360
|
+
_nanoseconds }. See types/firestore.ts for REST API v1 and
|
|
1361
|
+
client SDK serialization notes (#10).'
|
|
1066
1362
|
_deletedBy:
|
|
1067
1363
|
description: FK → User/staff UID who soft-deleted this item.
|
|
1068
1364
|
type: string
|
|
1069
1365
|
_lastModifiedAt:
|
|
1070
1366
|
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
1071
|
-
description: Firestore Timestamp
|
|
1367
|
+
description: 'Firestore Timestamp — Admin SDK form: { _seconds,
|
|
1368
|
+
_nanoseconds }. See types/firestore.ts for REST API v1 and
|
|
1369
|
+
client SDK serialization notes (#10).'
|
|
1072
1370
|
_lastModifiedBy:
|
|
1073
1371
|
description: FK → User/staff UID who last modified this item.
|
|
1074
1372
|
type: string
|
|
@@ -1133,7 +1431,9 @@ components:
|
|
|
1133
1431
|
type: string
|
|
1134
1432
|
additionalProperties:
|
|
1135
1433
|
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
1136
|
-
description: Firestore Timestamp
|
|
1434
|
+
description: 'Firestore Timestamp — Admin SDK form: { _seconds,
|
|
1435
|
+
_nanoseconds }. See types/firestore.ts for REST API v1 and client
|
|
1436
|
+
SDK serialization notes (#10).'
|
|
1137
1437
|
slotStatusUpdatedBy:
|
|
1138
1438
|
type: object
|
|
1139
1439
|
propertyNames:
|
|
@@ -1145,13 +1445,17 @@ components:
|
|
|
1145
1445
|
type: boolean
|
|
1146
1446
|
_deletedAt:
|
|
1147
1447
|
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
1148
|
-
description: Firestore Timestamp
|
|
1448
|
+
description: 'Firestore Timestamp — Admin SDK form: { _seconds, _nanoseconds
|
|
1449
|
+
}. See types/firestore.ts for REST API v1 and client SDK serialization
|
|
1450
|
+
notes (#10).'
|
|
1149
1451
|
_deletedBy:
|
|
1150
1452
|
description: FK → User/staff UID who soft-deleted this item.
|
|
1151
1453
|
type: string
|
|
1152
1454
|
_lastModifiedAt:
|
|
1153
1455
|
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
1154
|
-
description: Firestore Timestamp
|
|
1456
|
+
description: 'Firestore Timestamp — Admin SDK form: { _seconds, _nanoseconds
|
|
1457
|
+
}. See types/firestore.ts for REST API v1 and client SDK serialization
|
|
1458
|
+
notes (#10).'
|
|
1155
1459
|
_lastModifiedBy:
|
|
1156
1460
|
description: FK → User/staff UID who last modified this item.
|
|
1157
1461
|
type: string
|
|
@@ -1313,13 +1617,17 @@ components:
|
|
|
1313
1617
|
type: boolean
|
|
1314
1618
|
_deletedAt:
|
|
1315
1619
|
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
1316
|
-
description: Firestore Timestamp
|
|
1620
|
+
description: 'Firestore Timestamp — Admin SDK form: { _seconds, _nanoseconds
|
|
1621
|
+
}. See types/firestore.ts for REST API v1 and client SDK serialization
|
|
1622
|
+
notes (#10).'
|
|
1317
1623
|
_deletedBy:
|
|
1318
1624
|
description: FK → User/staff UID who soft-deleted this item.
|
|
1319
1625
|
type: string
|
|
1320
1626
|
_lastModifiedAt:
|
|
1321
1627
|
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
1322
|
-
description: Firestore Timestamp
|
|
1628
|
+
description: 'Firestore Timestamp — Admin SDK form: { _seconds, _nanoseconds
|
|
1629
|
+
}. See types/firestore.ts for REST API v1 and client SDK serialization
|
|
1630
|
+
notes (#10).'
|
|
1323
1631
|
_lastModifiedBy:
|
|
1324
1632
|
description: FK → User/staff UID who last modified this item.
|
|
1325
1633
|
type: string
|
|
@@ -1372,7 +1680,9 @@ components:
|
|
|
1372
1680
|
anyOf:
|
|
1373
1681
|
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
1374
1682
|
- type: 'null'
|
|
1375
|
-
description: Firestore Timestamp
|
|
1683
|
+
description: 'Firestore Timestamp — Admin SDK form: { _seconds, _nanoseconds
|
|
1684
|
+
}. See types/firestore.ts for REST API v1 and client SDK serialization
|
|
1685
|
+
notes (#10).'
|
|
1376
1686
|
paymentProofUrl:
|
|
1377
1687
|
description: URL to uploaded payment proof image/document.
|
|
1378
1688
|
type:
|
|
@@ -1388,7 +1698,9 @@ components:
|
|
|
1388
1698
|
anyOf:
|
|
1389
1699
|
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
1390
1700
|
- type: 'null'
|
|
1391
|
-
description: Firestore Timestamp
|
|
1701
|
+
description: 'Firestore Timestamp — Admin SDK form: { _seconds, _nanoseconds
|
|
1702
|
+
}. See types/firestore.ts for REST API v1 and client SDK serialization
|
|
1703
|
+
notes (#10).'
|
|
1392
1704
|
paymentProofAddedBy:
|
|
1393
1705
|
description: FK → User/staff UID who uploaded the payment proof.
|
|
1394
1706
|
type:
|
|
@@ -1403,7 +1715,9 @@ components:
|
|
|
1403
1715
|
anyOf:
|
|
1404
1716
|
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
1405
1717
|
- type: 'null'
|
|
1406
|
-
description: Firestore Timestamp
|
|
1718
|
+
description: 'Firestore Timestamp — Admin SDK form: { _seconds, _nanoseconds
|
|
1719
|
+
}. See types/firestore.ts for REST API v1 and client SDK serialization
|
|
1720
|
+
notes (#10).'
|
|
1407
1721
|
paymentProofRejectionReason:
|
|
1408
1722
|
type:
|
|
1409
1723
|
- string
|
|
@@ -1426,7 +1740,9 @@ components:
|
|
|
1426
1740
|
anyOf:
|
|
1427
1741
|
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
1428
1742
|
- type: 'null'
|
|
1429
|
-
description: Firestore Timestamp
|
|
1743
|
+
description: 'Firestore Timestamp — Admin SDK form: { _seconds, _nanoseconds
|
|
1744
|
+
}. See types/firestore.ts for REST API v1 and client SDK serialization
|
|
1745
|
+
notes (#10).'
|
|
1430
1746
|
cancelledByRole:
|
|
1431
1747
|
type:
|
|
1432
1748
|
- string
|
|
@@ -1587,6 +1903,156 @@ components:
|
|
|
1587
1903
|
description: 'BookingVersion model (D18). Collection: companies/{companyId}/bookings/{bookingId}/versions/{versionId}.
|
|
1588
1904
|
Server-owned audit trail written by Firebase trigger on every Booking mutation.
|
|
1589
1905
|
Captures writes from all clients.'
|
|
1906
|
+
Contract:
|
|
1907
|
+
type: object
|
|
1908
|
+
properties:
|
|
1909
|
+
id:
|
|
1910
|
+
readOnly: true
|
|
1911
|
+
description: (Read-only) Firestore document ID, auto-generated.
|
|
1912
|
+
type:
|
|
1913
|
+
- string
|
|
1914
|
+
- 'null'
|
|
1915
|
+
companyId:
|
|
1916
|
+
type: string
|
|
1917
|
+
x-immutable: true
|
|
1918
|
+
description: (Immutable) FK → Company document ID.
|
|
1919
|
+
payeeId:
|
|
1920
|
+
type: string
|
|
1921
|
+
x-immutable: true
|
|
1922
|
+
description: '(Immutable) FK → Payee document ID. Full Payee model tracked
|
|
1923
|
+
in #20.'
|
|
1924
|
+
title:
|
|
1925
|
+
type: string
|
|
1926
|
+
description: Contract title or reference name shown in dashboards.
|
|
1927
|
+
description:
|
|
1928
|
+
description: Optional freeform description of the contract scope.
|
|
1929
|
+
type:
|
|
1930
|
+
- string
|
|
1931
|
+
- 'null'
|
|
1932
|
+
status:
|
|
1933
|
+
$ref: '#/components/schemas/ContractStatus'
|
|
1934
|
+
description: Contract lifecycle status (#14). Query by ACTIVE — do not use
|
|
1935
|
+
an isActive boolean.
|
|
1936
|
+
currency:
|
|
1937
|
+
type: string
|
|
1938
|
+
const: XOF
|
|
1939
|
+
description: Currency code. Locked to XOF (#18). Multi-currency support
|
|
1940
|
+
requires a deliberate schema version bump.
|
|
1941
|
+
totalAmount:
|
|
1942
|
+
type: number
|
|
1943
|
+
description: Total contract value (XOF).
|
|
1944
|
+
startDate:
|
|
1945
|
+
type: string
|
|
1946
|
+
description: Contract start date (ISO 8601 YYYY-MM-DD).
|
|
1947
|
+
endDate:
|
|
1948
|
+
description: Contract end date (ISO 8601 YYYY-MM-DD). Absent for open-ended
|
|
1949
|
+
contracts.
|
|
1950
|
+
type:
|
|
1951
|
+
- string
|
|
1952
|
+
- 'null'
|
|
1953
|
+
milestones:
|
|
1954
|
+
description: Ordered list of payment milestones. Embedded in the contract
|
|
1955
|
+
document (#17).
|
|
1956
|
+
type:
|
|
1957
|
+
- array
|
|
1958
|
+
- 'null'
|
|
1959
|
+
items:
|
|
1960
|
+
type: object
|
|
1961
|
+
properties:
|
|
1962
|
+
id:
|
|
1963
|
+
type: string
|
|
1964
|
+
description: Client-generated milestone ID (UUID or slug). Unique
|
|
1965
|
+
within the contract.
|
|
1966
|
+
title:
|
|
1967
|
+
type: string
|
|
1968
|
+
description: Milestone description or deliverable name.
|
|
1969
|
+
amount:
|
|
1970
|
+
type: number
|
|
1971
|
+
description: Amount due at this milestone (XOF).
|
|
1972
|
+
dueDate:
|
|
1973
|
+
description: ISO 8601 date string (YYYY-MM-DD) when the milestone
|
|
1974
|
+
is due. OVERDUE is derived at read time from dueDate — not stored.
|
|
1975
|
+
type: string
|
|
1976
|
+
status:
|
|
1977
|
+
$ref: '#/components/schemas/MilestoneStatus'
|
|
1978
|
+
x-note: Existing Firestore documents may have lowercase values (pending,
|
|
1979
|
+
invoiced, paid) from before this enum was introduced (#17). Normalize
|
|
1980
|
+
on read or via migration script.
|
|
1981
|
+
description: Milestone payment status (#17). OVERDUE is derived at
|
|
1982
|
+
read time from dueDate, not stored.
|
|
1983
|
+
invoicedAt:
|
|
1984
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
1985
|
+
description: When the invoice was issued for this milestone.
|
|
1986
|
+
paidAt:
|
|
1987
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
1988
|
+
description: When payment was received for this milestone.
|
|
1989
|
+
notes:
|
|
1990
|
+
description: Optional notes for this milestone.
|
|
1991
|
+
type: string
|
|
1992
|
+
required:
|
|
1993
|
+
- id
|
|
1994
|
+
- title
|
|
1995
|
+
- amount
|
|
1996
|
+
- status
|
|
1997
|
+
additionalProperties: false
|
|
1998
|
+
description: ContractMilestone — embedded sub-object on Contract (#17).
|
|
1999
|
+
Not a separate collection.
|
|
2000
|
+
notes:
|
|
2001
|
+
description: Optional internal notes.
|
|
2002
|
+
type:
|
|
2003
|
+
- string
|
|
2004
|
+
- 'null'
|
|
2005
|
+
createdBy:
|
|
2006
|
+
type: string
|
|
2007
|
+
x-immutable: true
|
|
2008
|
+
description: (Immutable) FK → User/staff UID who created the contract.
|
|
2009
|
+
createdAt:
|
|
2010
|
+
anyOf:
|
|
2011
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
2012
|
+
- type: 'null'
|
|
2013
|
+
readOnly: true
|
|
2014
|
+
description: (Read-only) Server-generated creation timestamp.
|
|
2015
|
+
updatedAt:
|
|
2016
|
+
anyOf:
|
|
2017
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
2018
|
+
- type: 'null'
|
|
2019
|
+
readOnly: true
|
|
2020
|
+
description: (Read-only) Server-generated update timestamp.
|
|
2021
|
+
required:
|
|
2022
|
+
- companyId
|
|
2023
|
+
- payeeId
|
|
2024
|
+
- title
|
|
2025
|
+
- status
|
|
2026
|
+
- currency
|
|
2027
|
+
- totalAmount
|
|
2028
|
+
- startDate
|
|
2029
|
+
- createdBy
|
|
2030
|
+
additionalProperties: false
|
|
2031
|
+
description: 'Contract model (GH#14/#17/#18). Collection: companies/{companyId}/contracts/{contractId}.
|
|
2032
|
+
Service/supplier contract between a company and a Payee. No isActive field
|
|
2033
|
+
— query by status. Currency locked to XOF. Milestones use MilestoneStatus
|
|
2034
|
+
enum (no stored OVERDUE).'
|
|
2035
|
+
ContractCreate:
|
|
2036
|
+
allOf:
|
|
2037
|
+
- $ref: '#/components/schemas/Contract'
|
|
2038
|
+
description: Write payload for creating a new Contract document. Fields marked
|
|
2039
|
+
`readOnly` are server-set and must not be included. Fields marked `x-immutable`
|
|
2040
|
+
may be set once at creation.
|
|
2041
|
+
required:
|
|
2042
|
+
- companyId
|
|
2043
|
+
- payeeId
|
|
2044
|
+
- title
|
|
2045
|
+
- status
|
|
2046
|
+
- currency
|
|
2047
|
+
- totalAmount
|
|
2048
|
+
- startDate
|
|
2049
|
+
- createdBy
|
|
2050
|
+
ContractUpdate:
|
|
2051
|
+
allOf:
|
|
2052
|
+
- $ref: '#/components/schemas/Contract'
|
|
2053
|
+
description: Write payload for partial update (PATCH) of a Contract document.
|
|
2054
|
+
All fields optional. Fields marked `readOnly` or `x-immutable` must not be
|
|
2055
|
+
sent.
|
|
1590
2056
|
Customer:
|
|
1591
2057
|
type: object
|
|
1592
2058
|
properties:
|
|
@@ -1633,7 +2099,9 @@ components:
|
|
|
1633
2099
|
properties:
|
|
1634
2100
|
timestamp:
|
|
1635
2101
|
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
1636
|
-
description: Firestore Timestamp
|
|
2102
|
+
description: 'Firestore Timestamp — Admin SDK form: { _seconds, _nanoseconds
|
|
2103
|
+
}. See types/firestore.ts for REST API v1 and client SDK serialization
|
|
2104
|
+
notes (#10).'
|
|
1637
2105
|
type:
|
|
1638
2106
|
type: string
|
|
1639
2107
|
description: Communication channel (e.g. phone, email, meeting).
|
|
@@ -1750,7 +2218,9 @@ components:
|
|
|
1750
2218
|
description: Currency code. Locked to XOF (West African CFA franc) for now.
|
|
1751
2219
|
paymentDate:
|
|
1752
2220
|
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
1753
|
-
description: Firestore Timestamp
|
|
2221
|
+
description: 'Firestore Timestamp — Admin SDK form: { _seconds, _nanoseconds
|
|
2222
|
+
}. See types/firestore.ts for REST API v1 and client SDK serialization
|
|
2223
|
+
notes (#10).'
|
|
1754
2224
|
paymentMethod:
|
|
1755
2225
|
$ref: '#/components/schemas/PaymentMethod'
|
|
1756
2226
|
description: Unified payment method set with African + global methods (D02).
|
|
@@ -1894,7 +2364,9 @@ components:
|
|
|
1894
2364
|
anyOf:
|
|
1895
2365
|
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
1896
2366
|
- type: 'null'
|
|
1897
|
-
description: Firestore Timestamp
|
|
2367
|
+
description: 'Firestore Timestamp — Admin SDK form: { _seconds, _nanoseconds
|
|
2368
|
+
}. See types/firestore.ts for REST API v1 and client SDK serialization
|
|
2369
|
+
notes (#10).'
|
|
1898
2370
|
createdBy:
|
|
1899
2371
|
type: string
|
|
1900
2372
|
x-immutable: true
|
|
@@ -1967,12 +2439,16 @@ components:
|
|
|
1967
2439
|
- 'null'
|
|
1968
2440
|
startDate:
|
|
1969
2441
|
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
1970
|
-
description: Firestore Timestamp
|
|
2442
|
+
description: 'Firestore Timestamp — Admin SDK form: { _seconds, _nanoseconds
|
|
2443
|
+
}. See types/firestore.ts for REST API v1 and client SDK serialization
|
|
2444
|
+
notes (#10).'
|
|
1971
2445
|
endDate:
|
|
1972
2446
|
anyOf:
|
|
1973
2447
|
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
1974
2448
|
- type: 'null'
|
|
1975
|
-
description: Firestore Timestamp
|
|
2449
|
+
description: 'Firestore Timestamp — Admin SDK form: { _seconds, _nanoseconds
|
|
2450
|
+
}. See types/firestore.ts for REST API v1 and client SDK serialization
|
|
2451
|
+
notes (#10).'
|
|
1976
2452
|
status:
|
|
1977
2453
|
$ref: '#/components/schemas/EventStatus'
|
|
1978
2454
|
description: Event lifecycle status (D32). SCREAMING_SNAKE per D04. MIG-09
|
|
@@ -2417,10 +2893,11 @@ components:
|
|
|
2417
2893
|
type: string
|
|
2418
2894
|
x-immutable: true
|
|
2419
2895
|
description: (Immutable) FK → Company document ID.
|
|
2420
|
-
|
|
2896
|
+
appId:
|
|
2421
2897
|
type: string
|
|
2422
2898
|
x-immutable: true
|
|
2423
|
-
description: (Immutable) FK →
|
|
2899
|
+
description: (Immutable) FK → App document ID (D40 sub-tenant scope, renamed
|
|
2900
|
+
per D44).
|
|
2424
2901
|
email:
|
|
2425
2902
|
type: string
|
|
2426
2903
|
description: Populated if identifier is email; empty string if phone. Mutually
|
|
@@ -2472,7 +2949,7 @@ components:
|
|
|
2472
2949
|
description: RFC3339Nano UTC at verify time.
|
|
2473
2950
|
required:
|
|
2474
2951
|
- companyId
|
|
2475
|
-
-
|
|
2952
|
+
- appId
|
|
2476
2953
|
- email
|
|
2477
2954
|
- phone
|
|
2478
2955
|
- ip
|
|
@@ -2483,7 +2960,7 @@ components:
|
|
|
2483
2960
|
- referredBy
|
|
2484
2961
|
- requestedAt
|
|
2485
2962
|
additionalProperties: false
|
|
2486
|
-
description: 'MagicLinkRequest model (D40 / ING-304). Collection: companies/{companyId}/
|
|
2963
|
+
description: 'MagicLinkRequest model (D40 / ING-304). Collection: companies/{companyId}/apps/{appId}/magic_link_requests/{requestId}.
|
|
2487
2964
|
Authentication audit log — every request is logged regardless of outcome.
|
|
2488
2965
|
Two-stage write: Log() then LogVerify().'
|
|
2489
2966
|
MagicLinkRequestCreate:
|
|
@@ -2494,7 +2971,7 @@ components:
|
|
|
2494
2971
|
may be set once at creation.
|
|
2495
2972
|
required:
|
|
2496
2973
|
- companyId
|
|
2497
|
-
-
|
|
2974
|
+
- appId
|
|
2498
2975
|
- email
|
|
2499
2976
|
- phone
|
|
2500
2977
|
- ip
|
|
@@ -2650,8 +3127,64 @@ components:
|
|
|
2650
3127
|
monthlyRecurringRevenue:
|
|
2651
3128
|
type: number
|
|
2652
3129
|
readOnly: true
|
|
2653
|
-
description: (Read-only) Sum of amount for ACTIVE + MONTHLY recurring payments.
|
|
2654
|
-
Always full recalc.
|
|
3130
|
+
description: (Read-only) Sum of amount for ACTIVE + MONTHLY recurring payments.
|
|
3131
|
+
Always full recalc.
|
|
3132
|
+
escalatedOrdersCount:
|
|
3133
|
+
readOnly: true
|
|
3134
|
+
x-note: Absent on tenants whose metrics/current was last written before
|
|
3135
|
+
aggregator v2. Backfill required for universal presence (#8).
|
|
3136
|
+
description: (Read-only, Optional) Orders currently in an escalated state.
|
|
3137
|
+
Present once the current aggregator rewrites the document.
|
|
3138
|
+
type:
|
|
3139
|
+
- integer
|
|
3140
|
+
- 'null'
|
|
3141
|
+
minimum: -9007199254740991
|
|
3142
|
+
maximum: 9007199254740991
|
|
3143
|
+
staleOrdersCount:
|
|
3144
|
+
readOnly: true
|
|
3145
|
+
x-note: Absent on tenants whose metrics/current was last written before
|
|
3146
|
+
aggregator v2. Backfill required for universal presence (#8).
|
|
3147
|
+
description: (Read-only, Optional) Orders that have been in an incomplete
|
|
3148
|
+
status beyond the stale threshold.
|
|
3149
|
+
type:
|
|
3150
|
+
- integer
|
|
3151
|
+
- 'null'
|
|
3152
|
+
minimum: -9007199254740991
|
|
3153
|
+
maximum: 9007199254740991
|
|
3154
|
+
staleBookingsCount:
|
|
3155
|
+
readOnly: true
|
|
3156
|
+
x-note: Absent on tenants whose metrics/current was last written before
|
|
3157
|
+
aggregator v2. Backfill required for universal presence (#8).
|
|
3158
|
+
description: (Read-only, Optional) Bookings that have been in an incomplete
|
|
3159
|
+
status beyond the stale threshold.
|
|
3160
|
+
type:
|
|
3161
|
+
- integer
|
|
3162
|
+
- 'null'
|
|
3163
|
+
minimum: -9007199254740991
|
|
3164
|
+
maximum: 9007199254740991
|
|
3165
|
+
onHoldOrdersCount:
|
|
3166
|
+
readOnly: true
|
|
3167
|
+
x-note: Absent on tenants whose metrics/current was last written before
|
|
3168
|
+
aggregator v2. Backfill required for universal presence (#8).
|
|
3169
|
+
description: (Read-only, Optional) Orders currently in an on-hold state.
|
|
3170
|
+
type:
|
|
3171
|
+
- integer
|
|
3172
|
+
- 'null'
|
|
3173
|
+
minimum: -9007199254740991
|
|
3174
|
+
maximum: 9007199254740991
|
|
3175
|
+
paymentsByMethod:
|
|
3176
|
+
readOnly: true
|
|
3177
|
+
x-note: Always {} until the first real payment is recorded. Present on all
|
|
3178
|
+
tenants once rewritten by current aggregator (#8).
|
|
3179
|
+
description: (Read-only, Optional) Map of PaymentMethod → total amount for
|
|
3180
|
+
the current day. Empty map {} until first payment.
|
|
3181
|
+
type:
|
|
3182
|
+
- object
|
|
3183
|
+
- 'null'
|
|
3184
|
+
propertyNames:
|
|
3185
|
+
type: string
|
|
3186
|
+
additionalProperties:
|
|
3187
|
+
type: number
|
|
2655
3188
|
computedForDay:
|
|
2656
3189
|
type: string
|
|
2657
3190
|
readOnly: true
|
|
@@ -2845,6 +3378,62 @@ components:
|
|
|
2845
3378
|
readOnly: true
|
|
2846
3379
|
description: (Read-only) Sum of amount for ACTIVE + MONTHLY recurring payments.
|
|
2847
3380
|
Always full recalc.
|
|
3381
|
+
escalatedOrdersCount:
|
|
3382
|
+
readOnly: true
|
|
3383
|
+
x-note: Absent on tenants whose metrics/current was last written before
|
|
3384
|
+
aggregator v2. Backfill required for universal presence (#8).
|
|
3385
|
+
description: (Read-only, Optional) Orders currently in an escalated state.
|
|
3386
|
+
Present once the current aggregator rewrites the document.
|
|
3387
|
+
type:
|
|
3388
|
+
- integer
|
|
3389
|
+
- 'null'
|
|
3390
|
+
minimum: -9007199254740991
|
|
3391
|
+
maximum: 9007199254740991
|
|
3392
|
+
staleOrdersCount:
|
|
3393
|
+
readOnly: true
|
|
3394
|
+
x-note: Absent on tenants whose metrics/current was last written before
|
|
3395
|
+
aggregator v2. Backfill required for universal presence (#8).
|
|
3396
|
+
description: (Read-only, Optional) Orders that have been in an incomplete
|
|
3397
|
+
status beyond the stale threshold.
|
|
3398
|
+
type:
|
|
3399
|
+
- integer
|
|
3400
|
+
- 'null'
|
|
3401
|
+
minimum: -9007199254740991
|
|
3402
|
+
maximum: 9007199254740991
|
|
3403
|
+
staleBookingsCount:
|
|
3404
|
+
readOnly: true
|
|
3405
|
+
x-note: Absent on tenants whose metrics/current was last written before
|
|
3406
|
+
aggregator v2. Backfill required for universal presence (#8).
|
|
3407
|
+
description: (Read-only, Optional) Bookings that have been in an incomplete
|
|
3408
|
+
status beyond the stale threshold.
|
|
3409
|
+
type:
|
|
3410
|
+
- integer
|
|
3411
|
+
- 'null'
|
|
3412
|
+
minimum: -9007199254740991
|
|
3413
|
+
maximum: 9007199254740991
|
|
3414
|
+
onHoldOrdersCount:
|
|
3415
|
+
readOnly: true
|
|
3416
|
+
x-note: Absent on tenants whose metrics/current was last written before
|
|
3417
|
+
aggregator v2. Backfill required for universal presence (#8).
|
|
3418
|
+
description: (Read-only, Optional) Orders currently in an on-hold state.
|
|
3419
|
+
type:
|
|
3420
|
+
- integer
|
|
3421
|
+
- 'null'
|
|
3422
|
+
minimum: -9007199254740991
|
|
3423
|
+
maximum: 9007199254740991
|
|
3424
|
+
paymentsByMethod:
|
|
3425
|
+
readOnly: true
|
|
3426
|
+
x-note: Always {} until the first real payment is recorded. Present on all
|
|
3427
|
+
tenants once rewritten by current aggregator (#8).
|
|
3428
|
+
description: (Read-only, Optional) Map of PaymentMethod → total amount for
|
|
3429
|
+
the current day. Empty map {} until first payment.
|
|
3430
|
+
type:
|
|
3431
|
+
- object
|
|
3432
|
+
- 'null'
|
|
3433
|
+
propertyNames:
|
|
3434
|
+
type: string
|
|
3435
|
+
additionalProperties:
|
|
3436
|
+
type: number
|
|
2848
3437
|
computedForDay:
|
|
2849
3438
|
type: string
|
|
2850
3439
|
readOnly: true
|
|
@@ -3044,6 +3633,62 @@ components:
|
|
|
3044
3633
|
readOnly: true
|
|
3045
3634
|
description: (Read-only) Sum of amount for ACTIVE + MONTHLY recurring payments.
|
|
3046
3635
|
Always full recalc.
|
|
3636
|
+
escalatedOrdersCount:
|
|
3637
|
+
readOnly: true
|
|
3638
|
+
x-note: Absent on tenants whose metrics/current was last written before
|
|
3639
|
+
aggregator v2. Backfill required for universal presence (#8).
|
|
3640
|
+
description: (Read-only, Optional) Orders currently in an escalated state.
|
|
3641
|
+
Present once the current aggregator rewrites the document.
|
|
3642
|
+
type:
|
|
3643
|
+
- integer
|
|
3644
|
+
- 'null'
|
|
3645
|
+
minimum: -9007199254740991
|
|
3646
|
+
maximum: 9007199254740991
|
|
3647
|
+
staleOrdersCount:
|
|
3648
|
+
readOnly: true
|
|
3649
|
+
x-note: Absent on tenants whose metrics/current was last written before
|
|
3650
|
+
aggregator v2. Backfill required for universal presence (#8).
|
|
3651
|
+
description: (Read-only, Optional) Orders that have been in an incomplete
|
|
3652
|
+
status beyond the stale threshold.
|
|
3653
|
+
type:
|
|
3654
|
+
- integer
|
|
3655
|
+
- 'null'
|
|
3656
|
+
minimum: -9007199254740991
|
|
3657
|
+
maximum: 9007199254740991
|
|
3658
|
+
staleBookingsCount:
|
|
3659
|
+
readOnly: true
|
|
3660
|
+
x-note: Absent on tenants whose metrics/current was last written before
|
|
3661
|
+
aggregator v2. Backfill required for universal presence (#8).
|
|
3662
|
+
description: (Read-only, Optional) Bookings that have been in an incomplete
|
|
3663
|
+
status beyond the stale threshold.
|
|
3664
|
+
type:
|
|
3665
|
+
- integer
|
|
3666
|
+
- 'null'
|
|
3667
|
+
minimum: -9007199254740991
|
|
3668
|
+
maximum: 9007199254740991
|
|
3669
|
+
onHoldOrdersCount:
|
|
3670
|
+
readOnly: true
|
|
3671
|
+
x-note: Absent on tenants whose metrics/current was last written before
|
|
3672
|
+
aggregator v2. Backfill required for universal presence (#8).
|
|
3673
|
+
description: (Read-only, Optional) Orders currently in an on-hold state.
|
|
3674
|
+
type:
|
|
3675
|
+
- integer
|
|
3676
|
+
- 'null'
|
|
3677
|
+
minimum: -9007199254740991
|
|
3678
|
+
maximum: 9007199254740991
|
|
3679
|
+
paymentsByMethod:
|
|
3680
|
+
readOnly: true
|
|
3681
|
+
x-note: Always {} until the first real payment is recorded. Present on all
|
|
3682
|
+
tenants once rewritten by current aggregator (#8).
|
|
3683
|
+
description: (Read-only, Optional) Map of PaymentMethod → total amount for
|
|
3684
|
+
the current day. Empty map {} until first payment.
|
|
3685
|
+
type:
|
|
3686
|
+
- object
|
|
3687
|
+
- 'null'
|
|
3688
|
+
propertyNames:
|
|
3689
|
+
type: string
|
|
3690
|
+
additionalProperties:
|
|
3691
|
+
type: number
|
|
3047
3692
|
computedForDay:
|
|
3048
3693
|
type: string
|
|
3049
3694
|
readOnly: true
|
|
@@ -3263,9 +3908,11 @@ components:
|
|
|
3263
3908
|
- createdAt
|
|
3264
3909
|
additionalProperties: false
|
|
3265
3910
|
description: 'NotificationRecord — backend-written, multi-channel notification
|
|
3266
|
-
audit log (GH#48). Paths: companies/{cid}/
|
|
3267
|
-
companies/{cid}/orders/{oid}/
|
|
3268
|
-
Consumers read only. Distinct from WhatsappOutboundMessage
|
|
3911
|
+
audit log (GH#48). Paths: companies/{cid}/notification_records/{id} (always)
|
|
3912
|
+
and companies/{cid}/orders/{oid}/notification_records/{id} (dual-write when
|
|
3913
|
+
relatedEntity.type=order). Consumers read only. Distinct from WhatsappOutboundMessage
|
|
3914
|
+
(GH#43). Collection renamed from notifications → notification_records per
|
|
3915
|
+
decision #55 (2026-05-30).'
|
|
3269
3916
|
Order:
|
|
3270
3917
|
type: object
|
|
3271
3918
|
properties:
|
|
@@ -3282,20 +3929,22 @@ components:
|
|
|
3282
3929
|
type: string
|
|
3283
3930
|
x-immutable: true
|
|
3284
3931
|
description: (Immutable) FK → Company document ID. Scopes all queries.
|
|
3285
|
-
|
|
3932
|
+
appId:
|
|
3286
3933
|
x-immutable: true
|
|
3287
|
-
x-note: 'D43 / ADR-003: optional
|
|
3288
|
-
(legacy). When set, the order is
|
|
3289
|
-
|
|
3290
|
-
Flat path; Order continues to
|
|
3934
|
+
x-note: 'D43 / ADR-003: optional app attribution (renamed from siteId per
|
|
3935
|
+
D44). Absent/null means company-wide (legacy). When set, the order is
|
|
3936
|
+
attributed to a specific app for analytics and app-scoped dashboards.
|
|
3937
|
+
No migration — existing orders keep null. Flat path; Order continues to
|
|
3938
|
+
live at `companies/{companyId}/orders/{orderId}`.'
|
|
3291
3939
|
x-see:
|
|
3292
3940
|
decisions:
|
|
3293
3941
|
- D43
|
|
3294
|
-
|
|
3942
|
+
- D44
|
|
3943
|
+
x-when: 'Set at order creation when the client knows which app the order
|
|
3295
3944
|
originated from (e.g. SR Single, Lifesense). Leave null for legacy/company-wide
|
|
3296
|
-
orders. Composite index: (companyId,
|
|
3297
|
-
description: (Immutable, Optional) FK →
|
|
3298
|
-
null = company-wide.
|
|
3945
|
+
orders. Composite index: (companyId, appId, createdAt).'
|
|
3946
|
+
description: (Immutable, Optional) FK → App document ID (D43 / ADR-003,
|
|
3947
|
+
renamed from siteId per D44). null = company-wide.
|
|
3299
3948
|
type:
|
|
3300
3949
|
- string
|
|
3301
3950
|
- 'null'
|
|
@@ -3303,6 +3952,17 @@ components:
|
|
|
3303
3952
|
type: string
|
|
3304
3953
|
readOnly: true
|
|
3305
3954
|
description: (Read-only) Server-generated order number.
|
|
3955
|
+
followUpUrl:
|
|
3956
|
+
x-note: Standardized casing is followUpUrl (not followUpURL). Mobile legacy
|
|
3957
|
+
code reads both casings for backward compat but writes followUpUrl going
|
|
3958
|
+
forward (#6).
|
|
3959
|
+
x-when: 'Used by mobile to generate QR codes on printed receipts. If absent,
|
|
3960
|
+
the mobile app derives a deterministic fallback: https://zahoui.web.app/reviews?orderNumber={orderNumber}.'
|
|
3961
|
+
description: 'Optional URL for receipt QR code / post-order follow-up. Canonical
|
|
3962
|
+
casing: followUpUrl (#6).'
|
|
3963
|
+
type:
|
|
3964
|
+
- string
|
|
3965
|
+
- 'null'
|
|
3306
3966
|
status:
|
|
3307
3967
|
$ref: '#/components/schemas/OrderStatus'
|
|
3308
3968
|
description: Core lifecycle status (D34, MIG-11). See OrderStatus enum for
|
|
@@ -3485,7 +4145,9 @@ components:
|
|
|
3485
4145
|
readOnly: true
|
|
3486
4146
|
orderDate:
|
|
3487
4147
|
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
3488
|
-
description: Firestore Timestamp
|
|
4148
|
+
description: 'Firestore Timestamp — Admin SDK form: { _seconds, _nanoseconds
|
|
4149
|
+
}. See types/firestore.ts for REST API v1 and client SDK serialization
|
|
4150
|
+
notes (#10).'
|
|
3489
4151
|
PROCESSING_ON:
|
|
3490
4152
|
anyOf:
|
|
3491
4153
|
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
@@ -3530,7 +4192,9 @@ components:
|
|
|
3530
4192
|
anyOf:
|
|
3531
4193
|
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
3532
4194
|
- type: 'null'
|
|
3533
|
-
description: Firestore Timestamp
|
|
4195
|
+
description: 'Firestore Timestamp — Admin SDK form: { _seconds, _nanoseconds
|
|
4196
|
+
}. See types/firestore.ts for REST API v1 and client SDK serialization
|
|
4197
|
+
notes (#10).'
|
|
3534
4198
|
shippingCost:
|
|
3535
4199
|
type:
|
|
3536
4200
|
- number
|
|
@@ -3617,7 +4281,9 @@ components:
|
|
|
3617
4281
|
description: Payment method used (D02).
|
|
3618
4282
|
paymentDate:
|
|
3619
4283
|
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
3620
|
-
description: Firestore Timestamp
|
|
4284
|
+
description: 'Firestore Timestamp — Admin SDK form: { _seconds, _nanoseconds
|
|
4285
|
+
}. See types/firestore.ts for REST API v1 and client SDK serialization
|
|
4286
|
+
notes (#10).'
|
|
3621
4287
|
referenceNumber:
|
|
3622
4288
|
description: Payment reference (receipt number, transaction ID, etc.).
|
|
3623
4289
|
type: string
|
|
@@ -3831,6 +4497,235 @@ components:
|
|
|
3831
4497
|
description: Write payload for partial update (PATCH) of a OrderItem document.
|
|
3832
4498
|
All fields optional. Fields marked `readOnly` or `x-immutable` must not be
|
|
3833
4499
|
sent.
|
|
4500
|
+
OutboundPayment:
|
|
4501
|
+
type: object
|
|
4502
|
+
properties:
|
|
4503
|
+
id:
|
|
4504
|
+
readOnly: true
|
|
4505
|
+
description: (Read-only) Firestore document ID, auto-generated.
|
|
4506
|
+
type:
|
|
4507
|
+
- string
|
|
4508
|
+
- 'null'
|
|
4509
|
+
companyId:
|
|
4510
|
+
type: string
|
|
4511
|
+
x-immutable: true
|
|
4512
|
+
description: (Immutable) FK → Company document ID.
|
|
4513
|
+
payeeId:
|
|
4514
|
+
type: string
|
|
4515
|
+
x-immutable: true
|
|
4516
|
+
description: '(Immutable) FK → Payee document ID. Full Payee model tracked
|
|
4517
|
+
in #20.'
|
|
4518
|
+
contractId:
|
|
4519
|
+
x-immutable: true
|
|
4520
|
+
description: (Immutable, Optional) FK → Contract document ID. Absent for
|
|
4521
|
+
ad-hoc payments outside a formal contract.
|
|
4522
|
+
type:
|
|
4523
|
+
- string
|
|
4524
|
+
- 'null'
|
|
4525
|
+
amount:
|
|
4526
|
+
type: number
|
|
4527
|
+
description: Amount paid (XOF).
|
|
4528
|
+
currency:
|
|
4529
|
+
type: string
|
|
4530
|
+
const: XOF
|
|
4531
|
+
description: Currency code. Locked to XOF — consistent with Contract and
|
|
4532
|
+
CustomerPayment.
|
|
4533
|
+
method:
|
|
4534
|
+
$ref: '#/components/schemas/PaymentMethod'
|
|
4535
|
+
description: Payment method used (e.g. BANK_TRANSFER, MOBILE_MONEY, CHECK).
|
|
4536
|
+
reference:
|
|
4537
|
+
description: Optional payment reference — bank transaction number, check
|
|
4538
|
+
number, Wave ref, etc.
|
|
4539
|
+
type:
|
|
4540
|
+
- string
|
|
4541
|
+
- 'null'
|
|
4542
|
+
paidAt:
|
|
4543
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
4544
|
+
description: When the payment was made.
|
|
4545
|
+
notes:
|
|
4546
|
+
description: Optional internal notes.
|
|
4547
|
+
type:
|
|
4548
|
+
- string
|
|
4549
|
+
- 'null'
|
|
4550
|
+
createdBy:
|
|
4551
|
+
type: string
|
|
4552
|
+
x-immutable: true
|
|
4553
|
+
description: (Immutable) FK → User/staff UID who recorded the payment.
|
|
4554
|
+
createdAt:
|
|
4555
|
+
anyOf:
|
|
4556
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
4557
|
+
- type: 'null'
|
|
4558
|
+
readOnly: true
|
|
4559
|
+
description: (Read-only) Server-generated creation timestamp.
|
|
4560
|
+
updatedAt:
|
|
4561
|
+
anyOf:
|
|
4562
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
4563
|
+
- type: 'null'
|
|
4564
|
+
readOnly: true
|
|
4565
|
+
description: (Read-only) Server-generated update timestamp.
|
|
4566
|
+
required:
|
|
4567
|
+
- companyId
|
|
4568
|
+
- payeeId
|
|
4569
|
+
- amount
|
|
4570
|
+
- currency
|
|
4571
|
+
- method
|
|
4572
|
+
- paidAt
|
|
4573
|
+
- createdBy
|
|
4574
|
+
additionalProperties: false
|
|
4575
|
+
description: 'OutboundPayment (GH#15). Collection: companies/{companyId}/outboundPayments/{paymentId}.
|
|
4576
|
+
Single outbound transfer to a Payee. Canonical name chosen over SupplierPayment/VendorPayment
|
|
4577
|
+
— direction-based, agnostic of payee type. Currency locked to XOF.'
|
|
4578
|
+
OutboundPaymentCreate:
|
|
4579
|
+
allOf:
|
|
4580
|
+
- $ref: '#/components/schemas/OutboundPayment'
|
|
4581
|
+
description: Write payload for creating a new OutboundPayment document. Fields
|
|
4582
|
+
marked `readOnly` are server-set and must not be included. Fields marked `x-immutable`
|
|
4583
|
+
may be set once at creation.
|
|
4584
|
+
required:
|
|
4585
|
+
- companyId
|
|
4586
|
+
- payeeId
|
|
4587
|
+
- amount
|
|
4588
|
+
- currency
|
|
4589
|
+
- method
|
|
4590
|
+
- paidAt
|
|
4591
|
+
- createdBy
|
|
4592
|
+
OutboundPaymentUpdate:
|
|
4593
|
+
allOf:
|
|
4594
|
+
- $ref: '#/components/schemas/OutboundPayment'
|
|
4595
|
+
description: Write payload for partial update (PATCH) of a OutboundPayment document.
|
|
4596
|
+
All fields optional. Fields marked `readOnly` or `x-immutable` must not be
|
|
4597
|
+
sent.
|
|
4598
|
+
OutboundPaymentAllocation:
|
|
4599
|
+
type: object
|
|
4600
|
+
properties:
|
|
4601
|
+
id:
|
|
4602
|
+
readOnly: true
|
|
4603
|
+
description: (Read-only) Firestore document ID, auto-generated.
|
|
4604
|
+
type:
|
|
4605
|
+
- string
|
|
4606
|
+
- 'null'
|
|
4607
|
+
outboundPaymentId:
|
|
4608
|
+
type: string
|
|
4609
|
+
x-immutable: true
|
|
4610
|
+
description: (Immutable) FK → OutboundPayment document ID (parent).
|
|
4611
|
+
expenseId:
|
|
4612
|
+
type: string
|
|
4613
|
+
x-immutable: true
|
|
4614
|
+
description: '(Immutable) FK → Expense document ID. Full Expense model tracked
|
|
4615
|
+
in #20.'
|
|
4616
|
+
companyId:
|
|
4617
|
+
type: string
|
|
4618
|
+
x-immutable: true
|
|
4619
|
+
description: (Immutable) FK → Company document ID. Denormalized for collection-group
|
|
4620
|
+
queries.
|
|
4621
|
+
amount:
|
|
4622
|
+
type: number
|
|
4623
|
+
description: Amount of this payment allocated to the referenced expense
|
|
4624
|
+
(XOF).
|
|
4625
|
+
notes:
|
|
4626
|
+
description: Optional notes about this allocation.
|
|
4627
|
+
type:
|
|
4628
|
+
- string
|
|
4629
|
+
- 'null'
|
|
4630
|
+
allocatedAt:
|
|
4631
|
+
anyOf:
|
|
4632
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
4633
|
+
- type: 'null'
|
|
4634
|
+
readOnly: true
|
|
4635
|
+
description: (Read-only) When this allocation was recorded.
|
|
4636
|
+
required:
|
|
4637
|
+
- outboundPaymentId
|
|
4638
|
+
- expenseId
|
|
4639
|
+
- companyId
|
|
4640
|
+
- amount
|
|
4641
|
+
additionalProperties: false
|
|
4642
|
+
description: 'OutboundPaymentAllocation (GH#15). Subcollection: companies/{companyId}/outboundPayments/{paymentId}/allocations/{allocationId}.
|
|
4643
|
+
Links an OutboundPayment to an Expense. Supports partial and multi-expense
|
|
4644
|
+
allocations.'
|
|
4645
|
+
OutboundPaymentAllocationCreate:
|
|
4646
|
+
allOf:
|
|
4647
|
+
- $ref: '#/components/schemas/OutboundPaymentAllocation'
|
|
4648
|
+
description: Write payload for creating a new OutboundPaymentAllocation document.
|
|
4649
|
+
Fields marked `readOnly` are server-set and must not be included. Fields marked
|
|
4650
|
+
`x-immutable` may be set once at creation.
|
|
4651
|
+
required:
|
|
4652
|
+
- outboundPaymentId
|
|
4653
|
+
- expenseId
|
|
4654
|
+
- companyId
|
|
4655
|
+
- amount
|
|
4656
|
+
OutboundPaymentAllocationUpdate:
|
|
4657
|
+
allOf:
|
|
4658
|
+
- $ref: '#/components/schemas/OutboundPaymentAllocation'
|
|
4659
|
+
description: Write payload for partial update (PATCH) of a OutboundPaymentAllocation
|
|
4660
|
+
document. All fields optional. Fields marked `readOnly` or `x-immutable` must
|
|
4661
|
+
not be sent.
|
|
4662
|
+
PaymentWebhookEndpoint:
|
|
4663
|
+
type: object
|
|
4664
|
+
properties:
|
|
4665
|
+
token:
|
|
4666
|
+
type: string
|
|
4667
|
+
x-immutable: true
|
|
4668
|
+
description: (Immutable) base64url-encoded 24-byte random token. Also the
|
|
4669
|
+
Firestore document ID and the URL path segment.
|
|
4670
|
+
company:
|
|
4671
|
+
type: string
|
|
4672
|
+
x-immutable: true
|
|
4673
|
+
description: (Immutable) Company slug (e.g. gerko_studios). Identifies the
|
|
4674
|
+
tenant that owns this endpoint.
|
|
4675
|
+
provider:
|
|
4676
|
+
type: string
|
|
4677
|
+
enum:
|
|
4678
|
+
- wave
|
|
4679
|
+
- jeko
|
|
4680
|
+
x-immutable: true
|
|
4681
|
+
description: (Immutable) Payment provider whose webhooks this endpoint accepts.
|
|
4682
|
+
secret:
|
|
4683
|
+
type: string
|
|
4684
|
+
x-note: Provider-specific webhook signing secret. Used to verify HMAC-SHA256
|
|
4685
|
+
signatures on inbound payloads. Never expose to clients.
|
|
4686
|
+
readOnly: true
|
|
4687
|
+
description: Webhook signing secret for HMAC verification. Backend-only
|
|
4688
|
+
— never returned to dashboard or mobile clients.
|
|
4689
|
+
active:
|
|
4690
|
+
type: boolean
|
|
4691
|
+
description: Whether this endpoint is currently active. Inactive endpoints
|
|
4692
|
+
reject incoming webhooks.
|
|
4693
|
+
createdAt:
|
|
4694
|
+
anyOf:
|
|
4695
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
4696
|
+
- type: 'null'
|
|
4697
|
+
readOnly: true
|
|
4698
|
+
description: (Read-only) When this endpoint was provisioned.
|
|
4699
|
+
required:
|
|
4700
|
+
- token
|
|
4701
|
+
- company
|
|
4702
|
+
- provider
|
|
4703
|
+
- secret
|
|
4704
|
+
- active
|
|
4705
|
+
additionalProperties: false
|
|
4706
|
+
x-internal: true
|
|
4707
|
+
description: 'PaymentWebhookEndpoint (GH#41). Collection: payment_webhook_endpoints/{token}.
|
|
4708
|
+
Top-level, not tenant-scoped. Provisioned by superadmin; used by the backend
|
|
4709
|
+
to verify inbound payment webhooks from Wave and Jeko. The delivery log collection
|
|
4710
|
+
(raw webhook payloads + verification outcomes) is tracked in GH#41 — shape
|
|
4711
|
+
TBD.'
|
|
4712
|
+
PaymentWebhookEndpointCreate:
|
|
4713
|
+
allOf:
|
|
4714
|
+
- $ref: '#/components/schemas/PaymentWebhookEndpoint'
|
|
4715
|
+
description: Write payload for creating a new PaymentWebhookEndpoint document.
|
|
4716
|
+
Fields marked `readOnly` are server-set and must not be included. Fields marked
|
|
4717
|
+
`x-immutable` may be set once at creation.
|
|
4718
|
+
required:
|
|
4719
|
+
- token
|
|
4720
|
+
- company
|
|
4721
|
+
- provider
|
|
4722
|
+
- active
|
|
4723
|
+
PaymentWebhookEndpointUpdate:
|
|
4724
|
+
allOf:
|
|
4725
|
+
- $ref: '#/components/schemas/PaymentWebhookEndpoint'
|
|
4726
|
+
description: Write payload for partial update (PATCH) of a PaymentWebhookEndpoint
|
|
4727
|
+
document. All fields optional. Fields marked `readOnly` or `x-immutable` must
|
|
4728
|
+
not be sent.
|
|
3834
4729
|
Sale:
|
|
3835
4730
|
type: object
|
|
3836
4731
|
properties:
|
|
@@ -3895,7 +4790,9 @@ components:
|
|
|
3895
4790
|
- 'null'
|
|
3896
4791
|
purchaseDate:
|
|
3897
4792
|
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
3898
|
-
description: Firestore Timestamp
|
|
4793
|
+
description: 'Firestore Timestamp — Admin SDK form: { _seconds, _nanoseconds
|
|
4794
|
+
}. See types/firestore.ts for REST API v1 and client SDK serialization
|
|
4795
|
+
notes (#10).'
|
|
3899
4796
|
createdAt:
|
|
3900
4797
|
anyOf:
|
|
3901
4798
|
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
@@ -4631,6 +5528,86 @@ components:
|
|
|
4631
5528
|
description: Write payload for partial update (PATCH) of a Ticket document.
|
|
4632
5529
|
All fields optional. Fields marked `readOnly` or `x-immutable` must not be
|
|
4633
5530
|
sent.
|
|
5531
|
+
User:
|
|
5532
|
+
type: object
|
|
5533
|
+
properties:
|
|
5534
|
+
id:
|
|
5535
|
+
readOnly: true
|
|
5536
|
+
description: (Read-only) Firebase Auth UID. Matches the Firestore document
|
|
5537
|
+
ID.
|
|
5538
|
+
type:
|
|
5539
|
+
- string
|
|
5540
|
+
- 'null'
|
|
5541
|
+
displayName:
|
|
5542
|
+
description: User display name from Firebase Auth or manually set.
|
|
5543
|
+
type:
|
|
5544
|
+
- string
|
|
5545
|
+
- 'null'
|
|
5546
|
+
email:
|
|
5547
|
+
description: Email address. Present for email/Google auth users.
|
|
5548
|
+
type:
|
|
5549
|
+
- string
|
|
5550
|
+
- 'null'
|
|
5551
|
+
phoneE164:
|
|
5552
|
+
x-note: 'E.164 format with leading + (e.g. +2250777471485). Canonical phone
|
|
5553
|
+
identity field (decision #27). Distinct from wa_id (Meta conversation
|
|
5554
|
+
key). Server must normalize at write time: 8-digit CI local → prepend
|
|
5555
|
+
+225.'
|
|
5556
|
+
x-when: Set when the user authenticated via phone (WhatsApp OTP) or when
|
|
5557
|
+
a staff member's phone is known. Required for WhatsApp OTP lookup — add
|
|
5558
|
+
a Firestore composite index on phoneE164.
|
|
5559
|
+
description: E.164-normalized phone number (e.g. +2250777471485). Canonical
|
|
5560
|
+
phone identity field; used for WhatsApp OTP lookup via indexed query.
|
|
5561
|
+
type:
|
|
5562
|
+
- string
|
|
5563
|
+
- 'null'
|
|
5564
|
+
companyId:
|
|
5565
|
+
x-immutable: true
|
|
5566
|
+
description: (Immutable) FK → Company document ID. Present for staff accounts
|
|
5567
|
+
scoped to a company.
|
|
5568
|
+
type:
|
|
5569
|
+
- string
|
|
5570
|
+
- 'null'
|
|
5571
|
+
role:
|
|
5572
|
+
description: Staff role within the company (e.g. admin, manager, staff).
|
|
5573
|
+
Application-defined.
|
|
5574
|
+
type:
|
|
5575
|
+
- string
|
|
5576
|
+
- 'null'
|
|
5577
|
+
isActive:
|
|
5578
|
+
description: Whether this user account is active. Inactive accounts are
|
|
5579
|
+
denied access.
|
|
5580
|
+
type:
|
|
5581
|
+
- boolean
|
|
5582
|
+
- 'null'
|
|
5583
|
+
createdAt:
|
|
5584
|
+
anyOf:
|
|
5585
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
5586
|
+
- type: 'null'
|
|
5587
|
+
readOnly: true
|
|
5588
|
+
description: (Read-only) When the user document was created.
|
|
5589
|
+
updatedAt:
|
|
5590
|
+
anyOf:
|
|
5591
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
5592
|
+
- type: 'null'
|
|
5593
|
+
readOnly: true
|
|
5594
|
+
description: (Read-only) When the user document was last updated.
|
|
5595
|
+
additionalProperties: false
|
|
5596
|
+
description: 'User / staff account. Collection: users/{uid}. Document ID is
|
|
5597
|
+
always the Firebase Auth UID (decision #27). phoneE164 is the canonical E.164
|
|
5598
|
+
phone field for OTP lookup. Legacy phone-keyed documents must be migrated
|
|
5599
|
+
to uid-keyed docs with phoneE164 set.'
|
|
5600
|
+
UserCreate:
|
|
5601
|
+
allOf:
|
|
5602
|
+
- $ref: '#/components/schemas/User'
|
|
5603
|
+
description: Write payload for creating a new User document. Fields marked `readOnly`
|
|
5604
|
+
are server-set and must not be included. Fields marked `x-immutable` may be
|
|
5605
|
+
set once at creation.
|
|
5606
|
+
UserUpdate:
|
|
5607
|
+
allOf:
|
|
5608
|
+
- $ref: '#/components/schemas/User'
|
|
5609
|
+
description: Write payload for partial update (PATCH) of a User document. All
|
|
5610
|
+
fields optional. Fields marked `readOnly` or `x-immutable` must not be sent.
|
|
4634
5611
|
WhatsappInboundMessage:
|
|
4635
5612
|
type: object
|
|
4636
5613
|
properties:
|
|
@@ -4647,6 +5624,12 @@ components:
|
|
|
4647
5624
|
received the message.
|
|
4648
5625
|
waba:
|
|
4649
5626
|
$ref: '#/components/schemas/WabaLabel'
|
|
5627
|
+
x-note: 'cmz = "IngenX - Chez Miss Zahoui", phone number ID 446424085225188,
|
|
5628
|
+
used for chez_miss_zahoui_* companies. val = "IngenX - Valets", phone
|
|
5629
|
+
number ID 425582173979125, used for all other companies. Templates are
|
|
5630
|
+
approved at WABA level — if cmz and val share a WABA ID, all templates
|
|
5631
|
+
are available to both. Routing logic: functions/src/orders/order.ts#isSender2Company.
|
|
5632
|
+
See messaging/whatsapp-platform-constraints (#50).'
|
|
4650
5633
|
description: (Immutable) Human-readable WABA label (cmz | val). See WabaLabel
|
|
4651
5634
|
enum.
|
|
4652
5635
|
x-immutable: true
|
|
@@ -4849,10 +5832,26 @@ components:
|
|
|
4849
5832
|
to:
|
|
4850
5833
|
type: string
|
|
4851
5834
|
x-immutable: true
|
|
4852
|
-
|
|
4853
|
-
|
|
5835
|
+
x-note: 'This is the Meta wa_id (digits only, no leading +), NOT a literal
|
|
5836
|
+
E.164 string. Meta normalizes phone numbers in non-obvious ways (e.g.
|
|
5837
|
+
+2250777471485 → wa_id 22577471485, dropping the trunk zero). The only
|
|
5838
|
+
reliable source is Meta''s contacts[].wa_id from the send response — do
|
|
5839
|
+
not derive from E.164 by stripping + alone. The dashboard conversational
|
|
5840
|
+
sends and the whatsapp-server OTP path both use the wa_id form. Confirmed
|
|
5841
|
+
in prod: ING-368.'
|
|
5842
|
+
x-when: Set at enqueue time to the recipient's Meta wa_id. Use inbound WhatsappInboundMessage.from
|
|
5843
|
+
(also wa_id) as the join key for the conversation thread.
|
|
5844
|
+
description: (Immutable) Recipient Meta wa_id — digits only, no leading
|
|
5845
|
+
+ (e.g. 22577471485). Equal to the inbound `from` for the same conversation.
|
|
5846
|
+
NOT literal E.164; see x-note (#54).
|
|
4854
5847
|
waba:
|
|
4855
5848
|
$ref: '#/components/schemas/WabaLabel'
|
|
5849
|
+
x-note: 'cmz = "IngenX - Chez Miss Zahoui", phone number ID 446424085225188,
|
|
5850
|
+
used for chez_miss_zahoui_* companies. val = "IngenX - Valets", phone
|
|
5851
|
+
number ID 425582173979125, used for all other companies. Templates are
|
|
5852
|
+
approved at WABA level — if cmz and val share a WABA ID, all templates
|
|
5853
|
+
are available to both. Routing logic: functions/src/orders/order.ts#isSender2Company.
|
|
5854
|
+
See messaging/whatsapp-platform-constraints (#50).'
|
|
4856
5855
|
description: (Immutable) WABA that will send the message. Mirrors inbound
|
|
4857
5856
|
`waba`.
|
|
4858
5857
|
x-immutable: true
|
|
@@ -4938,6 +5937,9 @@ components:
|
|
|
4938
5937
|
after (sent → delivered → read, or failed).
|
|
4939
5938
|
wamid:
|
|
4940
5939
|
readOnly: true
|
|
5940
|
+
x-note: Useful for audit and dedup. Does NOT enable reply-threading for
|
|
5941
|
+
template messages — Meta silently ignores context.message_id on templates.
|
|
5942
|
+
Threading only works for kind=text within the 24-hour service window (#50).
|
|
4941
5943
|
description: (Read-only) WhatsApp message ID returned by Meta once the backend
|
|
4942
5944
|
sends. Absent while queued or on failure.
|
|
4943
5945
|
type:
|
|
@@ -5017,6 +6019,12 @@ components:
|
|
|
5017
6019
|
- 'null'
|
|
5018
6020
|
waba:
|
|
5019
6021
|
$ref: '#/components/schemas/WabaLabel'
|
|
6022
|
+
x-note: 'cmz = "IngenX - Chez Miss Zahoui", phone number ID 446424085225188,
|
|
6023
|
+
used for chez_miss_zahoui_* companies. val = "IngenX - Valets", phone
|
|
6024
|
+
number ID 425582173979125, used for all other companies. Templates are
|
|
6025
|
+
approved at WABA level — if cmz and val share a WABA ID, all templates
|
|
6026
|
+
are available to both. Routing logic: functions/src/orders/order.ts#isSender2Company.
|
|
6027
|
+
See messaging/whatsapp-platform-constraints (#50).'
|
|
5020
6028
|
description: (Read-only) WABA label this template is approved on. Templates
|
|
5021
6029
|
are WABA-scoped. Mirrors WhatsappOutboundMessage.waba.
|
|
5022
6030
|
readOnly: true
|