@ingenx-io/valets-schema-mcp-server 0.2.5 → 0.2.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.
- package/data/docs/collections/firestore-paths.md +20 -0
- package/data/docs/enums/app-status.md +1 -1
- package/data/docs/enums/attention-status.md +1 -1
- package/data/docs/enums/booking-status.md +1 -1
- 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/expense-payment-status.md +24 -0
- 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 +4 -3
- 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 +15 -6
- package/data/docs/models/allowed-user.md +1 -1
- package/data/docs/models/analytics-backfill.md +1 -1
- package/data/docs/models/analytics-daily.md +1 -1
- package/data/docs/models/analytics-event.md +1 -1
- package/data/docs/models/analytics-hourly.md +1 -1
- package/data/docs/models/app-payment.md +1 -1
- package/data/docs/models/app.md +45 -21
- package/data/docs/models/booking-version.md +1 -1
- package/data/docs/models/booking.md +1 -1
- package/data/docs/models/contract.md +454 -0
- package/data/docs/models/customer-payment-allocation.md +2 -2
- package/data/docs/models/customer-payment.md +23 -22
- package/data/docs/models/customer.md +2 -2
- package/data/docs/models/event.md +2 -2
- package/data/docs/models/expense.md +434 -0
- package/data/docs/models/loyalty-config.md +2 -2
- package/data/docs/models/loyalty-reward.md +2 -2
- package/data/docs/models/loyalty-status.md +2 -2
- package/data/docs/models/loyalty-transaction.md +2 -2
- package/data/docs/models/magic-link-request.md +2 -2
- package/data/docs/models/metrics-current.md +22 -2
- package/data/docs/models/metrics-daily.md +92 -41
- package/data/docs/models/metrics-monthly.md +22 -2
- package/data/docs/models/notification-record.md +2 -2
- package/data/docs/models/order-item.md +2 -2
- package/data/docs/models/order.md +291 -270
- package/data/docs/models/outbound-payment-allocation.md +195 -0
- package/data/docs/models/outbound-payment.md +319 -0
- package/data/docs/models/payment-webhook-delivery.md +321 -0
- package/data/docs/models/payment-webhook-endpoint.md +191 -0
- package/data/docs/models/sale.md +2 -2
- package/data/docs/models/site-payment.md +2 -2
- package/data/docs/models/site.md +2 -2
- package/data/docs/models/stocktake-item.md +2 -2
- package/data/docs/models/stocktake.md +2 -2
- package/data/docs/models/ticket.md +2 -2
- package/data/docs/models/user.md +2 -2
- 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 +39 -23
- package/data/docs/models/whatsapp-template.md +6 -2
- package/data/static/llms.txt +242 -10
- package/data/static/openapi.yaml +826 -23
- package/data/static/schemas.json +877 -71
- package/package.json +1 -1
package/data/static/openapi.yaml
CHANGED
|
@@ -51,6 +51,16 @@ components:
|
|
|
51
51
|
- COMPLETED_MIXED
|
|
52
52
|
description: Booking lifecycle status. COMPLETED_MIXED = some sessions completed,
|
|
53
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.
|
|
54
64
|
CustomerPaymentStatus:
|
|
55
65
|
type: string
|
|
56
66
|
enum:
|
|
@@ -99,6 +109,15 @@ components:
|
|
|
99
109
|
- COMPLETED
|
|
100
110
|
description: Ticketed event lifecycle (D32). Mobile-only today; Dashboard in
|
|
101
111
|
Wave 4.
|
|
112
|
+
ExpensePaymentStatus:
|
|
113
|
+
type: string
|
|
114
|
+
enum:
|
|
115
|
+
- PENDING
|
|
116
|
+
- PARTIALLY_PAID
|
|
117
|
+
- PAID
|
|
118
|
+
- FAILED
|
|
119
|
+
description: Payment status of an Expense. Stored enum — OVERDUE is not stored,
|
|
120
|
+
it is derived at read time from dueDate (#13).
|
|
102
121
|
FulfillmentStatus:
|
|
103
122
|
type: string
|
|
104
123
|
enum:
|
|
@@ -120,6 +139,14 @@ components:
|
|
|
120
139
|
- BONUS
|
|
121
140
|
- REFUND
|
|
122
141
|
description: Loyalty point transaction type (D07). SCREAMING_SNAKE past tense.
|
|
142
|
+
MilestoneStatus:
|
|
143
|
+
type: string
|
|
144
|
+
enum:
|
|
145
|
+
- PENDING
|
|
146
|
+
- INVOICED
|
|
147
|
+
- PAID
|
|
148
|
+
description: Status of a ContractMilestone (#17). PENDING = created, not yet
|
|
149
|
+
invoiced. INVOICED = invoice issued, awaiting payment. PAID = payment received.
|
|
123
150
|
NotificationChannel:
|
|
124
151
|
type: string
|
|
125
152
|
enum:
|
|
@@ -204,7 +231,11 @@ components:
|
|
|
204
231
|
- PAYPAL
|
|
205
232
|
- STRIPE
|
|
206
233
|
- OTHER
|
|
207
|
-
|
|
234
|
+
- OM
|
|
235
|
+
description: 'Unified payment method set with African + global methods (D02).
|
|
236
|
+
Note: the metrics writer historically emits "OM" instead of "ORANGE_MONEY"
|
|
237
|
+
as a paymentsByMethod map key — treat OM as deprecated; canonical value is
|
|
238
|
+
ORANGE_MONEY (#21).'
|
|
208
239
|
PaymentProofStatus:
|
|
209
240
|
type: string
|
|
210
241
|
enum:
|
|
@@ -309,8 +340,9 @@ components:
|
|
|
309
340
|
enum:
|
|
310
341
|
- cmz
|
|
311
342
|
- val
|
|
312
|
-
description:
|
|
313
|
-
|
|
343
|
+
description: WABA label identifying which Meta Business Account sent/received
|
|
344
|
+
the message. cmz = Chez Miss Zahoui sender; val = Valets sender. See WhatsApp
|
|
345
|
+
platform constraints doc (#50).
|
|
314
346
|
WhatsappButtonSubType:
|
|
315
347
|
type: string
|
|
316
348
|
enum:
|
|
@@ -1022,18 +1054,22 @@ components:
|
|
|
1022
1054
|
- string
|
|
1023
1055
|
- 'null'
|
|
1024
1056
|
status:
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1057
|
+
anyOf:
|
|
1058
|
+
- $ref: '#/components/schemas/AppStatus'
|
|
1059
|
+
- type: 'null'
|
|
1060
|
+
x-note: Real Firestore documents may be missing this field on pre-backfill
|
|
1061
|
+
records (#26). Treat absent as ACTIVE. A backfill script will populate
|
|
1062
|
+
status=ACTIVE on all existing documents; once confirmed, this field will
|
|
1063
|
+
be promoted to required.
|
|
1064
|
+
x-when: Written by operators via dashboard or by server triggers (expiration).
|
|
1065
|
+
Clients must not use server-side `where(status == ACTIVE)` until backfill
|
|
1066
|
+
is complete — filter client-side instead, treating absent as ACTIVE.
|
|
1067
|
+
description: Lifecycle status (D41/D44). Optional pending backfill of pre-existing
|
|
1068
|
+
records (#26) — treat absent as ACTIVE. Clients filter by ACTIVE.
|
|
1031
1069
|
x-see:
|
|
1032
1070
|
decisions:
|
|
1033
1071
|
- D41
|
|
1034
1072
|
- D44
|
|
1035
|
-
x-when: Written by operators via dashboard or by server triggers (expiration).
|
|
1036
|
-
Clients filter by ACTIVE.
|
|
1037
1073
|
deploymentLinks:
|
|
1038
1074
|
type: array
|
|
1039
1075
|
items:
|
|
@@ -1154,7 +1190,6 @@ components:
|
|
|
1154
1190
|
required:
|
|
1155
1191
|
- companyId
|
|
1156
1192
|
- name
|
|
1157
|
-
- status
|
|
1158
1193
|
- deploymentLinks
|
|
1159
1194
|
- createdBy
|
|
1160
1195
|
- analyticsEnabled
|
|
@@ -1172,7 +1207,6 @@ components:
|
|
|
1172
1207
|
required:
|
|
1173
1208
|
- companyId
|
|
1174
1209
|
- name
|
|
1175
|
-
- status
|
|
1176
1210
|
- deploymentLinks
|
|
1177
1211
|
- createdBy
|
|
1178
1212
|
- analyticsEnabled
|
|
@@ -1882,6 +1916,156 @@ components:
|
|
|
1882
1916
|
description: 'BookingVersion model (D18). Collection: companies/{companyId}/bookings/{bookingId}/versions/{versionId}.
|
|
1883
1917
|
Server-owned audit trail written by Firebase trigger on every Booking mutation.
|
|
1884
1918
|
Captures writes from all clients.'
|
|
1919
|
+
Contract:
|
|
1920
|
+
type: object
|
|
1921
|
+
properties:
|
|
1922
|
+
id:
|
|
1923
|
+
readOnly: true
|
|
1924
|
+
description: (Read-only) Firestore document ID, auto-generated.
|
|
1925
|
+
type:
|
|
1926
|
+
- string
|
|
1927
|
+
- 'null'
|
|
1928
|
+
companyId:
|
|
1929
|
+
type: string
|
|
1930
|
+
x-immutable: true
|
|
1931
|
+
description: (Immutable) FK → Company document ID.
|
|
1932
|
+
payeeId:
|
|
1933
|
+
type: string
|
|
1934
|
+
x-immutable: true
|
|
1935
|
+
description: '(Immutable) FK → Payee document ID. Full Payee model tracked
|
|
1936
|
+
in #20.'
|
|
1937
|
+
title:
|
|
1938
|
+
type: string
|
|
1939
|
+
description: Contract title or reference name shown in dashboards.
|
|
1940
|
+
description:
|
|
1941
|
+
description: Optional freeform description of the contract scope.
|
|
1942
|
+
type:
|
|
1943
|
+
- string
|
|
1944
|
+
- 'null'
|
|
1945
|
+
status:
|
|
1946
|
+
$ref: '#/components/schemas/ContractStatus'
|
|
1947
|
+
description: Contract lifecycle status (#14). Query by ACTIVE — do not use
|
|
1948
|
+
an isActive boolean.
|
|
1949
|
+
currency:
|
|
1950
|
+
type: string
|
|
1951
|
+
const: XOF
|
|
1952
|
+
description: Currency code. Locked to XOF (#18). Multi-currency support
|
|
1953
|
+
requires a deliberate schema version bump.
|
|
1954
|
+
totalAmount:
|
|
1955
|
+
type: number
|
|
1956
|
+
description: Total contract value (XOF).
|
|
1957
|
+
startDate:
|
|
1958
|
+
type: string
|
|
1959
|
+
description: Contract start date (ISO 8601 YYYY-MM-DD).
|
|
1960
|
+
endDate:
|
|
1961
|
+
description: Contract end date (ISO 8601 YYYY-MM-DD). Absent for open-ended
|
|
1962
|
+
contracts.
|
|
1963
|
+
type:
|
|
1964
|
+
- string
|
|
1965
|
+
- 'null'
|
|
1966
|
+
milestones:
|
|
1967
|
+
description: Ordered list of payment milestones. Embedded in the contract
|
|
1968
|
+
document (#17).
|
|
1969
|
+
type:
|
|
1970
|
+
- array
|
|
1971
|
+
- 'null'
|
|
1972
|
+
items:
|
|
1973
|
+
type: object
|
|
1974
|
+
properties:
|
|
1975
|
+
id:
|
|
1976
|
+
type: string
|
|
1977
|
+
description: Client-generated milestone ID (UUID or slug). Unique
|
|
1978
|
+
within the contract.
|
|
1979
|
+
title:
|
|
1980
|
+
type: string
|
|
1981
|
+
description: Milestone description or deliverable name.
|
|
1982
|
+
amount:
|
|
1983
|
+
type: number
|
|
1984
|
+
description: Amount due at this milestone (XOF).
|
|
1985
|
+
dueDate:
|
|
1986
|
+
description: ISO 8601 date string (YYYY-MM-DD) when the milestone
|
|
1987
|
+
is due. OVERDUE is derived at read time from dueDate — not stored.
|
|
1988
|
+
type: string
|
|
1989
|
+
status:
|
|
1990
|
+
$ref: '#/components/schemas/MilestoneStatus'
|
|
1991
|
+
x-note: Existing Firestore documents may have lowercase values (pending,
|
|
1992
|
+
invoiced, paid) from before this enum was introduced (#17). Normalize
|
|
1993
|
+
on read or via migration script.
|
|
1994
|
+
description: Milestone payment status (#17). OVERDUE is derived at
|
|
1995
|
+
read time from dueDate, not stored.
|
|
1996
|
+
invoicedAt:
|
|
1997
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
1998
|
+
description: When the invoice was issued for this milestone.
|
|
1999
|
+
paidAt:
|
|
2000
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
2001
|
+
description: When payment was received for this milestone.
|
|
2002
|
+
notes:
|
|
2003
|
+
description: Optional notes for this milestone.
|
|
2004
|
+
type: string
|
|
2005
|
+
required:
|
|
2006
|
+
- id
|
|
2007
|
+
- title
|
|
2008
|
+
- amount
|
|
2009
|
+
- status
|
|
2010
|
+
additionalProperties: false
|
|
2011
|
+
description: ContractMilestone — embedded sub-object on Contract (#17).
|
|
2012
|
+
Not a separate collection.
|
|
2013
|
+
notes:
|
|
2014
|
+
description: Optional internal notes.
|
|
2015
|
+
type:
|
|
2016
|
+
- string
|
|
2017
|
+
- 'null'
|
|
2018
|
+
createdBy:
|
|
2019
|
+
type: string
|
|
2020
|
+
x-immutable: true
|
|
2021
|
+
description: (Immutable) FK → User/staff UID who created the contract.
|
|
2022
|
+
createdAt:
|
|
2023
|
+
anyOf:
|
|
2024
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
2025
|
+
- type: 'null'
|
|
2026
|
+
readOnly: true
|
|
2027
|
+
description: (Read-only) Server-generated creation timestamp.
|
|
2028
|
+
updatedAt:
|
|
2029
|
+
anyOf:
|
|
2030
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
2031
|
+
- type: 'null'
|
|
2032
|
+
readOnly: true
|
|
2033
|
+
description: (Read-only) Server-generated update timestamp.
|
|
2034
|
+
required:
|
|
2035
|
+
- companyId
|
|
2036
|
+
- payeeId
|
|
2037
|
+
- title
|
|
2038
|
+
- status
|
|
2039
|
+
- currency
|
|
2040
|
+
- totalAmount
|
|
2041
|
+
- startDate
|
|
2042
|
+
- createdBy
|
|
2043
|
+
additionalProperties: false
|
|
2044
|
+
description: 'Contract model (GH#14/#17/#18). Collection: companies/{companyId}/contracts/{contractId}.
|
|
2045
|
+
Service/supplier contract between a company and a Payee. No isActive field
|
|
2046
|
+
— query by status. Currency locked to XOF. Milestones use MilestoneStatus
|
|
2047
|
+
enum (no stored OVERDUE).'
|
|
2048
|
+
ContractCreate:
|
|
2049
|
+
allOf:
|
|
2050
|
+
- $ref: '#/components/schemas/Contract'
|
|
2051
|
+
description: Write payload for creating a new Contract document. Fields marked
|
|
2052
|
+
`readOnly` are server-set and must not be included. Fields marked `x-immutable`
|
|
2053
|
+
may be set once at creation.
|
|
2054
|
+
required:
|
|
2055
|
+
- companyId
|
|
2056
|
+
- payeeId
|
|
2057
|
+
- title
|
|
2058
|
+
- status
|
|
2059
|
+
- currency
|
|
2060
|
+
- totalAmount
|
|
2061
|
+
- startDate
|
|
2062
|
+
- createdBy
|
|
2063
|
+
ContractUpdate:
|
|
2064
|
+
allOf:
|
|
2065
|
+
- $ref: '#/components/schemas/Contract'
|
|
2066
|
+
description: Write payload for partial update (PATCH) of a Contract document.
|
|
2067
|
+
All fields optional. Fields marked `readOnly` or `x-immutable` must not be
|
|
2068
|
+
sent.
|
|
1885
2069
|
Customer:
|
|
1886
2070
|
type: object
|
|
1887
2071
|
properties:
|
|
@@ -2052,7 +2236,10 @@ components:
|
|
|
2052
2236
|
notes (#10).'
|
|
2053
2237
|
paymentMethod:
|
|
2054
2238
|
$ref: '#/components/schemas/PaymentMethod'
|
|
2055
|
-
description: Unified payment method set with African + global methods (D02).
|
|
2239
|
+
description: 'Unified payment method set with African + global methods (D02).
|
|
2240
|
+
Note: the metrics writer historically emits "OM" instead of "ORANGE_MONEY"
|
|
2241
|
+
as a paymentsByMethod map key — treat OM as deprecated; canonical value
|
|
2242
|
+
is ORANGE_MONEY (#21).'
|
|
2056
2243
|
referenceNumber:
|
|
2057
2244
|
type: string
|
|
2058
2245
|
description: Unique payment reference (receipt number, transaction ID, etc.).
|
|
@@ -2349,6 +2536,146 @@ components:
|
|
|
2349
2536
|
- $ref: '#/components/schemas/Event'
|
|
2350
2537
|
description: Write payload for partial update (PATCH) of a Event document. All
|
|
2351
2538
|
fields optional. Fields marked `readOnly` or `x-immutable` must not be sent.
|
|
2539
|
+
Expense:
|
|
2540
|
+
type: object
|
|
2541
|
+
properties:
|
|
2542
|
+
id:
|
|
2543
|
+
readOnly: true
|
|
2544
|
+
description: (Read-only) Firestore document ID, auto-generated.
|
|
2545
|
+
type:
|
|
2546
|
+
- string
|
|
2547
|
+
- 'null'
|
|
2548
|
+
companyId:
|
|
2549
|
+
type: string
|
|
2550
|
+
x-immutable: true
|
|
2551
|
+
description: (Immutable) FK → Company document ID.
|
|
2552
|
+
title:
|
|
2553
|
+
type: string
|
|
2554
|
+
description: Human-readable expense title (e.g. "Loyer mars 2026", "Facture
|
|
2555
|
+
EAU").
|
|
2556
|
+
description:
|
|
2557
|
+
description: Optional longer description or notes.
|
|
2558
|
+
type:
|
|
2559
|
+
- string
|
|
2560
|
+
- 'null'
|
|
2561
|
+
amount:
|
|
2562
|
+
type: number
|
|
2563
|
+
description: Total expense amount (XOF).
|
|
2564
|
+
currency:
|
|
2565
|
+
type: string
|
|
2566
|
+
const: XOF
|
|
2567
|
+
description: Currency code. Locked to XOF.
|
|
2568
|
+
dueDate:
|
|
2569
|
+
anyOf:
|
|
2570
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
2571
|
+
- type: 'null'
|
|
2572
|
+
description: When the expense is due. Used to compute OVERDUE state at read
|
|
2573
|
+
time (not stored in paymentStatus).
|
|
2574
|
+
paymentStatus:
|
|
2575
|
+
$ref: '#/components/schemas/ExpensePaymentStatus'
|
|
2576
|
+
x-note: 'OVERDUE is intentionally excluded — it is never stored in Firestore.
|
|
2577
|
+
Compute it at read time: expense.paymentStatus !== PAID && expense.dueDate
|
|
2578
|
+
< now() (#13). Helper: isExpenseOverdue(expense: Expense): boolean.'
|
|
2579
|
+
description: Current payment status. OVERDUE is never stored — derive from
|
|
2580
|
+
dueDate at read time (#13).
|
|
2581
|
+
amountDue:
|
|
2582
|
+
x-note: Authoritative for simple (non-allocation) expenses. Legacy field
|
|
2583
|
+
maintained for backward compatibility when no OutboundPaymentAllocation
|
|
2584
|
+
records exist (#12).
|
|
2585
|
+
description: Amount still owed. Authoritative when no OutboundPaymentAllocation
|
|
2586
|
+
records exist for this expense.
|
|
2587
|
+
type:
|
|
2588
|
+
- number
|
|
2589
|
+
- 'null'
|
|
2590
|
+
amountPaid:
|
|
2591
|
+
description: Amount paid to date (simple tracking, no allocations).
|
|
2592
|
+
type:
|
|
2593
|
+
- number
|
|
2594
|
+
- 'null'
|
|
2595
|
+
allocatedAmount:
|
|
2596
|
+
readOnly: true
|
|
2597
|
+
x-note: Server-set — computed from OutboundPaymentAllocation records. Clients
|
|
2598
|
+
must never write this field (#12).
|
|
2599
|
+
description: (Read-only) Total amount allocated via OutboundPaymentAllocation
|
|
2600
|
+
records. Authoritative when allocations exist.
|
|
2601
|
+
type:
|
|
2602
|
+
- number
|
|
2603
|
+
- 'null'
|
|
2604
|
+
balance:
|
|
2605
|
+
readOnly: true
|
|
2606
|
+
x-note: Server-set — computed as amount - allocatedAmount. Authoritative
|
|
2607
|
+
remaining amount when allocations exist. Prefer this over amountDue when
|
|
2608
|
+
OutboundPaymentAllocation records are present (#12).
|
|
2609
|
+
description: '(Read-only) Remaining balance: amount minus allocatedAmount.
|
|
2610
|
+
Authoritative when OutboundPaymentAllocation records exist.'
|
|
2611
|
+
type:
|
|
2612
|
+
- number
|
|
2613
|
+
- 'null'
|
|
2614
|
+
paidDate:
|
|
2615
|
+
anyOf:
|
|
2616
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
2617
|
+
- type: 'null'
|
|
2618
|
+
x-when: Set when paymentStatus transitions to PAID (fully settled). Null
|
|
2619
|
+
for partially paid or unpaid expenses. For multi-payment history, read
|
|
2620
|
+
OutboundPaymentAllocation records (#19).
|
|
2621
|
+
description: When the expense was fully settled (paymentStatus = PAID).
|
|
2622
|
+
Null otherwise.
|
|
2623
|
+
paymentReference:
|
|
2624
|
+
x-note: Reference for the most recent payment transaction (check number,
|
|
2625
|
+
wire ID, Wave ref, etc.). Overwritten on each payment. For full payment
|
|
2626
|
+
history read OutboundPaymentAllocation records (#19).
|
|
2627
|
+
description: Most recent payment transaction reference. Overwritten on each
|
|
2628
|
+
payment; not a full history.
|
|
2629
|
+
type:
|
|
2630
|
+
- string
|
|
2631
|
+
- 'null'
|
|
2632
|
+
createdBy:
|
|
2633
|
+
type: string
|
|
2634
|
+
x-immutable: true
|
|
2635
|
+
description: (Immutable) FK → User/staff UID who created this expense record.
|
|
2636
|
+
createdAt:
|
|
2637
|
+
anyOf:
|
|
2638
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
2639
|
+
- type: 'null'
|
|
2640
|
+
readOnly: true
|
|
2641
|
+
description: (Read-only) Server-generated creation timestamp.
|
|
2642
|
+
updatedAt:
|
|
2643
|
+
anyOf:
|
|
2644
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
2645
|
+
- type: 'null'
|
|
2646
|
+
readOnly: true
|
|
2647
|
+
description: (Read-only) Server-generated last-update timestamp.
|
|
2648
|
+
required:
|
|
2649
|
+
- companyId
|
|
2650
|
+
- title
|
|
2651
|
+
- amount
|
|
2652
|
+
- currency
|
|
2653
|
+
- paymentStatus
|
|
2654
|
+
- createdBy
|
|
2655
|
+
additionalProperties: false
|
|
2656
|
+
description: 'Expense (GH#12/#13/#19 partial). Collection: companies/{companyId}/expenses/{expenseId}.
|
|
2657
|
+
Dual balance tracking: amountPaid/amountDue for simple expenses; allocatedAmount/balance
|
|
2658
|
+
(server-set) for allocation-settled expenses. OVERDUE excluded from stored
|
|
2659
|
+
enum — derive at read time. Full domain (Payee FK, Contract FK) in #20.'
|
|
2660
|
+
ExpenseCreate:
|
|
2661
|
+
allOf:
|
|
2662
|
+
- $ref: '#/components/schemas/Expense'
|
|
2663
|
+
description: Write payload for creating a new Expense document. Fields marked
|
|
2664
|
+
`readOnly` are server-set and must not be included. Fields marked `x-immutable`
|
|
2665
|
+
may be set once at creation.
|
|
2666
|
+
required:
|
|
2667
|
+
- companyId
|
|
2668
|
+
- title
|
|
2669
|
+
- amount
|
|
2670
|
+
- currency
|
|
2671
|
+
- paymentStatus
|
|
2672
|
+
- createdBy
|
|
2673
|
+
ExpenseUpdate:
|
|
2674
|
+
allOf:
|
|
2675
|
+
- $ref: '#/components/schemas/Expense'
|
|
2676
|
+
description: Write payload for partial update (PATCH) of a Expense document.
|
|
2677
|
+
All fields optional. Fields marked `readOnly` or `x-immutable` must not be
|
|
2678
|
+
sent.
|
|
2352
2679
|
LoyaltyConfig:
|
|
2353
2680
|
type: object
|
|
2354
2681
|
properties:
|
|
@@ -2835,6 +3162,9 @@ components:
|
|
|
2835
3162
|
orderCompletionRate30d:
|
|
2836
3163
|
type: number
|
|
2837
3164
|
readOnly: true
|
|
3165
|
+
x-note: Firestore REST API v1 writes integerValue when the stored value
|
|
3166
|
+
is whole (e.g. 0), doubleValue when fractional (e.g. 82.17). Admin SDK
|
|
3167
|
+
smooths this to a JS number; REST clients must coerce the union (#11).
|
|
2838
3168
|
description: (Read-only) Percentage of orders completed or delivered in
|
|
2839
3169
|
the last 30 days. Always full recalc.
|
|
2840
3170
|
todayPurchasesCount:
|
|
@@ -2851,11 +3181,16 @@ components:
|
|
|
2851
3181
|
averagePurchaseAmount:
|
|
2852
3182
|
type: number
|
|
2853
3183
|
readOnly: true
|
|
3184
|
+
x-note: Firestore REST API v1 writes integerValue when whole (e.g. 10070),
|
|
3185
|
+
doubleValue when fractional (e.g. 10006.5). Admin SDK smooths this; REST
|
|
3186
|
+
clients must coerce (#11).
|
|
2854
3187
|
description: (Read-only) Average purchase value across last 200 purchases
|
|
2855
3188
|
(rolling, not time-windowed).
|
|
2856
3189
|
monthlyRevenue:
|
|
2857
3190
|
type: number
|
|
2858
3191
|
readOnly: true
|
|
3192
|
+
x-note: Observed as integerValue on all sampled tenants (whole XOF amounts).
|
|
3193
|
+
Will be doubleValue if fractional. REST clients must coerce (#11).
|
|
2859
3194
|
description: (Read-only) Total purchase value in the current calendar month
|
|
2860
3195
|
(UTC).
|
|
2861
3196
|
monthlyPurchasesCount:
|
|
@@ -2892,6 +3227,8 @@ components:
|
|
|
2892
3227
|
todayCollectedAmount:
|
|
2893
3228
|
type: number
|
|
2894
3229
|
readOnly: true
|
|
3230
|
+
x-note: Observed as integerValue "0" on all sampled tenants. Will be doubleValue
|
|
3231
|
+
if fractional payments occur. REST clients must coerce (#11).
|
|
2895
3232
|
description: (Read-only) Sum of totalAmount for bookings where PAYMENT_PAID_AT
|
|
2896
3233
|
is today. Resets at midnight.
|
|
2897
3234
|
todayRevenue:
|
|
@@ -2937,6 +3274,8 @@ components:
|
|
|
2937
3274
|
averageRating:
|
|
2938
3275
|
type: number
|
|
2939
3276
|
readOnly: true
|
|
3277
|
+
x-note: Observed as integerValue "0" on all tenants (no reviews yet). Will
|
|
3278
|
+
be doubleValue once real ratings exist. REST clients must coerce (#11).
|
|
2940
3279
|
description: (Read-only) Average rating from the last 200 reviews (rolling).
|
|
2941
3280
|
Always full recalc.
|
|
2942
3281
|
lowStockItemsCount:
|
|
@@ -3084,6 +3423,9 @@ components:
|
|
|
3084
3423
|
orderCompletionRate30d:
|
|
3085
3424
|
type: number
|
|
3086
3425
|
readOnly: true
|
|
3426
|
+
x-note: Firestore REST API v1 writes integerValue when the stored value
|
|
3427
|
+
is whole (e.g. 0), doubleValue when fractional (e.g. 82.17). Admin SDK
|
|
3428
|
+
smooths this to a JS number; REST clients must coerce the union (#11).
|
|
3087
3429
|
description: (Read-only) Percentage of orders completed or delivered in
|
|
3088
3430
|
the last 30 days. Always full recalc.
|
|
3089
3431
|
todayPurchasesCount:
|
|
@@ -3100,11 +3442,16 @@ components:
|
|
|
3100
3442
|
averagePurchaseAmount:
|
|
3101
3443
|
type: number
|
|
3102
3444
|
readOnly: true
|
|
3445
|
+
x-note: Firestore REST API v1 writes integerValue when whole (e.g. 10070),
|
|
3446
|
+
doubleValue when fractional (e.g. 10006.5). Admin SDK smooths this; REST
|
|
3447
|
+
clients must coerce (#11).
|
|
3103
3448
|
description: (Read-only) Average purchase value across last 200 purchases
|
|
3104
3449
|
(rolling, not time-windowed).
|
|
3105
3450
|
monthlyRevenue:
|
|
3106
3451
|
type: number
|
|
3107
3452
|
readOnly: true
|
|
3453
|
+
x-note: Observed as integerValue on all sampled tenants (whole XOF amounts).
|
|
3454
|
+
Will be doubleValue if fractional. REST clients must coerce (#11).
|
|
3108
3455
|
description: (Read-only) Total purchase value in the current calendar month
|
|
3109
3456
|
(UTC).
|
|
3110
3457
|
monthlyPurchasesCount:
|
|
@@ -3141,6 +3488,8 @@ components:
|
|
|
3141
3488
|
todayCollectedAmount:
|
|
3142
3489
|
type: number
|
|
3143
3490
|
readOnly: true
|
|
3491
|
+
x-note: Observed as integerValue "0" on all sampled tenants. Will be doubleValue
|
|
3492
|
+
if fractional payments occur. REST clients must coerce (#11).
|
|
3144
3493
|
description: (Read-only) Sum of totalAmount for bookings where PAYMENT_PAID_AT
|
|
3145
3494
|
is today. Resets at midnight.
|
|
3146
3495
|
todayRevenue:
|
|
@@ -3186,6 +3535,8 @@ components:
|
|
|
3186
3535
|
averageRating:
|
|
3187
3536
|
type: number
|
|
3188
3537
|
readOnly: true
|
|
3538
|
+
x-note: Observed as integerValue "0" on all tenants (no reviews yet). Will
|
|
3539
|
+
be doubleValue once real ratings exist. REST clients must coerce (#11).
|
|
3189
3540
|
description: (Read-only) Average rating from the last 200 reviews (rolling).
|
|
3190
3541
|
Always full recalc.
|
|
3191
3542
|
lowStockItemsCount:
|
|
@@ -3252,17 +3603,34 @@ components:
|
|
|
3252
3603
|
maximum: 9007199254740991
|
|
3253
3604
|
paymentsByMethod:
|
|
3254
3605
|
readOnly: true
|
|
3255
|
-
x-note:
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3606
|
+
x-note: Map keys use short codes in practice (OM, CASH, WAVE) — OM is a
|
|
3607
|
+
non-canonical alias for ORANGE_MONEY emitted by the metrics writer (#21).
|
|
3608
|
+
Value shape { total, count } differs from MetricsCurrent.paymentsByMethod
|
|
3609
|
+
(bare number).
|
|
3610
|
+
description: '(Read-only, Optional) Payment breakdown by method for the
|
|
3611
|
+
day. Keys are PaymentMethod values (or legacy short code OM). Value is
|
|
3612
|
+
{ total: XOF amount, count: number of payments }.'
|
|
3259
3613
|
type:
|
|
3260
3614
|
- object
|
|
3261
3615
|
- 'null'
|
|
3262
3616
|
propertyNames:
|
|
3263
3617
|
type: string
|
|
3264
3618
|
additionalProperties:
|
|
3265
|
-
type:
|
|
3619
|
+
type: object
|
|
3620
|
+
properties:
|
|
3621
|
+
total:
|
|
3622
|
+
type: number
|
|
3623
|
+
description: Sum of payment amounts for this method on the given day
|
|
3624
|
+
(XOF).
|
|
3625
|
+
count:
|
|
3626
|
+
type: integer
|
|
3627
|
+
minimum: -9007199254740991
|
|
3628
|
+
maximum: 9007199254740991
|
|
3629
|
+
description: Number of payments using this method on the given day.
|
|
3630
|
+
required:
|
|
3631
|
+
- total
|
|
3632
|
+
- count
|
|
3633
|
+
additionalProperties: false
|
|
3266
3634
|
computedForDay:
|
|
3267
3635
|
type: string
|
|
3268
3636
|
readOnly: true
|
|
@@ -3305,9 +3673,17 @@ components:
|
|
|
3305
3673
|
- generatedAt
|
|
3306
3674
|
- date
|
|
3307
3675
|
additionalProperties: false
|
|
3676
|
+
x-note: 'Zero-activity behavior (#9): the computeDailyCompanyMetrics cron (02:00
|
|
3677
|
+
UTC) does NOT write a snapshot for days with no activity. A missing document
|
|
3678
|
+
means either zero activity or the cron did not run — consumers cannot distinguish
|
|
3679
|
+
the two from the absence alone. To detect cron gaps, compare the latest document
|
|
3680
|
+
date with today; a gap larger than 1 day on an otherwise active tenant indicates
|
|
3681
|
+
a cron failure. Observed: 3 of 4 zahoui tenants had gaps; bingerville (active)
|
|
3682
|
+
had a document every day.'
|
|
3308
3683
|
description: 'Daily metrics snapshot. Collection: companies/{companyId}/metrics_daily/{YYYY-MM-DD}.
|
|
3309
3684
|
Same fields as MetricsCurrent plus `date`. Written by computeDailyCompanyMetrics
|
|
3310
|
-
cron (02:00 UTC)
|
|
3685
|
+
cron (02:00 UTC) when the company had activity that day; zero-activity days
|
|
3686
|
+
may produce no document (#9).'
|
|
3311
3687
|
MetricsDailyCreate:
|
|
3312
3688
|
allOf:
|
|
3313
3689
|
- $ref: '#/components/schemas/MetricsDaily'
|
|
@@ -3339,6 +3715,9 @@ components:
|
|
|
3339
3715
|
orderCompletionRate30d:
|
|
3340
3716
|
type: number
|
|
3341
3717
|
readOnly: true
|
|
3718
|
+
x-note: Firestore REST API v1 writes integerValue when the stored value
|
|
3719
|
+
is whole (e.g. 0), doubleValue when fractional (e.g. 82.17). Admin SDK
|
|
3720
|
+
smooths this to a JS number; REST clients must coerce the union (#11).
|
|
3342
3721
|
description: (Read-only) Percentage of orders completed or delivered in
|
|
3343
3722
|
the last 30 days. Always full recalc.
|
|
3344
3723
|
todayPurchasesCount:
|
|
@@ -3355,11 +3734,16 @@ components:
|
|
|
3355
3734
|
averagePurchaseAmount:
|
|
3356
3735
|
type: number
|
|
3357
3736
|
readOnly: true
|
|
3737
|
+
x-note: Firestore REST API v1 writes integerValue when whole (e.g. 10070),
|
|
3738
|
+
doubleValue when fractional (e.g. 10006.5). Admin SDK smooths this; REST
|
|
3739
|
+
clients must coerce (#11).
|
|
3358
3740
|
description: (Read-only) Average purchase value across last 200 purchases
|
|
3359
3741
|
(rolling, not time-windowed).
|
|
3360
3742
|
monthlyRevenue:
|
|
3361
3743
|
type: number
|
|
3362
3744
|
readOnly: true
|
|
3745
|
+
x-note: Observed as integerValue on all sampled tenants (whole XOF amounts).
|
|
3746
|
+
Will be doubleValue if fractional. REST clients must coerce (#11).
|
|
3363
3747
|
description: (Read-only) Total purchase value in the current calendar month
|
|
3364
3748
|
(UTC).
|
|
3365
3749
|
monthlyPurchasesCount:
|
|
@@ -3396,6 +3780,8 @@ components:
|
|
|
3396
3780
|
todayCollectedAmount:
|
|
3397
3781
|
type: number
|
|
3398
3782
|
readOnly: true
|
|
3783
|
+
x-note: Observed as integerValue "0" on all sampled tenants. Will be doubleValue
|
|
3784
|
+
if fractional payments occur. REST clients must coerce (#11).
|
|
3399
3785
|
description: (Read-only) Sum of totalAmount for bookings where PAYMENT_PAID_AT
|
|
3400
3786
|
is today. Resets at midnight.
|
|
3401
3787
|
todayRevenue:
|
|
@@ -3441,6 +3827,8 @@ components:
|
|
|
3441
3827
|
averageRating:
|
|
3442
3828
|
type: number
|
|
3443
3829
|
readOnly: true
|
|
3830
|
+
x-note: Observed as integerValue "0" on all tenants (no reviews yet). Will
|
|
3831
|
+
be doubleValue once real ratings exist. REST clients must coerce (#11).
|
|
3444
3832
|
description: (Read-only) Average rating from the last 200 reviews (rolling).
|
|
3445
3833
|
Always full recalc.
|
|
3446
3834
|
lowStockItemsCount:
|
|
@@ -3781,6 +4169,17 @@ components:
|
|
|
3781
4169
|
type: string
|
|
3782
4170
|
readOnly: true
|
|
3783
4171
|
description: (Read-only) Server-generated order number.
|
|
4172
|
+
followUpUrl:
|
|
4173
|
+
x-note: Standardized casing is followUpUrl (not followUpURL). Mobile legacy
|
|
4174
|
+
code reads both casings for backward compat but writes followUpUrl going
|
|
4175
|
+
forward (#6).
|
|
4176
|
+
x-when: 'Used by mobile to generate QR codes on printed receipts. If absent,
|
|
4177
|
+
the mobile app derives a deterministic fallback: https://zahoui.web.app/reviews?orderNumber={orderNumber}.'
|
|
4178
|
+
description: 'Optional URL for receipt QR code / post-order follow-up. Canonical
|
|
4179
|
+
casing: followUpUrl (#6).'
|
|
4180
|
+
type:
|
|
4181
|
+
- string
|
|
4182
|
+
- 'null'
|
|
3784
4183
|
status:
|
|
3785
4184
|
$ref: '#/components/schemas/OrderStatus'
|
|
3786
4185
|
description: Core lifecycle status (D34, MIG-11). See OrderStatus enum for
|
|
@@ -3879,7 +4278,10 @@ components:
|
|
|
3879
4278
|
anyOf:
|
|
3880
4279
|
- $ref: '#/components/schemas/PaymentMethod'
|
|
3881
4280
|
- type: 'null'
|
|
3882
|
-
description: Unified payment method set with African + global methods (D02).
|
|
4281
|
+
description: 'Unified payment method set with African + global methods (D02).
|
|
4282
|
+
Note: the metrics writer historically emits "OM" instead of "ORANGE_MONEY"
|
|
4283
|
+
as a paymentsByMethod map key — treat OM as deprecated; canonical value
|
|
4284
|
+
is ORANGE_MONEY (#21).'
|
|
3883
4285
|
invoiceId:
|
|
3884
4286
|
description: FK → Invoice document ID.
|
|
3885
4287
|
type:
|
|
@@ -4315,6 +4717,376 @@ components:
|
|
|
4315
4717
|
description: Write payload for partial update (PATCH) of a OrderItem document.
|
|
4316
4718
|
All fields optional. Fields marked `readOnly` or `x-immutable` must not be
|
|
4317
4719
|
sent.
|
|
4720
|
+
OutboundPayment:
|
|
4721
|
+
type: object
|
|
4722
|
+
properties:
|
|
4723
|
+
id:
|
|
4724
|
+
readOnly: true
|
|
4725
|
+
description: (Read-only) Firestore document ID, auto-generated.
|
|
4726
|
+
type:
|
|
4727
|
+
- string
|
|
4728
|
+
- 'null'
|
|
4729
|
+
companyId:
|
|
4730
|
+
type: string
|
|
4731
|
+
x-immutable: true
|
|
4732
|
+
description: (Immutable) FK → Company document ID.
|
|
4733
|
+
payeeId:
|
|
4734
|
+
type: string
|
|
4735
|
+
x-immutable: true
|
|
4736
|
+
description: '(Immutable) FK → Payee document ID. Full Payee model tracked
|
|
4737
|
+
in #20.'
|
|
4738
|
+
contractId:
|
|
4739
|
+
x-immutable: true
|
|
4740
|
+
description: (Immutable, Optional) FK → Contract document ID. Absent for
|
|
4741
|
+
ad-hoc payments outside a formal contract.
|
|
4742
|
+
type:
|
|
4743
|
+
- string
|
|
4744
|
+
- 'null'
|
|
4745
|
+
amount:
|
|
4746
|
+
type: number
|
|
4747
|
+
description: Amount paid (XOF).
|
|
4748
|
+
currency:
|
|
4749
|
+
type: string
|
|
4750
|
+
const: XOF
|
|
4751
|
+
description: Currency code. Locked to XOF — consistent with Contract and
|
|
4752
|
+
CustomerPayment.
|
|
4753
|
+
method:
|
|
4754
|
+
$ref: '#/components/schemas/PaymentMethod'
|
|
4755
|
+
description: Payment method used (e.g. BANK_TRANSFER, MOBILE_MONEY, CHECK).
|
|
4756
|
+
reference:
|
|
4757
|
+
description: Optional payment reference — bank transaction number, check
|
|
4758
|
+
number, Wave ref, etc.
|
|
4759
|
+
type:
|
|
4760
|
+
- string
|
|
4761
|
+
- 'null'
|
|
4762
|
+
paidAt:
|
|
4763
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
4764
|
+
description: When the payment was made.
|
|
4765
|
+
notes:
|
|
4766
|
+
description: Optional internal notes.
|
|
4767
|
+
type:
|
|
4768
|
+
- string
|
|
4769
|
+
- 'null'
|
|
4770
|
+
createdBy:
|
|
4771
|
+
type: string
|
|
4772
|
+
x-immutable: true
|
|
4773
|
+
description: (Immutable) FK → User/staff UID who recorded the payment.
|
|
4774
|
+
createdAt:
|
|
4775
|
+
anyOf:
|
|
4776
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
4777
|
+
- type: 'null'
|
|
4778
|
+
readOnly: true
|
|
4779
|
+
description: (Read-only) Server-generated creation timestamp.
|
|
4780
|
+
updatedAt:
|
|
4781
|
+
anyOf:
|
|
4782
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
4783
|
+
- type: 'null'
|
|
4784
|
+
readOnly: true
|
|
4785
|
+
description: (Read-only) Server-generated update timestamp.
|
|
4786
|
+
required:
|
|
4787
|
+
- companyId
|
|
4788
|
+
- payeeId
|
|
4789
|
+
- amount
|
|
4790
|
+
- currency
|
|
4791
|
+
- method
|
|
4792
|
+
- paidAt
|
|
4793
|
+
- createdBy
|
|
4794
|
+
additionalProperties: false
|
|
4795
|
+
description: 'OutboundPayment (GH#15). Collection: companies/{companyId}/outboundPayments/{paymentId}.
|
|
4796
|
+
Single outbound transfer to a Payee. Canonical name chosen over SupplierPayment/VendorPayment
|
|
4797
|
+
— direction-based, agnostic of payee type. Currency locked to XOF.'
|
|
4798
|
+
OutboundPaymentCreate:
|
|
4799
|
+
allOf:
|
|
4800
|
+
- $ref: '#/components/schemas/OutboundPayment'
|
|
4801
|
+
description: Write payload for creating a new OutboundPayment document. Fields
|
|
4802
|
+
marked `readOnly` are server-set and must not be included. Fields marked `x-immutable`
|
|
4803
|
+
may be set once at creation.
|
|
4804
|
+
required:
|
|
4805
|
+
- companyId
|
|
4806
|
+
- payeeId
|
|
4807
|
+
- amount
|
|
4808
|
+
- currency
|
|
4809
|
+
- method
|
|
4810
|
+
- paidAt
|
|
4811
|
+
- createdBy
|
|
4812
|
+
OutboundPaymentUpdate:
|
|
4813
|
+
allOf:
|
|
4814
|
+
- $ref: '#/components/schemas/OutboundPayment'
|
|
4815
|
+
description: Write payload for partial update (PATCH) of a OutboundPayment document.
|
|
4816
|
+
All fields optional. Fields marked `readOnly` or `x-immutable` must not be
|
|
4817
|
+
sent.
|
|
4818
|
+
OutboundPaymentAllocation:
|
|
4819
|
+
type: object
|
|
4820
|
+
properties:
|
|
4821
|
+
id:
|
|
4822
|
+
readOnly: true
|
|
4823
|
+
description: (Read-only) Firestore document ID, auto-generated.
|
|
4824
|
+
type:
|
|
4825
|
+
- string
|
|
4826
|
+
- 'null'
|
|
4827
|
+
outboundPaymentId:
|
|
4828
|
+
type: string
|
|
4829
|
+
x-immutable: true
|
|
4830
|
+
description: (Immutable) FK → OutboundPayment document ID (parent).
|
|
4831
|
+
expenseId:
|
|
4832
|
+
type: string
|
|
4833
|
+
x-immutable: true
|
|
4834
|
+
description: '(Immutable) FK → Expense document ID. Full Expense model tracked
|
|
4835
|
+
in #20.'
|
|
4836
|
+
companyId:
|
|
4837
|
+
type: string
|
|
4838
|
+
x-immutable: true
|
|
4839
|
+
description: (Immutable) FK → Company document ID. Denormalized for collection-group
|
|
4840
|
+
queries.
|
|
4841
|
+
amount:
|
|
4842
|
+
type: number
|
|
4843
|
+
description: Amount of this payment allocated to the referenced expense
|
|
4844
|
+
(XOF).
|
|
4845
|
+
notes:
|
|
4846
|
+
description: Optional notes about this allocation.
|
|
4847
|
+
type:
|
|
4848
|
+
- string
|
|
4849
|
+
- 'null'
|
|
4850
|
+
allocatedAt:
|
|
4851
|
+
anyOf:
|
|
4852
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
4853
|
+
- type: 'null'
|
|
4854
|
+
readOnly: true
|
|
4855
|
+
description: (Read-only) When this allocation was recorded.
|
|
4856
|
+
required:
|
|
4857
|
+
- outboundPaymentId
|
|
4858
|
+
- expenseId
|
|
4859
|
+
- companyId
|
|
4860
|
+
- amount
|
|
4861
|
+
additionalProperties: false
|
|
4862
|
+
description: 'OutboundPaymentAllocation (GH#15). Subcollection: companies/{companyId}/outboundPayments/{paymentId}/allocations/{allocationId}.
|
|
4863
|
+
Links an OutboundPayment to an Expense. Supports partial and multi-expense
|
|
4864
|
+
allocations.'
|
|
4865
|
+
OutboundPaymentAllocationCreate:
|
|
4866
|
+
allOf:
|
|
4867
|
+
- $ref: '#/components/schemas/OutboundPaymentAllocation'
|
|
4868
|
+
description: Write payload for creating a new OutboundPaymentAllocation document.
|
|
4869
|
+
Fields marked `readOnly` are server-set and must not be included. Fields marked
|
|
4870
|
+
`x-immutable` may be set once at creation.
|
|
4871
|
+
required:
|
|
4872
|
+
- outboundPaymentId
|
|
4873
|
+
- expenseId
|
|
4874
|
+
- companyId
|
|
4875
|
+
- amount
|
|
4876
|
+
OutboundPaymentAllocationUpdate:
|
|
4877
|
+
allOf:
|
|
4878
|
+
- $ref: '#/components/schemas/OutboundPaymentAllocation'
|
|
4879
|
+
description: Write payload for partial update (PATCH) of a OutboundPaymentAllocation
|
|
4880
|
+
document. All fields optional. Fields marked `readOnly` or `x-immutable` must
|
|
4881
|
+
not be sent.
|
|
4882
|
+
PaymentWebhookDelivery:
|
|
4883
|
+
type: object
|
|
4884
|
+
properties:
|
|
4885
|
+
id:
|
|
4886
|
+
readOnly: true
|
|
4887
|
+
description: (Read-only) Firestore document ID, auto-generated.
|
|
4888
|
+
type:
|
|
4889
|
+
- string
|
|
4890
|
+
- 'null'
|
|
4891
|
+
company:
|
|
4892
|
+
type: string
|
|
4893
|
+
x-immutable: true
|
|
4894
|
+
description: (Immutable) Company document ID (e.g. "gerko_studios"). Resolved
|
|
4895
|
+
from the matched endpoint at delivery time.
|
|
4896
|
+
provider:
|
|
4897
|
+
type: string
|
|
4898
|
+
x-note: 'Observed value: "jeko". The inner payload.paymentMethod may differ
|
|
4899
|
+
(e.g. "wave") — provider here is the webhook sender, not the payment rail
|
|
4900
|
+
(#42).'
|
|
4901
|
+
description: Payment provider that sent this webhook (e.g. "jeko", "wave").
|
|
4902
|
+
eventType:
|
|
4903
|
+
type: string
|
|
4904
|
+
x-note: 'Observed value: "transaction.payment". Jeko docs say "transaction.completed"
|
|
4905
|
+
— full set per provider unconfirmed (#42). Use z.string() to avoid rejecting
|
|
4906
|
+
unseen values.'
|
|
4907
|
+
description: 'Provider-defined event type. Observed: "transaction.payment".
|
|
4908
|
+
Full set per provider TBD (#42).'
|
|
4909
|
+
status:
|
|
4910
|
+
type: string
|
|
4911
|
+
x-note: 'Observed values: "success", "error". Indicates whether the webhook
|
|
4912
|
+
was processed without errors.'
|
|
4913
|
+
description: 'Processing outcome. Observed values: "success" | "error".'
|
|
4914
|
+
verified:
|
|
4915
|
+
type: string
|
|
4916
|
+
x-note: 'Observed value: "verified". Indicates HMAC-SHA256 signature verification
|
|
4917
|
+
result. Full set of failure values unconfirmed (#42).'
|
|
4918
|
+
description: 'Signature verification result. Observed: "verified". Other
|
|
4919
|
+
values (e.g. "unverified", "error") may exist but are unconfirmed.'
|
|
4920
|
+
endpointStatus:
|
|
4921
|
+
type: string
|
|
4922
|
+
x-note: 'Observed value: "matched". Indicates whether the token resolved
|
|
4923
|
+
to a known PaymentWebhookEndpoint. Other values (e.g. "not_found", "inactive")
|
|
4924
|
+
unconfirmed (#42).'
|
|
4925
|
+
description: 'Endpoint resolution result. Observed: "matched". Other values
|
|
4926
|
+
unconfirmed (#42).'
|
|
4927
|
+
processed:
|
|
4928
|
+
type: boolean
|
|
4929
|
+
x-note: Set to true once the delivery has been reconciled to the AppPayment
|
|
4930
|
+
ledger (companies/{cid}/apps/{appId}/payments). Back-reference FK not
|
|
4931
|
+
stored on this doc — reconciliation is tracked on the AppPayment side.
|
|
4932
|
+
description: Whether this delivery has been reconciled to the AppPayment
|
|
4933
|
+
ledger.
|
|
4934
|
+
reference:
|
|
4935
|
+
type: string
|
|
4936
|
+
x-note: Equals payload.id (provider transaction ID). Used as dedup key —
|
|
4937
|
+
the backend checks this before processing (#42 ask 3).
|
|
4938
|
+
description: Provider transaction ID (= payload.id). Canonical dedup key.
|
|
4939
|
+
amount:
|
|
4940
|
+
type: number
|
|
4941
|
+
description: Payment amount, denormalized from payload.amount.amount (XOF).
|
|
4942
|
+
currency:
|
|
4943
|
+
type: string
|
|
4944
|
+
description: Currency code, denormalized from payload.amount.currency (e.g.
|
|
4945
|
+
"XOF").
|
|
4946
|
+
payload:
|
|
4947
|
+
type: object
|
|
4948
|
+
propertyNames:
|
|
4949
|
+
type: string
|
|
4950
|
+
additionalProperties: {}
|
|
4951
|
+
x-note: 'Parsed provider request body. Contains PII: counterpartIdentifier
|
|
4952
|
+
and counterpartLabel hold customer phone numbers. Retention/TTL policy
|
|
4953
|
+
TBD (#42 ask 5).'
|
|
4954
|
+
description: Full parsed provider payload. Shape varies by provider. Contains
|
|
4955
|
+
PII (customer phone). See x-note for retention policy status.
|
|
4956
|
+
rawBody:
|
|
4957
|
+
type: string
|
|
4958
|
+
x-note: Verbatim request body string used for HMAC-SHA256 signature verification.
|
|
4959
|
+
Contains same PII as payload. Retention/TTL policy TBD (#42 ask 5).
|
|
4960
|
+
description: Verbatim raw request body — used for HMAC-SHA256 verification.
|
|
4961
|
+
Contains PII.
|
|
4962
|
+
headers:
|
|
4963
|
+
x-note: Request headers including provider signature (e.g. "jeko-signature")
|
|
4964
|
+
and tracing headers. Sensitive — do not expose to clients.
|
|
4965
|
+
description: Incoming HTTP headers. Includes provider signature header and
|
|
4966
|
+
Sentry trace. Sensitive.
|
|
4967
|
+
type:
|
|
4968
|
+
- object
|
|
4969
|
+
- 'null'
|
|
4970
|
+
propertyNames:
|
|
4971
|
+
type: string
|
|
4972
|
+
additionalProperties:
|
|
4973
|
+
type: string
|
|
4974
|
+
receivedAt:
|
|
4975
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
4976
|
+
description: When the webhook delivery was received by the backend.
|
|
4977
|
+
required:
|
|
4978
|
+
- company
|
|
4979
|
+
- provider
|
|
4980
|
+
- eventType
|
|
4981
|
+
- status
|
|
4982
|
+
- verified
|
|
4983
|
+
- endpointStatus
|
|
4984
|
+
- processed
|
|
4985
|
+
- reference
|
|
4986
|
+
- amount
|
|
4987
|
+
- currency
|
|
4988
|
+
- payload
|
|
4989
|
+
- rawBody
|
|
4990
|
+
- receivedAt
|
|
4991
|
+
additionalProperties: false
|
|
4992
|
+
x-internal: true
|
|
4993
|
+
description: 'PaymentWebhookDelivery (GH#42). Collection: payment_webhooks/{deliveryId}
|
|
4994
|
+
(top-level). One document per received provider callback. Contains raw payload
|
|
4995
|
+
+ verification outcome. x-internal: written/read only by backend; dashboard
|
|
4996
|
+
reads via admin UI. PII in payload/rawBody — retention policy TBD.'
|
|
4997
|
+
PaymentWebhookDeliveryCreate:
|
|
4998
|
+
allOf:
|
|
4999
|
+
- $ref: '#/components/schemas/PaymentWebhookDelivery'
|
|
5000
|
+
description: Write payload for creating a new PaymentWebhookDelivery document.
|
|
5001
|
+
Fields marked `readOnly` are server-set and must not be included. Fields marked
|
|
5002
|
+
`x-immutable` may be set once at creation.
|
|
5003
|
+
required:
|
|
5004
|
+
- company
|
|
5005
|
+
- provider
|
|
5006
|
+
- eventType
|
|
5007
|
+
- status
|
|
5008
|
+
- verified
|
|
5009
|
+
- endpointStatus
|
|
5010
|
+
- processed
|
|
5011
|
+
- reference
|
|
5012
|
+
- amount
|
|
5013
|
+
- currency
|
|
5014
|
+
- payload
|
|
5015
|
+
- rawBody
|
|
5016
|
+
- receivedAt
|
|
5017
|
+
PaymentWebhookDeliveryUpdate:
|
|
5018
|
+
allOf:
|
|
5019
|
+
- $ref: '#/components/schemas/PaymentWebhookDelivery'
|
|
5020
|
+
description: Write payload for partial update (PATCH) of a PaymentWebhookDelivery
|
|
5021
|
+
document. All fields optional. Fields marked `readOnly` or `x-immutable` must
|
|
5022
|
+
not be sent.
|
|
5023
|
+
PaymentWebhookEndpoint:
|
|
5024
|
+
type: object
|
|
5025
|
+
properties:
|
|
5026
|
+
token:
|
|
5027
|
+
type: string
|
|
5028
|
+
x-immutable: true
|
|
5029
|
+
description: (Immutable) base64url-encoded 24-byte random token. Also the
|
|
5030
|
+
Firestore document ID and the URL path segment.
|
|
5031
|
+
company:
|
|
5032
|
+
type: string
|
|
5033
|
+
x-immutable: true
|
|
5034
|
+
description: (Immutable) Company slug (e.g. gerko_studios). Identifies the
|
|
5035
|
+
tenant that owns this endpoint.
|
|
5036
|
+
provider:
|
|
5037
|
+
type: string
|
|
5038
|
+
enum:
|
|
5039
|
+
- wave
|
|
5040
|
+
- jeko
|
|
5041
|
+
x-immutable: true
|
|
5042
|
+
description: (Immutable) Payment provider whose webhooks this endpoint accepts.
|
|
5043
|
+
secret:
|
|
5044
|
+
type: string
|
|
5045
|
+
x-note: Provider-specific webhook signing secret. Used to verify HMAC-SHA256
|
|
5046
|
+
signatures on inbound payloads. Never expose to clients.
|
|
5047
|
+
readOnly: true
|
|
5048
|
+
description: Webhook signing secret for HMAC verification. Backend-only
|
|
5049
|
+
— never returned to dashboard or mobile clients.
|
|
5050
|
+
active:
|
|
5051
|
+
type: boolean
|
|
5052
|
+
description: Whether this endpoint is currently active. Inactive endpoints
|
|
5053
|
+
reject incoming webhooks.
|
|
5054
|
+
createdAt:
|
|
5055
|
+
anyOf:
|
|
5056
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
5057
|
+
- type: 'null'
|
|
5058
|
+
readOnly: true
|
|
5059
|
+
description: (Read-only) When this endpoint was provisioned.
|
|
5060
|
+
required:
|
|
5061
|
+
- token
|
|
5062
|
+
- company
|
|
5063
|
+
- provider
|
|
5064
|
+
- secret
|
|
5065
|
+
- active
|
|
5066
|
+
additionalProperties: false
|
|
5067
|
+
x-internal: true
|
|
5068
|
+
description: 'PaymentWebhookEndpoint (GH#41). Collection: payment_webhook_endpoints/{token}.
|
|
5069
|
+
Top-level, not tenant-scoped. Provisioned by superadmin; used by the backend
|
|
5070
|
+
to verify inbound payment webhooks from Wave and Jeko. The delivery log collection
|
|
5071
|
+
(raw webhook payloads + verification outcomes) is tracked in GH#41 — shape
|
|
5072
|
+
TBD.'
|
|
5073
|
+
PaymentWebhookEndpointCreate:
|
|
5074
|
+
allOf:
|
|
5075
|
+
- $ref: '#/components/schemas/PaymentWebhookEndpoint'
|
|
5076
|
+
description: Write payload for creating a new PaymentWebhookEndpoint document.
|
|
5077
|
+
Fields marked `readOnly` are server-set and must not be included. Fields marked
|
|
5078
|
+
`x-immutable` may be set once at creation.
|
|
5079
|
+
required:
|
|
5080
|
+
- token
|
|
5081
|
+
- company
|
|
5082
|
+
- provider
|
|
5083
|
+
- active
|
|
5084
|
+
PaymentWebhookEndpointUpdate:
|
|
5085
|
+
allOf:
|
|
5086
|
+
- $ref: '#/components/schemas/PaymentWebhookEndpoint'
|
|
5087
|
+
description: Write payload for partial update (PATCH) of a PaymentWebhookEndpoint
|
|
5088
|
+
document. All fields optional. Fields marked `readOnly` or `x-immutable` must
|
|
5089
|
+
not be sent.
|
|
4318
5090
|
Sale:
|
|
4319
5091
|
type: object
|
|
4320
5092
|
properties:
|
|
@@ -5213,6 +5985,12 @@ components:
|
|
|
5213
5985
|
received the message.
|
|
5214
5986
|
waba:
|
|
5215
5987
|
$ref: '#/components/schemas/WabaLabel'
|
|
5988
|
+
x-note: 'cmz = "IngenX - Chez Miss Zahoui", phone number ID 446424085225188,
|
|
5989
|
+
used for chez_miss_zahoui_* companies. val = "IngenX - Valets", phone
|
|
5990
|
+
number ID 425582173979125, used for all other companies. Templates are
|
|
5991
|
+
approved at WABA level — if cmz and val share a WABA ID, all templates
|
|
5992
|
+
are available to both. Routing logic: functions/src/orders/order.ts#isSender2Company.
|
|
5993
|
+
See messaging/whatsapp-platform-constraints (#50).'
|
|
5216
5994
|
description: (Immutable) Human-readable WABA label (cmz | val). See WabaLabel
|
|
5217
5995
|
enum.
|
|
5218
5996
|
x-immutable: true
|
|
@@ -5415,10 +6193,26 @@ components:
|
|
|
5415
6193
|
to:
|
|
5416
6194
|
type: string
|
|
5417
6195
|
x-immutable: true
|
|
5418
|
-
|
|
5419
|
-
|
|
6196
|
+
x-note: 'This is the Meta wa_id (digits only, no leading +), NOT a literal
|
|
6197
|
+
E.164 string. Meta normalizes phone numbers in non-obvious ways (e.g.
|
|
6198
|
+
+2250777471485 → wa_id 22577471485, dropping the trunk zero). The only
|
|
6199
|
+
reliable source is Meta''s contacts[].wa_id from the send response — do
|
|
6200
|
+
not derive from E.164 by stripping + alone. The dashboard conversational
|
|
6201
|
+
sends and the whatsapp-server OTP path both use the wa_id form. Confirmed
|
|
6202
|
+
in prod: ING-368.'
|
|
6203
|
+
x-when: Set at enqueue time to the recipient's Meta wa_id. Use inbound WhatsappInboundMessage.from
|
|
6204
|
+
(also wa_id) as the join key for the conversation thread.
|
|
6205
|
+
description: (Immutable) Recipient Meta wa_id — digits only, no leading
|
|
6206
|
+
+ (e.g. 22577471485). Equal to the inbound `from` for the same conversation.
|
|
6207
|
+
NOT literal E.164; see x-note (#54).
|
|
5420
6208
|
waba:
|
|
5421
6209
|
$ref: '#/components/schemas/WabaLabel'
|
|
6210
|
+
x-note: 'cmz = "IngenX - Chez Miss Zahoui", phone number ID 446424085225188,
|
|
6211
|
+
used for chez_miss_zahoui_* companies. val = "IngenX - Valets", phone
|
|
6212
|
+
number ID 425582173979125, used for all other companies. Templates are
|
|
6213
|
+
approved at WABA level — if cmz and val share a WABA ID, all templates
|
|
6214
|
+
are available to both. Routing logic: functions/src/orders/order.ts#isSender2Company.
|
|
6215
|
+
See messaging/whatsapp-platform-constraints (#50).'
|
|
5422
6216
|
description: (Immutable) WABA that will send the message. Mirrors inbound
|
|
5423
6217
|
`waba`.
|
|
5424
6218
|
x-immutable: true
|
|
@@ -5504,6 +6298,9 @@ components:
|
|
|
5504
6298
|
after (sent → delivered → read, or failed).
|
|
5505
6299
|
wamid:
|
|
5506
6300
|
readOnly: true
|
|
6301
|
+
x-note: Useful for audit and dedup. Does NOT enable reply-threading for
|
|
6302
|
+
template messages — Meta silently ignores context.message_id on templates.
|
|
6303
|
+
Threading only works for kind=text within the 24-hour service window (#50).
|
|
5507
6304
|
description: (Read-only) WhatsApp message ID returned by Meta once the backend
|
|
5508
6305
|
sends. Absent while queued or on failure.
|
|
5509
6306
|
type:
|
|
@@ -5583,6 +6380,12 @@ components:
|
|
|
5583
6380
|
- 'null'
|
|
5584
6381
|
waba:
|
|
5585
6382
|
$ref: '#/components/schemas/WabaLabel'
|
|
6383
|
+
x-note: 'cmz = "IngenX - Chez Miss Zahoui", phone number ID 446424085225188,
|
|
6384
|
+
used for chez_miss_zahoui_* companies. val = "IngenX - Valets", phone
|
|
6385
|
+
number ID 425582173979125, used for all other companies. Templates are
|
|
6386
|
+
approved at WABA level — if cmz and val share a WABA ID, all templates
|
|
6387
|
+
are available to both. Routing logic: functions/src/orders/order.ts#isSender2Company.
|
|
6388
|
+
See messaging/whatsapp-platform-constraints (#50).'
|
|
5586
6389
|
description: (Read-only) WABA label this template is approved on. Templates
|
|
5587
6390
|
are WABA-scoped. Mirrors WhatsappOutboundMessage.waba.
|
|
5588
6391
|
readOnly: true
|