@ingenx-io/valets-schema-mcp-server 0.1.1 → 0.1.3
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 +49 -0
- package/data/docs/decisions/migrations.md +56 -0
- package/data/docs/decisions/summary.md +78 -0
- package/data/docs/enums/booking-status.md +26 -0
- package/data/docs/enums/customer-payment-status.md +26 -0
- package/data/docs/enums/customer-payment-target-type.md +23 -0
- package/data/docs/enums/delivery-type.md +23 -0
- package/data/docs/enums/event-status.md +30 -0
- package/data/docs/enums/fulfillment-status.md +32 -0
- package/data/docs/enums/loyalty-transaction-type.md +32 -0
- package/data/docs/enums/order-status.md +65 -0
- package/data/docs/enums/payment-method.md +36 -0
- package/data/docs/enums/payment-proof-status.md +23 -0
- package/data/docs/enums/payment-status.md +34 -0
- package/data/docs/enums/return-status.md +32 -0
- package/data/docs/enums/session-status.md +32 -0
- package/data/docs/enums/ticket-status.md +29 -0
- package/data/docs/index.md +102 -0
- package/data/docs/models/booking-version.md +295 -0
- package/data/docs/models/booking.md +1754 -0
- package/data/docs/models/customer-payment-allocation.md +336 -0
- package/data/docs/models/customer-payment.md +392 -0
- package/data/docs/models/customer.md +475 -0
- package/data/docs/models/event.md +386 -0
- package/data/docs/models/loyalty-config.md +317 -0
- package/data/docs/models/loyalty-reward.md +236 -0
- package/data/docs/models/loyalty-status.md +328 -0
- package/data/docs/models/loyalty-transaction.md +326 -0
- package/data/docs/models/metrics-current.md +532 -0
- package/data/docs/models/metrics-daily.md +548 -0
- package/data/docs/models/metrics-monthly.md +548 -0
- package/data/docs/models/order-item.md +361 -0
- package/data/docs/models/order.md +1637 -0
- package/data/docs/models/payment-summary.md +123 -0
- package/data/docs/models/sale.md +540 -0
- package/data/docs/models/ticket.md +405 -0
- package/data/docs/triggers/event-ticket-triggers.md +204 -0
- package/data/docs/triggers/loyalty-automation.md +123 -0
- package/data/static/decisions.json +966 -0
- package/data/static/llms.txt +1056 -0
- package/data/static/openapi.yaml +3090 -0
- package/data/static/schemas.json +4055 -0
- package/package.json +1 -1
|
@@ -0,0 +1,3090 @@
|
|
|
1
|
+
openapi: 3.1.0
|
|
2
|
+
info:
|
|
3
|
+
title: '@valets/schema'
|
|
4
|
+
description: 'Canonical data model for the Valets platform (Firestore document schemas).
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
Each model appears in up to three variants:
|
|
8
|
+
|
|
9
|
+
- **{Model}** — read model (full Firestore document, includes server-set fields)
|
|
10
|
+
|
|
11
|
+
- **{Model}Create** — write model for document creation; uses allOf composition
|
|
12
|
+
referencing {Model}. `readOnly` fields must not be sent.
|
|
13
|
+
|
|
14
|
+
- **{Model}Update** — write model for partial updates / PATCH; uses allOf composition.
|
|
15
|
+
All fields optional; `readOnly` and `x-immutable` fields must not be sent.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
Server-owned models (e.g. BookingVersion, LoyaltyStatus) only have the read variant.'
|
|
19
|
+
version: 0.1.0
|
|
20
|
+
paths: {}
|
|
21
|
+
components:
|
|
22
|
+
schemas:
|
|
23
|
+
BookingStatus:
|
|
24
|
+
type: string
|
|
25
|
+
enum:
|
|
26
|
+
- PENDING
|
|
27
|
+
- CONFIRMED
|
|
28
|
+
- COMPLETED
|
|
29
|
+
- CANCELLED
|
|
30
|
+
- CANCELLATION_REQUESTED
|
|
31
|
+
- COMPLETED_MIXED
|
|
32
|
+
description: Booking lifecycle status. COMPLETED_MIXED = some sessions completed,
|
|
33
|
+
others cancelled/no-show.
|
|
34
|
+
CustomerPaymentStatus:
|
|
35
|
+
type: string
|
|
36
|
+
enum:
|
|
37
|
+
- PENDING
|
|
38
|
+
- CONFIRMED
|
|
39
|
+
- PARTIALLY_APPLIED
|
|
40
|
+
- FULLY_APPLIED
|
|
41
|
+
- REFUNDED
|
|
42
|
+
- CANCELLED
|
|
43
|
+
description: Customer payment lifecycle status (D22). Tracks allocation progress
|
|
44
|
+
of received payments.
|
|
45
|
+
CustomerPaymentTargetType:
|
|
46
|
+
type: string
|
|
47
|
+
enum:
|
|
48
|
+
- BOOKING
|
|
49
|
+
- ORDER
|
|
50
|
+
- PURCHASE
|
|
51
|
+
description: Target document type for customer payment allocation.
|
|
52
|
+
DeliveryType:
|
|
53
|
+
type: string
|
|
54
|
+
enum:
|
|
55
|
+
- ON_SITE
|
|
56
|
+
- PICK_UP
|
|
57
|
+
- DELIVERY
|
|
58
|
+
description: Fulfillment channel for an order. Determines whether the customer
|
|
59
|
+
comes to the business (ON_SITE), collects their order themselves (PICK_UP),
|
|
60
|
+
or receives a physical delivery (DELIVERY). Drives whether fulfillmentStatus
|
|
61
|
+
is relevant.
|
|
62
|
+
EventStatus:
|
|
63
|
+
type: string
|
|
64
|
+
enum:
|
|
65
|
+
- DRAFT
|
|
66
|
+
- ACTIVE
|
|
67
|
+
- CANCELLED
|
|
68
|
+
- COMPLETED
|
|
69
|
+
description: Ticketed event lifecycle (D32). Mobile-only today; Dashboard in
|
|
70
|
+
Wave 4.
|
|
71
|
+
FulfillmentStatus:
|
|
72
|
+
type: string
|
|
73
|
+
enum:
|
|
74
|
+
- PREPARING
|
|
75
|
+
- PARTIALLY_SHIPPED
|
|
76
|
+
- SHIPPED
|
|
77
|
+
- IN_TRANSIT
|
|
78
|
+
- DELIVERED
|
|
79
|
+
- PICKED_UP
|
|
80
|
+
description: Delivery/fulfillment lifecycle (D34). Optional — null for in-person
|
|
81
|
+
orders.
|
|
82
|
+
LoyaltyTransactionType:
|
|
83
|
+
type: string
|
|
84
|
+
enum:
|
|
85
|
+
- EARNED
|
|
86
|
+
- REDEEMED
|
|
87
|
+
- ADJUSTED
|
|
88
|
+
- EXPIRED
|
|
89
|
+
- BONUS
|
|
90
|
+
- REFUND
|
|
91
|
+
description: Loyalty point transaction type (D07). SCREAMING_SNAKE past tense.
|
|
92
|
+
OrderStatus:
|
|
93
|
+
type: string
|
|
94
|
+
enum:
|
|
95
|
+
- PENDING
|
|
96
|
+
- CONFIRMED
|
|
97
|
+
- PROCESSING
|
|
98
|
+
- READY
|
|
99
|
+
- COMPLETED
|
|
100
|
+
- CANCELLED
|
|
101
|
+
- EXPIRED
|
|
102
|
+
description: Core order lifecycle status (D03, D34). Universal across all business
|
|
103
|
+
types. Replaces the Dashboard's legacy 20-value flat enum (MIG-11).
|
|
104
|
+
PaymentMethod:
|
|
105
|
+
type: string
|
|
106
|
+
enum:
|
|
107
|
+
- CASH
|
|
108
|
+
- CREDIT_CARD
|
|
109
|
+
- ORANGE_MONEY
|
|
110
|
+
- WAVE
|
|
111
|
+
- MTN_MONEY
|
|
112
|
+
- MOOV_MONEY
|
|
113
|
+
- BANK_TRANSFER
|
|
114
|
+
- PAYPAL
|
|
115
|
+
- STRIPE
|
|
116
|
+
- OTHER
|
|
117
|
+
description: Unified payment method set with African + global methods (D02).
|
|
118
|
+
PaymentProofStatus:
|
|
119
|
+
type: string
|
|
120
|
+
enum:
|
|
121
|
+
- PENDING
|
|
122
|
+
- APPROVED
|
|
123
|
+
- REJECTED
|
|
124
|
+
description: Payment proof review status. Used by Order and Booking payment
|
|
125
|
+
proof workflows.
|
|
126
|
+
PaymentStatus:
|
|
127
|
+
type: string
|
|
128
|
+
enum:
|
|
129
|
+
- PENDING
|
|
130
|
+
- PAID
|
|
131
|
+
- PARTIALLY_PAID
|
|
132
|
+
- FAILED
|
|
133
|
+
- REFUND_PROCESSING
|
|
134
|
+
- REFUNDED
|
|
135
|
+
- PARTIALLY_REFUNDED
|
|
136
|
+
description: Payment lifecycle status (D01 amended). Used by Order, Sale/Purchase,
|
|
137
|
+
Booking.
|
|
138
|
+
ReturnStatus:
|
|
139
|
+
type: string
|
|
140
|
+
enum:
|
|
141
|
+
- RETURN_REQUESTED
|
|
142
|
+
- RETURN_PROCESSING
|
|
143
|
+
- RETURNED
|
|
144
|
+
- EXCHANGE_REQUESTED
|
|
145
|
+
- EXCHANGE_PROCESSING
|
|
146
|
+
- EXCHANGE_COMPLETED
|
|
147
|
+
description: Post-sale return/exchange lifecycle (D34). Optional — null until
|
|
148
|
+
return or exchange initiated.
|
|
149
|
+
SessionStatus:
|
|
150
|
+
type: string
|
|
151
|
+
enum:
|
|
152
|
+
- PENDING
|
|
153
|
+
- CONFIRMED
|
|
154
|
+
- CANCELLATION_REQUESTED
|
|
155
|
+
- COMPLETED
|
|
156
|
+
- NO_SHOW
|
|
157
|
+
- CANCELLED
|
|
158
|
+
description: Per-date/per-slot booking session status (D19). Dashboard is sole
|
|
159
|
+
writer; Mobile is read-only.
|
|
160
|
+
TicketStatus:
|
|
161
|
+
type: string
|
|
162
|
+
enum:
|
|
163
|
+
- VALID
|
|
164
|
+
- USED
|
|
165
|
+
- CANCELLED
|
|
166
|
+
description: Event ticket status (D32). VALID = active and unused.
|
|
167
|
+
FirestoreTimestamp:
|
|
168
|
+
type: object
|
|
169
|
+
properties:
|
|
170
|
+
_seconds:
|
|
171
|
+
type: integer
|
|
172
|
+
minimum: -9007199254740991
|
|
173
|
+
maximum: 9007199254740991
|
|
174
|
+
_nanoseconds:
|
|
175
|
+
type: integer
|
|
176
|
+
minimum: -9007199254740991
|
|
177
|
+
maximum: 9007199254740991
|
|
178
|
+
required:
|
|
179
|
+
- _seconds
|
|
180
|
+
- _nanoseconds
|
|
181
|
+
additionalProperties: false
|
|
182
|
+
description: Firestore Timestamp serialized representation
|
|
183
|
+
Booking:
|
|
184
|
+
type: object
|
|
185
|
+
properties:
|
|
186
|
+
id:
|
|
187
|
+
type: string
|
|
188
|
+
readOnly: true
|
|
189
|
+
description: (Read-only) Firestore document ID.
|
|
190
|
+
uid:
|
|
191
|
+
type: string
|
|
192
|
+
readOnly: true
|
|
193
|
+
description: (Read-only) Entity UID. Often mirrors id.
|
|
194
|
+
companyId:
|
|
195
|
+
x-immutable: true
|
|
196
|
+
description: '(Immutable) FK → Company document ID. Note: optional in current
|
|
197
|
+
schema — should be required (see ID consistency audit).'
|
|
198
|
+
type:
|
|
199
|
+
- string
|
|
200
|
+
- 'null'
|
|
201
|
+
status:
|
|
202
|
+
$ref: '#/components/schemas/BookingStatus'
|
|
203
|
+
description: Booking lifecycle status. COMPLETED_MIXED = some sessions completed,
|
|
204
|
+
others cancelled/no-show.
|
|
205
|
+
totalAmount:
|
|
206
|
+
type: number
|
|
207
|
+
x-note: Booking uses `totalAmount`; Order uses `amount` for the equivalent
|
|
208
|
+
field (D05 locked `amount` as canonical for orders). Pending cross-model
|
|
209
|
+
alignment.
|
|
210
|
+
x-see:
|
|
211
|
+
decisions:
|
|
212
|
+
- D05
|
|
213
|
+
bookingDates:
|
|
214
|
+
type: array
|
|
215
|
+
items:
|
|
216
|
+
type: object
|
|
217
|
+
properties:
|
|
218
|
+
date:
|
|
219
|
+
type: string
|
|
220
|
+
selectedTimeSlots:
|
|
221
|
+
type: array
|
|
222
|
+
items:
|
|
223
|
+
type: object
|
|
224
|
+
properties:
|
|
225
|
+
id:
|
|
226
|
+
type: number
|
|
227
|
+
name:
|
|
228
|
+
type: string
|
|
229
|
+
timeRange:
|
|
230
|
+
type: string
|
|
231
|
+
price:
|
|
232
|
+
type: number
|
|
233
|
+
description: Canonical price field (D11). Replaces legacy standardPrice/fullPrice
|
|
234
|
+
(MIG-08).
|
|
235
|
+
notMainPurposePrice:
|
|
236
|
+
type: number
|
|
237
|
+
description: Price when slot is not the main purpose (D11).
|
|
238
|
+
Canonical name; replaces legacy aliases (MIG-08).
|
|
239
|
+
hours:
|
|
240
|
+
type: string
|
|
241
|
+
startTime:
|
|
242
|
+
type: string
|
|
243
|
+
endTime:
|
|
244
|
+
type: string
|
|
245
|
+
isNightSlot:
|
|
246
|
+
type: boolean
|
|
247
|
+
isNotMainPurpose:
|
|
248
|
+
type: boolean
|
|
249
|
+
isNotMainPurposeReason:
|
|
250
|
+
type: string
|
|
251
|
+
isNotMainPurposeOtherReason:
|
|
252
|
+
type: string
|
|
253
|
+
_deleted:
|
|
254
|
+
description: Soft-delete flag. Dashboard writes; Mobile filters
|
|
255
|
+
(IG-6).
|
|
256
|
+
type: boolean
|
|
257
|
+
_deletedAt:
|
|
258
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
259
|
+
description: Firestore Timestamp serialized representation
|
|
260
|
+
_deletedBy:
|
|
261
|
+
description: FK → User/staff UID who soft-deleted this item.
|
|
262
|
+
type: string
|
|
263
|
+
_lastModifiedAt:
|
|
264
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
265
|
+
description: Firestore Timestamp serialized representation
|
|
266
|
+
_lastModifiedBy:
|
|
267
|
+
description: FK → User/staff UID who last modified this item.
|
|
268
|
+
type: string
|
|
269
|
+
_version:
|
|
270
|
+
description: Monotonic version counter for conflict detection.
|
|
271
|
+
type: number
|
|
272
|
+
required:
|
|
273
|
+
- id
|
|
274
|
+
- name
|
|
275
|
+
- timeRange
|
|
276
|
+
- price
|
|
277
|
+
- notMainPurposePrice
|
|
278
|
+
- hours
|
|
279
|
+
- startTime
|
|
280
|
+
- endTime
|
|
281
|
+
additionalProperties: false
|
|
282
|
+
description: Selected time slot within a BookingDate. Carries CRDT
|
|
283
|
+
metadata for conflict-free editing.
|
|
284
|
+
slotKitTypes:
|
|
285
|
+
type: object
|
|
286
|
+
propertyNames:
|
|
287
|
+
type: string
|
|
288
|
+
additionalProperties:
|
|
289
|
+
type: string
|
|
290
|
+
description: Kit type per slot (IG-11). Firebase parity gap — exists
|
|
291
|
+
in Firestore but Firebase type lacked it.
|
|
292
|
+
slotAddOns:
|
|
293
|
+
type: object
|
|
294
|
+
propertyNames:
|
|
295
|
+
type: string
|
|
296
|
+
additionalProperties:
|
|
297
|
+
type: array
|
|
298
|
+
items:
|
|
299
|
+
type: string
|
|
300
|
+
description: Add-on IDs per slot. Numeric IDs to be normalized to
|
|
301
|
+
descriptive names (MIG-07/D10).
|
|
302
|
+
extraHours:
|
|
303
|
+
type: number
|
|
304
|
+
status:
|
|
305
|
+
$ref: '#/components/schemas/SessionStatus'
|
|
306
|
+
description: Per-date session status (D19). Dashboard is sole writer;
|
|
307
|
+
Mobile is read-only.
|
|
308
|
+
statusUpdatedAt:
|
|
309
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
310
|
+
readOnly: true
|
|
311
|
+
description: (Read-only) Timestamp of last status change.
|
|
312
|
+
statusUpdatedBy:
|
|
313
|
+
description: FK → User/staff UID who updated this date status.
|
|
314
|
+
type: string
|
|
315
|
+
slotStatuses:
|
|
316
|
+
description: Per-slot session statuses (D19). Keyed by slot ID string.
|
|
317
|
+
type: object
|
|
318
|
+
propertyNames:
|
|
319
|
+
type: string
|
|
320
|
+
additionalProperties:
|
|
321
|
+
$ref: '#/components/schemas/SessionStatus'
|
|
322
|
+
description: Per-date/per-slot booking session status (D19). Dashboard
|
|
323
|
+
is sole writer; Mobile is read-only.
|
|
324
|
+
slotStatusUpdatedAt:
|
|
325
|
+
type: object
|
|
326
|
+
propertyNames:
|
|
327
|
+
type: string
|
|
328
|
+
additionalProperties:
|
|
329
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
330
|
+
description: Firestore Timestamp serialized representation
|
|
331
|
+
slotStatusUpdatedBy:
|
|
332
|
+
type: object
|
|
333
|
+
propertyNames:
|
|
334
|
+
type: string
|
|
335
|
+
additionalProperties:
|
|
336
|
+
type: string
|
|
337
|
+
_deleted:
|
|
338
|
+
description: Soft-delete flag. Dashboard writes; Mobile filters (IG-6).
|
|
339
|
+
type: boolean
|
|
340
|
+
_deletedAt:
|
|
341
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
342
|
+
description: Firestore Timestamp serialized representation
|
|
343
|
+
_deletedBy:
|
|
344
|
+
description: FK → User/staff UID who soft-deleted this item.
|
|
345
|
+
type: string
|
|
346
|
+
_lastModifiedAt:
|
|
347
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
348
|
+
description: Firestore Timestamp serialized representation
|
|
349
|
+
_lastModifiedBy:
|
|
350
|
+
description: FK → User/staff UID who last modified this item.
|
|
351
|
+
type: string
|
|
352
|
+
_version:
|
|
353
|
+
description: Monotonic version counter for conflict detection.
|
|
354
|
+
type: number
|
|
355
|
+
required:
|
|
356
|
+
- date
|
|
357
|
+
- selectedTimeSlots
|
|
358
|
+
- slotKitTypes
|
|
359
|
+
- slotAddOns
|
|
360
|
+
- extraHours
|
|
361
|
+
additionalProperties: false
|
|
362
|
+
description: Single date entry within a Booking. Contains time slots,
|
|
363
|
+
session statuses (D19), and CRDT metadata.
|
|
364
|
+
customerId:
|
|
365
|
+
description: FK → Customer.id (Firestore doc ID). Links booking to customer
|
|
366
|
+
record.
|
|
367
|
+
type:
|
|
368
|
+
- string
|
|
369
|
+
- 'null'
|
|
370
|
+
client:
|
|
371
|
+
denormalized: true
|
|
372
|
+
description: (Denormalized) Embedded client snapshot from Customer at write
|
|
373
|
+
time.
|
|
374
|
+
type:
|
|
375
|
+
- object
|
|
376
|
+
- 'null'
|
|
377
|
+
properties:
|
|
378
|
+
firstName:
|
|
379
|
+
type: string
|
|
380
|
+
lastName:
|
|
381
|
+
type: string
|
|
382
|
+
email:
|
|
383
|
+
type: string
|
|
384
|
+
phone:
|
|
385
|
+
type: string
|
|
386
|
+
additionalProperties: false
|
|
387
|
+
customerName:
|
|
388
|
+
denormalized: true
|
|
389
|
+
description: (Denormalized) From Customer.name at write time. Canonical
|
|
390
|
+
field per D24.
|
|
391
|
+
type:
|
|
392
|
+
- string
|
|
393
|
+
- 'null'
|
|
394
|
+
customerEmail:
|
|
395
|
+
denormalized: true
|
|
396
|
+
description: (Denormalized) From Customer.email at write time. Canonical
|
|
397
|
+
field per D24.
|
|
398
|
+
type:
|
|
399
|
+
- string
|
|
400
|
+
- 'null'
|
|
401
|
+
customerPhone:
|
|
402
|
+
denormalized: true
|
|
403
|
+
description: (Denormalized) From Customer.phone at write time. Canonical
|
|
404
|
+
field per D24.
|
|
405
|
+
type:
|
|
406
|
+
- string
|
|
407
|
+
- 'null'
|
|
408
|
+
clientName:
|
|
409
|
+
denormalized: true
|
|
410
|
+
deprecated: true
|
|
411
|
+
x-replaced-by: customerName
|
|
412
|
+
description: (Denormalized) Legacy — use `customerName`. D24 standardized
|
|
413
|
+
to customer* prefix.
|
|
414
|
+
type:
|
|
415
|
+
- string
|
|
416
|
+
- 'null'
|
|
417
|
+
clientReference:
|
|
418
|
+
type: string
|
|
419
|
+
clientEmail:
|
|
420
|
+
denormalized: true
|
|
421
|
+
deprecated: true
|
|
422
|
+
x-replaced-by: customerEmail
|
|
423
|
+
description: (Denormalized) Legacy — use `customerEmail`. D24 standardized
|
|
424
|
+
to customer* prefix.
|
|
425
|
+
type:
|
|
426
|
+
- string
|
|
427
|
+
- 'null'
|
|
428
|
+
clientPhone:
|
|
429
|
+
denormalized: true
|
|
430
|
+
deprecated: true
|
|
431
|
+
x-replaced-by: customerPhone
|
|
432
|
+
description: (Denormalized) Legacy — use `customerPhone`. D24 standardized
|
|
433
|
+
to customer* prefix.
|
|
434
|
+
type:
|
|
435
|
+
- string
|
|
436
|
+
- 'null'
|
|
437
|
+
service:
|
|
438
|
+
type:
|
|
439
|
+
- object
|
|
440
|
+
- 'null'
|
|
441
|
+
properties:
|
|
442
|
+
name:
|
|
443
|
+
type: string
|
|
444
|
+
additionalProperties: false
|
|
445
|
+
serviceId:
|
|
446
|
+
description: FK → Service document ID.
|
|
447
|
+
type:
|
|
448
|
+
- string
|
|
449
|
+
- 'null'
|
|
450
|
+
serviceName:
|
|
451
|
+
denormalized: true
|
|
452
|
+
description: (Denormalized) From Service.name at write time.
|
|
453
|
+
type:
|
|
454
|
+
- string
|
|
455
|
+
- 'null'
|
|
456
|
+
timeSlot:
|
|
457
|
+
type:
|
|
458
|
+
- string
|
|
459
|
+
- 'null'
|
|
460
|
+
date:
|
|
461
|
+
type:
|
|
462
|
+
- string
|
|
463
|
+
- 'null'
|
|
464
|
+
startDate:
|
|
465
|
+
type:
|
|
466
|
+
- string
|
|
467
|
+
- 'null'
|
|
468
|
+
endDate:
|
|
469
|
+
type:
|
|
470
|
+
- string
|
|
471
|
+
- 'null'
|
|
472
|
+
startTime:
|
|
473
|
+
type:
|
|
474
|
+
- string
|
|
475
|
+
- 'null'
|
|
476
|
+
endTime:
|
|
477
|
+
type:
|
|
478
|
+
- string
|
|
479
|
+
- 'null'
|
|
480
|
+
notes:
|
|
481
|
+
type:
|
|
482
|
+
- array
|
|
483
|
+
- 'null'
|
|
484
|
+
items:
|
|
485
|
+
type: object
|
|
486
|
+
properties:
|
|
487
|
+
id:
|
|
488
|
+
type: string
|
|
489
|
+
readOnly: true
|
|
490
|
+
description: (Read-only) Note ID.
|
|
491
|
+
text:
|
|
492
|
+
type: string
|
|
493
|
+
createdAt:
|
|
494
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
495
|
+
description: (Read-only) Firestore Timestamp serialized representation.
|
|
496
|
+
readOnly: true
|
|
497
|
+
createdBy:
|
|
498
|
+
x-immutable: true
|
|
499
|
+
description: (Immutable) FK → User/staff UID who created this note.
|
|
500
|
+
type: string
|
|
501
|
+
createdByName:
|
|
502
|
+
denormalized: true
|
|
503
|
+
description: (Denormalized) From User display name at write time.
|
|
504
|
+
type: string
|
|
505
|
+
_deleted:
|
|
506
|
+
description: Soft-delete flag. Dashboard writes; Mobile filters (IG-6).
|
|
507
|
+
type: boolean
|
|
508
|
+
_deletedAt:
|
|
509
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
510
|
+
description: Firestore Timestamp serialized representation
|
|
511
|
+
_deletedBy:
|
|
512
|
+
description: FK → User/staff UID who soft-deleted this item.
|
|
513
|
+
type: string
|
|
514
|
+
_lastModifiedAt:
|
|
515
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
516
|
+
description: Firestore Timestamp serialized representation
|
|
517
|
+
_lastModifiedBy:
|
|
518
|
+
description: FK → User/staff UID who last modified this item.
|
|
519
|
+
type: string
|
|
520
|
+
_version:
|
|
521
|
+
description: Monotonic version counter for conflict detection.
|
|
522
|
+
type: number
|
|
523
|
+
required:
|
|
524
|
+
- id
|
|
525
|
+
- text
|
|
526
|
+
- createdAt
|
|
527
|
+
additionalProperties: false
|
|
528
|
+
description: Timestamped note attached to a Booking. Carries CRDT metadata.
|
|
529
|
+
technicalInfo:
|
|
530
|
+
type:
|
|
531
|
+
- string
|
|
532
|
+
- 'null'
|
|
533
|
+
paymentStatus:
|
|
534
|
+
anyOf:
|
|
535
|
+
- $ref: '#/components/schemas/PaymentStatus'
|
|
536
|
+
- type: 'null'
|
|
537
|
+
description: Payment lifecycle status (D01 amended). Used by Order, Sale/Purchase,
|
|
538
|
+
Booking.
|
|
539
|
+
amountPaid:
|
|
540
|
+
type:
|
|
541
|
+
- number
|
|
542
|
+
- 'null'
|
|
543
|
+
amountRefunded:
|
|
544
|
+
type:
|
|
545
|
+
- number
|
|
546
|
+
- 'null'
|
|
547
|
+
amountPending:
|
|
548
|
+
type:
|
|
549
|
+
- number
|
|
550
|
+
- 'null'
|
|
551
|
+
purchaseId:
|
|
552
|
+
description: FK → Sale.id. Link to associated Sale document.
|
|
553
|
+
type:
|
|
554
|
+
- string
|
|
555
|
+
- 'null'
|
|
556
|
+
paymentStatusChangeReason:
|
|
557
|
+
type:
|
|
558
|
+
- string
|
|
559
|
+
- 'null'
|
|
560
|
+
paymentStatusChangedBy:
|
|
561
|
+
description: FK → User/staff UID who changed payment status.
|
|
562
|
+
type:
|
|
563
|
+
- string
|
|
564
|
+
- 'null'
|
|
565
|
+
paymentStatusChangedAt:
|
|
566
|
+
anyOf:
|
|
567
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
568
|
+
- type: 'null'
|
|
569
|
+
description: Firestore Timestamp serialized representation
|
|
570
|
+
paymentProofUrl:
|
|
571
|
+
description: URL to uploaded payment proof image/document.
|
|
572
|
+
type:
|
|
573
|
+
- string
|
|
574
|
+
- 'null'
|
|
575
|
+
paymentProofStatus:
|
|
576
|
+
anyOf:
|
|
577
|
+
- $ref: '#/components/schemas/PaymentProofStatus'
|
|
578
|
+
- type: 'null'
|
|
579
|
+
description: Payment proof review status. Used by Order and Booking payment
|
|
580
|
+
proof workflows.
|
|
581
|
+
paymentProofAddedAt:
|
|
582
|
+
anyOf:
|
|
583
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
584
|
+
- type: 'null'
|
|
585
|
+
description: Firestore Timestamp serialized representation
|
|
586
|
+
paymentProofAddedBy:
|
|
587
|
+
description: FK → User/staff UID who uploaded the payment proof.
|
|
588
|
+
type:
|
|
589
|
+
- string
|
|
590
|
+
- 'null'
|
|
591
|
+
paymentProofReviewedBy:
|
|
592
|
+
description: FK → User/staff UID who reviewed the payment proof.
|
|
593
|
+
type:
|
|
594
|
+
- string
|
|
595
|
+
- 'null'
|
|
596
|
+
paymentProofReviewedAt:
|
|
597
|
+
anyOf:
|
|
598
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
599
|
+
- type: 'null'
|
|
600
|
+
description: Firestore Timestamp serialized representation
|
|
601
|
+
paymentProofRejectionReason:
|
|
602
|
+
type:
|
|
603
|
+
- string
|
|
604
|
+
- 'null'
|
|
605
|
+
cancellationRequestedById:
|
|
606
|
+
description: FK → User/staff UID who requested cancellation.
|
|
607
|
+
type:
|
|
608
|
+
- string
|
|
609
|
+
- 'null'
|
|
610
|
+
cancellationRequestReason:
|
|
611
|
+
type:
|
|
612
|
+
- string
|
|
613
|
+
- 'null'
|
|
614
|
+
cancellationProcessedById:
|
|
615
|
+
description: FK → User/staff UID who processed the cancellation.
|
|
616
|
+
type:
|
|
617
|
+
- string
|
|
618
|
+
- 'null'
|
|
619
|
+
cancellationProcessedAt:
|
|
620
|
+
anyOf:
|
|
621
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
622
|
+
- type: 'null'
|
|
623
|
+
description: Firestore Timestamp serialized representation
|
|
624
|
+
cancelledByRole:
|
|
625
|
+
type:
|
|
626
|
+
- string
|
|
627
|
+
- 'null'
|
|
628
|
+
cancellationReason:
|
|
629
|
+
type:
|
|
630
|
+
- string
|
|
631
|
+
- 'null'
|
|
632
|
+
createdAt:
|
|
633
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
634
|
+
description: (Read-only) Server-generated creation timestamp.
|
|
635
|
+
readOnly: true
|
|
636
|
+
updatedAt:
|
|
637
|
+
anyOf:
|
|
638
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
639
|
+
- type: 'null'
|
|
640
|
+
readOnly: true
|
|
641
|
+
description: (Read-only) Server-generated update timestamp.
|
|
642
|
+
createdBy:
|
|
643
|
+
x-immutable: true
|
|
644
|
+
description: (Immutable) FK → User/staff UID who created this booking.
|
|
645
|
+
type:
|
|
646
|
+
- string
|
|
647
|
+
- 'null'
|
|
648
|
+
updatedBy:
|
|
649
|
+
description: FK → User/staff UID who last updated this booking.
|
|
650
|
+
type:
|
|
651
|
+
- string
|
|
652
|
+
- 'null'
|
|
653
|
+
createdFromBackend:
|
|
654
|
+
description: When true, suppresses Firebase notification triggers (D20/IG-8).
|
|
655
|
+
type:
|
|
656
|
+
- boolean
|
|
657
|
+
- 'null'
|
|
658
|
+
required:
|
|
659
|
+
- id
|
|
660
|
+
- uid
|
|
661
|
+
- status
|
|
662
|
+
- totalAmount
|
|
663
|
+
- bookingDates
|
|
664
|
+
- clientReference
|
|
665
|
+
- createdAt
|
|
666
|
+
additionalProperties: false
|
|
667
|
+
description: 'Booking model. Collection: companies/{companyId}/bookings/{bookingId}.
|
|
668
|
+
All platforms. Uses BookingStatus (6 values) and SessionStatus (D19) for per-date/slot
|
|
669
|
+
tracking.'
|
|
670
|
+
BookingCreate:
|
|
671
|
+
allOf:
|
|
672
|
+
- $ref: '#/components/schemas/Booking'
|
|
673
|
+
description: Write payload for creating a new Booking document. Fields marked
|
|
674
|
+
`readOnly` are server-set and must not be included. Fields marked `x-immutable`
|
|
675
|
+
may be set once at creation.
|
|
676
|
+
required:
|
|
677
|
+
- status
|
|
678
|
+
- totalAmount
|
|
679
|
+
- bookingDates
|
|
680
|
+
- clientReference
|
|
681
|
+
BookingUpdate:
|
|
682
|
+
allOf:
|
|
683
|
+
- $ref: '#/components/schemas/Booking'
|
|
684
|
+
description: Write payload for partial update (PATCH) of a Booking document.
|
|
685
|
+
All fields optional. Fields marked `readOnly` or `x-immutable` must not be
|
|
686
|
+
sent.
|
|
687
|
+
BookingVersion:
|
|
688
|
+
type: object
|
|
689
|
+
properties:
|
|
690
|
+
id:
|
|
691
|
+
type: string
|
|
692
|
+
readOnly: true
|
|
693
|
+
description: (Read-only) Firestore document ID. Server-generated version
|
|
694
|
+
record.
|
|
695
|
+
bookingId:
|
|
696
|
+
type: string
|
|
697
|
+
x-immutable: true
|
|
698
|
+
description: (Immutable) FK → Booking.id. Parent booking this version records.
|
|
699
|
+
companyId:
|
|
700
|
+
type: string
|
|
701
|
+
x-immutable: true
|
|
702
|
+
description: (Immutable) FK → Company document ID. Denormalized for direct
|
|
703
|
+
queries.
|
|
704
|
+
changeType:
|
|
705
|
+
type: string
|
|
706
|
+
enum:
|
|
707
|
+
- CREATE
|
|
708
|
+
- UPDATE
|
|
709
|
+
- DELETE
|
|
710
|
+
x-immutable: true
|
|
711
|
+
x-note: DELETE versions are written when a booking is soft-deleted (CRDT
|
|
712
|
+
_deleted flag). Hard deletes bypass this trail.
|
|
713
|
+
description: '(Immutable) What caused this version record: CREATE, UPDATE,
|
|
714
|
+
or DELETE.'
|
|
715
|
+
changedAt:
|
|
716
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
717
|
+
description: (Read-only) Timestamp of the write that created this version.
|
|
718
|
+
Server-set.
|
|
719
|
+
readOnly: true
|
|
720
|
+
changedBy:
|
|
721
|
+
x-immutable: true
|
|
722
|
+
x-note: Null when the write originated from a Firebase trigger, CLI script,
|
|
723
|
+
or unknown source.
|
|
724
|
+
description: (Immutable) FK → User/staff UID who made the change. Null for
|
|
725
|
+
server-originated writes.
|
|
726
|
+
type:
|
|
727
|
+
- string
|
|
728
|
+
- 'null'
|
|
729
|
+
changedByRole:
|
|
730
|
+
x-immutable: true
|
|
731
|
+
x-note: Populated by the Firebase trigger from the write context. Helps
|
|
732
|
+
distinguish client vs. server writes.
|
|
733
|
+
description: '(Immutable) Which platform/context made the write: DASHBOARD,
|
|
734
|
+
MOBILE, FIREBASE (trigger), CLI (migration script), or UNKNOWN. SCREAMING_SNAKE
|
|
735
|
+
per D04.'
|
|
736
|
+
type:
|
|
737
|
+
- string
|
|
738
|
+
- 'null'
|
|
739
|
+
enum:
|
|
740
|
+
- DASHBOARD
|
|
741
|
+
- MOBILE
|
|
742
|
+
- FIREBASE
|
|
743
|
+
- CLI
|
|
744
|
+
- UNKNOWN
|
|
745
|
+
fieldsChanged:
|
|
746
|
+
x-immutable: true
|
|
747
|
+
readOnly: true
|
|
748
|
+
x-note: Dot-notation paths for nested fields (e.g. "bookingDates.0.status").
|
|
749
|
+
Populated by diff in Firebase trigger. Null for CREATE versions.
|
|
750
|
+
description: (Immutable, Read-only) List of field paths that changed in
|
|
751
|
+
this write. Populated by the Firebase trigger diff. Null for CREATE records.
|
|
752
|
+
type:
|
|
753
|
+
- array
|
|
754
|
+
- 'null'
|
|
755
|
+
items:
|
|
756
|
+
type: string
|
|
757
|
+
snapshot:
|
|
758
|
+
type: object
|
|
759
|
+
propertyNames:
|
|
760
|
+
type: string
|
|
761
|
+
additionalProperties: {}
|
|
762
|
+
x-immutable: true
|
|
763
|
+
readOnly: true
|
|
764
|
+
x-note: Full Booking document at the time of write. Typed as a string-keyed
|
|
765
|
+
record to avoid circular schema reference. Consumers cast to Booking at
|
|
766
|
+
runtime.
|
|
767
|
+
x-see:
|
|
768
|
+
decisions:
|
|
769
|
+
- D18
|
|
770
|
+
description: (Immutable, Read-only) Full snapshot of the Booking document
|
|
771
|
+
immediately after the write. Untyped to avoid circular schema dependency
|
|
772
|
+
— cast to Booking at runtime.
|
|
773
|
+
required:
|
|
774
|
+
- id
|
|
775
|
+
- bookingId
|
|
776
|
+
- companyId
|
|
777
|
+
- changeType
|
|
778
|
+
- changedAt
|
|
779
|
+
- snapshot
|
|
780
|
+
additionalProperties: false
|
|
781
|
+
description: 'BookingVersion model (D18). Collection: companies/{companyId}/bookings/{bookingId}/versions/{versionId}.
|
|
782
|
+
Server-owned audit trail written by Firebase trigger on every Booking mutation.
|
|
783
|
+
Captures writes from all clients.'
|
|
784
|
+
Customer:
|
|
785
|
+
type: object
|
|
786
|
+
properties:
|
|
787
|
+
id:
|
|
788
|
+
type: string
|
|
789
|
+
readOnly: true
|
|
790
|
+
description: (Read-only) Firestore document ID. This is the canonical FK
|
|
791
|
+
target — other models reference Customer via this field.
|
|
792
|
+
uid:
|
|
793
|
+
type: string
|
|
794
|
+
readOnly: true
|
|
795
|
+
description: (Read-only) Entity UID. Often mirrors id.
|
|
796
|
+
name:
|
|
797
|
+
type: string
|
|
798
|
+
email:
|
|
799
|
+
type:
|
|
800
|
+
- string
|
|
801
|
+
- 'null'
|
|
802
|
+
phone:
|
|
803
|
+
type:
|
|
804
|
+
- string
|
|
805
|
+
- 'null'
|
|
806
|
+
address:
|
|
807
|
+
type:
|
|
808
|
+
- string
|
|
809
|
+
- 'null'
|
|
810
|
+
notes:
|
|
811
|
+
type:
|
|
812
|
+
- string
|
|
813
|
+
- 'null'
|
|
814
|
+
tags:
|
|
815
|
+
type:
|
|
816
|
+
- array
|
|
817
|
+
- 'null'
|
|
818
|
+
items:
|
|
819
|
+
type: string
|
|
820
|
+
communicationEntries:
|
|
821
|
+
description: Embedded CRM log (D25). Stays as array, not subcollection.
|
|
822
|
+
type:
|
|
823
|
+
- array
|
|
824
|
+
- 'null'
|
|
825
|
+
items:
|
|
826
|
+
type: object
|
|
827
|
+
properties:
|
|
828
|
+
timestamp:
|
|
829
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
830
|
+
description: Firestore Timestamp serialized representation
|
|
831
|
+
type:
|
|
832
|
+
type: string
|
|
833
|
+
description: Communication channel (e.g. phone, email, meeting).
|
|
834
|
+
summary:
|
|
835
|
+
type: string
|
|
836
|
+
staffMember:
|
|
837
|
+
description: Staff member name involved in this communication.
|
|
838
|
+
type: string
|
|
839
|
+
required:
|
|
840
|
+
- timestamp
|
|
841
|
+
- type
|
|
842
|
+
- summary
|
|
843
|
+
additionalProperties: false
|
|
844
|
+
description: CRM communication log entry (D25). Embedded array on Customer
|
|
845
|
+
document.
|
|
846
|
+
createdAt:
|
|
847
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
848
|
+
description: (Read-only) Server-generated creation timestamp.
|
|
849
|
+
readOnly: true
|
|
850
|
+
lastOrderDate:
|
|
851
|
+
anyOf:
|
|
852
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
853
|
+
- type: 'null'
|
|
854
|
+
readOnly: true
|
|
855
|
+
description: (Read-only) Updated by server when orders are placed.
|
|
856
|
+
balance:
|
|
857
|
+
readOnly: true
|
|
858
|
+
description: (Read-only) Outstanding balance. Dashboard-originated, server-calculated.
|
|
859
|
+
type:
|
|
860
|
+
- number
|
|
861
|
+
- 'null'
|
|
862
|
+
creditLimit:
|
|
863
|
+
type:
|
|
864
|
+
- number
|
|
865
|
+
- 'null'
|
|
866
|
+
lastPaymentDate:
|
|
867
|
+
anyOf:
|
|
868
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
869
|
+
- type: 'null'
|
|
870
|
+
readOnly: true
|
|
871
|
+
description: (Read-only) Updated by server when payments are recorded.
|
|
872
|
+
totalPaid:
|
|
873
|
+
readOnly: true
|
|
874
|
+
description: (Read-only) Server-calculated total paid amount.
|
|
875
|
+
type:
|
|
876
|
+
- number
|
|
877
|
+
- 'null'
|
|
878
|
+
totalOwed:
|
|
879
|
+
readOnly: true
|
|
880
|
+
description: (Read-only) Server-calculated total owed amount.
|
|
881
|
+
type:
|
|
882
|
+
- number
|
|
883
|
+
- 'null'
|
|
884
|
+
loyaltyPoints:
|
|
885
|
+
denormalized: true
|
|
886
|
+
readOnly: true
|
|
887
|
+
description: (Read-only, Denormalized) Derived summary from loyalty/status
|
|
888
|
+
subcollection (D08). Source of truth is LoyaltyStatus.pointsBalance.
|
|
889
|
+
type:
|
|
890
|
+
- number
|
|
891
|
+
- 'null'
|
|
892
|
+
required:
|
|
893
|
+
- id
|
|
894
|
+
- uid
|
|
895
|
+
- name
|
|
896
|
+
- createdAt
|
|
897
|
+
additionalProperties: false
|
|
898
|
+
description: 'Customer model. Collection: companies/{companyId}/customers/{customerId}.
|
|
899
|
+
Canonical across all platforms.'
|
|
900
|
+
CustomerCreate:
|
|
901
|
+
allOf:
|
|
902
|
+
- $ref: '#/components/schemas/Customer'
|
|
903
|
+
description: Write payload for creating a new Customer document. Fields marked
|
|
904
|
+
`readOnly` are server-set and must not be included. Fields marked `x-immutable`
|
|
905
|
+
may be set once at creation.
|
|
906
|
+
required:
|
|
907
|
+
- name
|
|
908
|
+
CustomerUpdate:
|
|
909
|
+
allOf:
|
|
910
|
+
- $ref: '#/components/schemas/Customer'
|
|
911
|
+
description: Write payload for partial update (PATCH) of a Customer document.
|
|
912
|
+
All fields optional. Fields marked `readOnly` or `x-immutable` must not be
|
|
913
|
+
sent.
|
|
914
|
+
CustomerPayment:
|
|
915
|
+
type: object
|
|
916
|
+
properties:
|
|
917
|
+
id:
|
|
918
|
+
readOnly: true
|
|
919
|
+
description: '(Read-only) Firestore document ID. Note: optional in current
|
|
920
|
+
schema — some legacy docs may lack this field.'
|
|
921
|
+
type:
|
|
922
|
+
- string
|
|
923
|
+
- 'null'
|
|
924
|
+
companyId:
|
|
925
|
+
type: string
|
|
926
|
+
x-immutable: true
|
|
927
|
+
description: (Immutable) FK → Company document ID. Scopes all queries.
|
|
928
|
+
customerId:
|
|
929
|
+
type: string
|
|
930
|
+
x-immutable: true
|
|
931
|
+
description: (Immutable) FK → Customer.id (Firestore doc ID). Links payment
|
|
932
|
+
to customer. Set at creation.
|
|
933
|
+
customerName:
|
|
934
|
+
denormalized: true
|
|
935
|
+
description: (Denormalized) From Customer.name at write time.
|
|
936
|
+
type:
|
|
937
|
+
- string
|
|
938
|
+
- 'null'
|
|
939
|
+
amount:
|
|
940
|
+
type: number
|
|
941
|
+
currency:
|
|
942
|
+
type: string
|
|
943
|
+
const: XOF
|
|
944
|
+
description: Currency code. Locked to XOF (West African CFA franc) for now.
|
|
945
|
+
paymentDate:
|
|
946
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
947
|
+
description: Firestore Timestamp serialized representation
|
|
948
|
+
paymentMethod:
|
|
949
|
+
$ref: '#/components/schemas/PaymentMethod'
|
|
950
|
+
description: Unified payment method set with African + global methods (D02).
|
|
951
|
+
referenceNumber:
|
|
952
|
+
type: string
|
|
953
|
+
description: Unique payment reference (receipt number, transaction ID, etc.).
|
|
954
|
+
allocatedAmount:
|
|
955
|
+
type: number
|
|
956
|
+
readOnly: true
|
|
957
|
+
description: (Read-only) Total amount allocated to bookings/orders/purchases
|
|
958
|
+
via allocations. Server-calculated.
|
|
959
|
+
unappliedAmount:
|
|
960
|
+
type: number
|
|
961
|
+
readOnly: true
|
|
962
|
+
description: (Read-only) Remaining unallocated amount (amount - allocatedAmount).
|
|
963
|
+
Server-calculated.
|
|
964
|
+
status:
|
|
965
|
+
$ref: '#/components/schemas/CustomerPaymentStatus'
|
|
966
|
+
description: Customer payment lifecycle status (D22). Tracks allocation
|
|
967
|
+
progress of received payments.
|
|
968
|
+
notes:
|
|
969
|
+
type:
|
|
970
|
+
- string
|
|
971
|
+
- 'null'
|
|
972
|
+
recordedBy:
|
|
973
|
+
type: string
|
|
974
|
+
x-immutable: true
|
|
975
|
+
description: (Immutable) FK → User/staff UID who recorded the payment. Required
|
|
976
|
+
audit field (D22/IG-7).
|
|
977
|
+
recordedByName:
|
|
978
|
+
x-immutable: true
|
|
979
|
+
denormalized: true
|
|
980
|
+
description: (Immutable, Denormalized) From User display name at creation
|
|
981
|
+
time.
|
|
982
|
+
type:
|
|
983
|
+
- string
|
|
984
|
+
- 'null'
|
|
985
|
+
createdAt:
|
|
986
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
987
|
+
description: (Read-only) Server-generated creation timestamp.
|
|
988
|
+
readOnly: true
|
|
989
|
+
updatedAt:
|
|
990
|
+
anyOf:
|
|
991
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
992
|
+
- type: 'null'
|
|
993
|
+
readOnly: true
|
|
994
|
+
description: (Read-only) Server-generated update timestamp.
|
|
995
|
+
required:
|
|
996
|
+
- companyId
|
|
997
|
+
- customerId
|
|
998
|
+
- amount
|
|
999
|
+
- currency
|
|
1000
|
+
- paymentDate
|
|
1001
|
+
- paymentMethod
|
|
1002
|
+
- referenceNumber
|
|
1003
|
+
- allocatedAmount
|
|
1004
|
+
- unappliedAmount
|
|
1005
|
+
- status
|
|
1006
|
+
- recordedBy
|
|
1007
|
+
- createdAt
|
|
1008
|
+
additionalProperties: false
|
|
1009
|
+
description: 'CustomerPayment model (D22). Collection: companies/{companyId}/customerPayments/{paymentId}.
|
|
1010
|
+
Dashboard-only today; Mobile read in Wave 2, write in Wave 4 (trusted-party
|
|
1011
|
+
workflow).'
|
|
1012
|
+
CustomerPaymentCreate:
|
|
1013
|
+
allOf:
|
|
1014
|
+
- $ref: '#/components/schemas/CustomerPayment'
|
|
1015
|
+
description: Write payload for creating a new CustomerPayment document. Fields
|
|
1016
|
+
marked `readOnly` are server-set and must not be included. Fields marked `x-immutable`
|
|
1017
|
+
may be set once at creation.
|
|
1018
|
+
required:
|
|
1019
|
+
- companyId
|
|
1020
|
+
- customerId
|
|
1021
|
+
- amount
|
|
1022
|
+
- currency
|
|
1023
|
+
- paymentDate
|
|
1024
|
+
- paymentMethod
|
|
1025
|
+
- referenceNumber
|
|
1026
|
+
- status
|
|
1027
|
+
- recordedBy
|
|
1028
|
+
CustomerPaymentUpdate:
|
|
1029
|
+
allOf:
|
|
1030
|
+
- $ref: '#/components/schemas/CustomerPayment'
|
|
1031
|
+
description: Write payload for partial update (PATCH) of a CustomerPayment document.
|
|
1032
|
+
All fields optional. Fields marked `readOnly` or `x-immutable` must not be
|
|
1033
|
+
sent.
|
|
1034
|
+
CustomerPaymentAllocation:
|
|
1035
|
+
type: object
|
|
1036
|
+
properties:
|
|
1037
|
+
id:
|
|
1038
|
+
readOnly: true
|
|
1039
|
+
description: '(Read-only) Firestore document ID. Note: optional in current
|
|
1040
|
+
schema.'
|
|
1041
|
+
type:
|
|
1042
|
+
- string
|
|
1043
|
+
- 'null'
|
|
1044
|
+
companyId:
|
|
1045
|
+
type: string
|
|
1046
|
+
x-immutable: true
|
|
1047
|
+
description: (Immutable) FK → Company document ID.
|
|
1048
|
+
paymentId:
|
|
1049
|
+
type: string
|
|
1050
|
+
x-immutable: true
|
|
1051
|
+
description: (Immutable) FK → CustomerPayment.id. Parent payment this allocation
|
|
1052
|
+
draws from.
|
|
1053
|
+
customerId:
|
|
1054
|
+
type: string
|
|
1055
|
+
x-immutable: true
|
|
1056
|
+
description: (Immutable) FK → Customer.id (Firestore doc ID).
|
|
1057
|
+
targetId:
|
|
1058
|
+
type: string
|
|
1059
|
+
x-immutable: true
|
|
1060
|
+
description: (Immutable) FK → Booking.id, Order.id, or Sale.id (polymorphic).
|
|
1061
|
+
See targetType for discriminator.
|
|
1062
|
+
targetType:
|
|
1063
|
+
$ref: '#/components/schemas/CustomerPaymentTargetType'
|
|
1064
|
+
description: '(Immutable) Discriminator for targetId: BOOKING, ORDER, or
|
|
1065
|
+
PURCHASE.'
|
|
1066
|
+
x-immutable: true
|
|
1067
|
+
targetReference:
|
|
1068
|
+
type:
|
|
1069
|
+
- string
|
|
1070
|
+
- 'null'
|
|
1071
|
+
allocatedAmount:
|
|
1072
|
+
type: number
|
|
1073
|
+
x-immutable: true
|
|
1074
|
+
description: (Immutable) Amount allocated in this allocation. Set at creation.
|
|
1075
|
+
transferredToAllocationId:
|
|
1076
|
+
description: FK → CustomerPaymentAllocation.id. Self-reference for transfer
|
|
1077
|
+
chains.
|
|
1078
|
+
type:
|
|
1079
|
+
- string
|
|
1080
|
+
- 'null'
|
|
1081
|
+
transferredFromAllocationId:
|
|
1082
|
+
description: FK → CustomerPaymentAllocation.id. Self-reference for transfer
|
|
1083
|
+
chains.
|
|
1084
|
+
type:
|
|
1085
|
+
- string
|
|
1086
|
+
- 'null'
|
|
1087
|
+
transferredAt:
|
|
1088
|
+
anyOf:
|
|
1089
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
1090
|
+
- type: 'null'
|
|
1091
|
+
description: Firestore Timestamp serialized representation
|
|
1092
|
+
createdBy:
|
|
1093
|
+
type: string
|
|
1094
|
+
x-immutable: true
|
|
1095
|
+
description: (Immutable) FK → User/staff UID who created this allocation.
|
|
1096
|
+
createdByName:
|
|
1097
|
+
x-immutable: true
|
|
1098
|
+
denormalized: true
|
|
1099
|
+
description: (Immutable, Denormalized) From User display name at creation
|
|
1100
|
+
time.
|
|
1101
|
+
type:
|
|
1102
|
+
- string
|
|
1103
|
+
- 'null'
|
|
1104
|
+
createdAt:
|
|
1105
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
1106
|
+
description: (Read-only) Server-generated creation timestamp.
|
|
1107
|
+
readOnly: true
|
|
1108
|
+
required:
|
|
1109
|
+
- companyId
|
|
1110
|
+
- paymentId
|
|
1111
|
+
- customerId
|
|
1112
|
+
- targetId
|
|
1113
|
+
- targetType
|
|
1114
|
+
- allocatedAmount
|
|
1115
|
+
- createdBy
|
|
1116
|
+
- createdAt
|
|
1117
|
+
additionalProperties: false
|
|
1118
|
+
description: 'CustomerPaymentAllocation model. Collection: companies/{companyId}/customerPaymentAllocations/{allocId}.
|
|
1119
|
+
Links customer payments to bookings, orders, or purchases.'
|
|
1120
|
+
CustomerPaymentAllocationCreate:
|
|
1121
|
+
allOf:
|
|
1122
|
+
- $ref: '#/components/schemas/CustomerPaymentAllocation'
|
|
1123
|
+
description: Write payload for creating a new CustomerPaymentAllocation document.
|
|
1124
|
+
Fields marked `readOnly` are server-set and must not be included. Fields marked
|
|
1125
|
+
`x-immutable` may be set once at creation.
|
|
1126
|
+
required:
|
|
1127
|
+
- companyId
|
|
1128
|
+
- paymentId
|
|
1129
|
+
- customerId
|
|
1130
|
+
- targetId
|
|
1131
|
+
- targetType
|
|
1132
|
+
- allocatedAmount
|
|
1133
|
+
- createdBy
|
|
1134
|
+
CustomerPaymentAllocationUpdate:
|
|
1135
|
+
allOf:
|
|
1136
|
+
- $ref: '#/components/schemas/CustomerPaymentAllocation'
|
|
1137
|
+
description: Write payload for partial update (PATCH) of a CustomerPaymentAllocation
|
|
1138
|
+
document. All fields optional. Fields marked `readOnly` or `x-immutable` must
|
|
1139
|
+
not be sent.
|
|
1140
|
+
Event:
|
|
1141
|
+
type: object
|
|
1142
|
+
properties:
|
|
1143
|
+
id:
|
|
1144
|
+
type: string
|
|
1145
|
+
readOnly: true
|
|
1146
|
+
description: '(Read-only) Firestore document ID. Note: Event does not have
|
|
1147
|
+
a uid field.'
|
|
1148
|
+
companyId:
|
|
1149
|
+
type: string
|
|
1150
|
+
x-immutable: true
|
|
1151
|
+
description: (Immutable) FK → Company document ID. Scopes all queries.
|
|
1152
|
+
name:
|
|
1153
|
+
type: string
|
|
1154
|
+
description:
|
|
1155
|
+
type:
|
|
1156
|
+
- string
|
|
1157
|
+
- 'null'
|
|
1158
|
+
location:
|
|
1159
|
+
type:
|
|
1160
|
+
- string
|
|
1161
|
+
- 'null'
|
|
1162
|
+
startDate:
|
|
1163
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
1164
|
+
description: Firestore Timestamp serialized representation
|
|
1165
|
+
endDate:
|
|
1166
|
+
anyOf:
|
|
1167
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
1168
|
+
- type: 'null'
|
|
1169
|
+
description: Firestore Timestamp serialized representation
|
|
1170
|
+
status:
|
|
1171
|
+
$ref: '#/components/schemas/EventStatus'
|
|
1172
|
+
description: Event lifecycle status (D32). SCREAMING_SNAKE per D04. MIG-09
|
|
1173
|
+
migrates legacy lowercase values.
|
|
1174
|
+
maxTickets:
|
|
1175
|
+
type:
|
|
1176
|
+
- integer
|
|
1177
|
+
- 'null'
|
|
1178
|
+
minimum: -9007199254740991
|
|
1179
|
+
maximum: 9007199254740991
|
|
1180
|
+
ticketsSold:
|
|
1181
|
+
type: integer
|
|
1182
|
+
minimum: -9007199254740991
|
|
1183
|
+
maximum: 9007199254740991
|
|
1184
|
+
readOnly: true
|
|
1185
|
+
description: '(Read-only) Counter: total tickets sold. Updated by Firebase
|
|
1186
|
+
triggers (D28).'
|
|
1187
|
+
ticketsUsed:
|
|
1188
|
+
type: integer
|
|
1189
|
+
minimum: -9007199254740991
|
|
1190
|
+
maximum: 9007199254740991
|
|
1191
|
+
readOnly: true
|
|
1192
|
+
description: '(Read-only) Counter: tickets scanned/used. Updated by Firebase
|
|
1193
|
+
triggers (D28).'
|
|
1194
|
+
ticketPrice:
|
|
1195
|
+
type:
|
|
1196
|
+
- number
|
|
1197
|
+
- 'null'
|
|
1198
|
+
createdAt:
|
|
1199
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
1200
|
+
description: (Read-only) Server-generated creation timestamp.
|
|
1201
|
+
readOnly: true
|
|
1202
|
+
updatedAt:
|
|
1203
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
1204
|
+
description: (Read-only) Server-generated update timestamp.
|
|
1205
|
+
readOnly: true
|
|
1206
|
+
createdBy:
|
|
1207
|
+
x-immutable: true
|
|
1208
|
+
description: (Immutable) FK → User/staff UID who created this event.
|
|
1209
|
+
type:
|
|
1210
|
+
- string
|
|
1211
|
+
- 'null'
|
|
1212
|
+
required:
|
|
1213
|
+
- id
|
|
1214
|
+
- companyId
|
|
1215
|
+
- name
|
|
1216
|
+
- startDate
|
|
1217
|
+
- status
|
|
1218
|
+
- ticketsSold
|
|
1219
|
+
- ticketsUsed
|
|
1220
|
+
- createdAt
|
|
1221
|
+
- updatedAt
|
|
1222
|
+
additionalProperties: false
|
|
1223
|
+
description: 'Event model (D26, D32). Collection: companies/{companyId}/events/{eventId}.
|
|
1224
|
+
Mobile-only today; Dashboard in Wave 4.'
|
|
1225
|
+
EventCreate:
|
|
1226
|
+
allOf:
|
|
1227
|
+
- $ref: '#/components/schemas/Event'
|
|
1228
|
+
description: Write payload for creating a new Event document. Fields marked
|
|
1229
|
+
`readOnly` are server-set and must not be included. Fields marked `x-immutable`
|
|
1230
|
+
may be set once at creation.
|
|
1231
|
+
required:
|
|
1232
|
+
- companyId
|
|
1233
|
+
- name
|
|
1234
|
+
- startDate
|
|
1235
|
+
- status
|
|
1236
|
+
EventUpdate:
|
|
1237
|
+
allOf:
|
|
1238
|
+
- $ref: '#/components/schemas/Event'
|
|
1239
|
+
description: Write payload for partial update (PATCH) of a Event document. All
|
|
1240
|
+
fields optional. Fields marked `readOnly` or `x-immutable` must not be sent.
|
|
1241
|
+
LoyaltyConfig:
|
|
1242
|
+
type: object
|
|
1243
|
+
properties:
|
|
1244
|
+
id:
|
|
1245
|
+
readOnly: true
|
|
1246
|
+
description: (Read-only) Firestore document ID. Singleton doc — typically
|
|
1247
|
+
"config".
|
|
1248
|
+
type:
|
|
1249
|
+
- string
|
|
1250
|
+
- 'null'
|
|
1251
|
+
isEnabled:
|
|
1252
|
+
type: boolean
|
|
1253
|
+
pointSystem:
|
|
1254
|
+
type: string
|
|
1255
|
+
enum:
|
|
1256
|
+
- SPENDING
|
|
1257
|
+
- PRODUCT
|
|
1258
|
+
- VISIT
|
|
1259
|
+
description: 'How points are earned: SPENDING (per currency spent), PRODUCT
|
|
1260
|
+
(per product purchased), or VISIT (per visit). SCREAMING_SNAKE per D04.'
|
|
1261
|
+
pointsPerCurrency:
|
|
1262
|
+
description: '[Deprecated alias: pointsPerCurrencyUnit — renamed by MIG-06]'
|
|
1263
|
+
deprecated: true
|
|
1264
|
+
type:
|
|
1265
|
+
- number
|
|
1266
|
+
- 'null'
|
|
1267
|
+
pointsPerVisit:
|
|
1268
|
+
description: Points earned per visit (when pointSystem is visit).
|
|
1269
|
+
type:
|
|
1270
|
+
- number
|
|
1271
|
+
- 'null'
|
|
1272
|
+
pointValue:
|
|
1273
|
+
description: Monetary value of one point for redemption.
|
|
1274
|
+
type:
|
|
1275
|
+
- number
|
|
1276
|
+
- 'null'
|
|
1277
|
+
minimumRedeemPoints:
|
|
1278
|
+
description: Minimum points balance required before redemption is allowed.
|
|
1279
|
+
type:
|
|
1280
|
+
- integer
|
|
1281
|
+
- 'null'
|
|
1282
|
+
minimum: -9007199254740991
|
|
1283
|
+
maximum: 9007199254740991
|
|
1284
|
+
welcomeBonusPoints:
|
|
1285
|
+
description: One-time points bonus for new loyalty enrollees.
|
|
1286
|
+
type:
|
|
1287
|
+
- integer
|
|
1288
|
+
- 'null'
|
|
1289
|
+
minimum: -9007199254740991
|
|
1290
|
+
maximum: 9007199254740991
|
|
1291
|
+
pointsExpirationDays:
|
|
1292
|
+
description: '[Deprecated alias: pointsExpiryMonths — renamed and converted
|
|
1293
|
+
months*30 to days by MIG-06]'
|
|
1294
|
+
deprecated: true
|
|
1295
|
+
anyOf:
|
|
1296
|
+
- type: integer
|
|
1297
|
+
minimum: -9007199254740991
|
|
1298
|
+
maximum: 9007199254740991
|
|
1299
|
+
- type: 'null'
|
|
1300
|
+
createdAt:
|
|
1301
|
+
anyOf:
|
|
1302
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
1303
|
+
- type: 'null'
|
|
1304
|
+
readOnly: true
|
|
1305
|
+
description: (Read-only) Server-generated creation timestamp.
|
|
1306
|
+
updatedAt:
|
|
1307
|
+
anyOf:
|
|
1308
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
1309
|
+
- type: 'null'
|
|
1310
|
+
readOnly: true
|
|
1311
|
+
description: (Read-only) Server-generated update timestamp.
|
|
1312
|
+
required:
|
|
1313
|
+
- isEnabled
|
|
1314
|
+
- pointSystem
|
|
1315
|
+
additionalProperties: false
|
|
1316
|
+
description: 'LoyaltyConfig model (D21). Collection: companies/{companyId}/loyaltySettings/config.
|
|
1317
|
+
1 doc per company. Uses canonical field names per D21 (MIG-06 renames legacy
|
|
1318
|
+
aliases).'
|
|
1319
|
+
LoyaltyConfigCreate:
|
|
1320
|
+
allOf:
|
|
1321
|
+
- $ref: '#/components/schemas/LoyaltyConfig'
|
|
1322
|
+
description: Write payload for creating a new LoyaltyConfig document. Fields
|
|
1323
|
+
marked `readOnly` are server-set and must not be included. Fields marked `x-immutable`
|
|
1324
|
+
may be set once at creation.
|
|
1325
|
+
required:
|
|
1326
|
+
- isEnabled
|
|
1327
|
+
- pointSystem
|
|
1328
|
+
LoyaltyConfigUpdate:
|
|
1329
|
+
allOf:
|
|
1330
|
+
- $ref: '#/components/schemas/LoyaltyConfig'
|
|
1331
|
+
description: Write payload for partial update (PATCH) of a LoyaltyConfig document.
|
|
1332
|
+
All fields optional. Fields marked `readOnly` or `x-immutable` must not be
|
|
1333
|
+
sent.
|
|
1334
|
+
LoyaltyReward:
|
|
1335
|
+
type: object
|
|
1336
|
+
properties:
|
|
1337
|
+
id:
|
|
1338
|
+
type: string
|
|
1339
|
+
readOnly: true
|
|
1340
|
+
description: (Read-only) Firestore document ID.
|
|
1341
|
+
name:
|
|
1342
|
+
type: string
|
|
1343
|
+
description:
|
|
1344
|
+
type:
|
|
1345
|
+
- string
|
|
1346
|
+
- 'null'
|
|
1347
|
+
pointsRequired:
|
|
1348
|
+
type: integer
|
|
1349
|
+
minimum: -9007199254740991
|
|
1350
|
+
maximum: 9007199254740991
|
|
1351
|
+
description: Points cost to redeem this reward.
|
|
1352
|
+
isActive:
|
|
1353
|
+
type: boolean
|
|
1354
|
+
description: Whether this reward is currently available for redemption.
|
|
1355
|
+
imageUrl:
|
|
1356
|
+
type:
|
|
1357
|
+
- string
|
|
1358
|
+
- 'null'
|
|
1359
|
+
rewardType:
|
|
1360
|
+
description: Category of reward (e.g. discount, free_item, service).
|
|
1361
|
+
type:
|
|
1362
|
+
- string
|
|
1363
|
+
- 'null'
|
|
1364
|
+
discountValue:
|
|
1365
|
+
description: Discount amount when rewardType is discount.
|
|
1366
|
+
type:
|
|
1367
|
+
- number
|
|
1368
|
+
- 'null'
|
|
1369
|
+
productId:
|
|
1370
|
+
description: FK → Product.id. Linked product when rewardType is free_item.
|
|
1371
|
+
type:
|
|
1372
|
+
- string
|
|
1373
|
+
- 'null'
|
|
1374
|
+
createdAt:
|
|
1375
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
1376
|
+
description: (Read-only) Server-generated creation timestamp.
|
|
1377
|
+
readOnly: true
|
|
1378
|
+
updatedAt:
|
|
1379
|
+
anyOf:
|
|
1380
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
1381
|
+
- type: 'null'
|
|
1382
|
+
readOnly: true
|
|
1383
|
+
description: (Read-only) Server-generated update timestamp.
|
|
1384
|
+
required:
|
|
1385
|
+
- id
|
|
1386
|
+
- name
|
|
1387
|
+
- pointsRequired
|
|
1388
|
+
- isActive
|
|
1389
|
+
- createdAt
|
|
1390
|
+
additionalProperties: false
|
|
1391
|
+
description: 'LoyaltyReward model. Collection: companies/{companyId}/loyaltyRewards/{rewardId}.
|
|
1392
|
+
Reward catalog for point redemption (IG-10).'
|
|
1393
|
+
LoyaltyRewardCreate:
|
|
1394
|
+
allOf:
|
|
1395
|
+
- $ref: '#/components/schemas/LoyaltyReward'
|
|
1396
|
+
description: Write payload for creating a new LoyaltyReward document. Fields
|
|
1397
|
+
marked `readOnly` are server-set and must not be included. Fields marked `x-immutable`
|
|
1398
|
+
may be set once at creation.
|
|
1399
|
+
required:
|
|
1400
|
+
- name
|
|
1401
|
+
- pointsRequired
|
|
1402
|
+
- isActive
|
|
1403
|
+
LoyaltyRewardUpdate:
|
|
1404
|
+
allOf:
|
|
1405
|
+
- $ref: '#/components/schemas/LoyaltyReward'
|
|
1406
|
+
description: Write payload for partial update (PATCH) of a LoyaltyReward document.
|
|
1407
|
+
All fields optional. Fields marked `readOnly` or `x-immutable` must not be
|
|
1408
|
+
sent.
|
|
1409
|
+
LoyaltyStatus:
|
|
1410
|
+
type: object
|
|
1411
|
+
properties:
|
|
1412
|
+
customerId:
|
|
1413
|
+
x-immutable: true
|
|
1414
|
+
description: '(Immutable) FK → Customer.id. Note: optional despite being
|
|
1415
|
+
in customer subcollection (path already contains custId).'
|
|
1416
|
+
type:
|
|
1417
|
+
- string
|
|
1418
|
+
- 'null'
|
|
1419
|
+
pointsBalance:
|
|
1420
|
+
type: integer
|
|
1421
|
+
minimum: -9007199254740991
|
|
1422
|
+
maximum: 9007199254740991
|
|
1423
|
+
readOnly: true
|
|
1424
|
+
description: '(Read-only) Current available points balance. Canonical name
|
|
1425
|
+
(D08). Dashboard: pointsBalance, Mobile: currentPoints. Updated by transaction
|
|
1426
|
+
triggers.'
|
|
1427
|
+
totalPointsEarned:
|
|
1428
|
+
type: integer
|
|
1429
|
+
minimum: -9007199254740991
|
|
1430
|
+
maximum: 9007199254740991
|
|
1431
|
+
readOnly: true
|
|
1432
|
+
description: '(Read-only) Lifetime total points earned. Canonical name (D08).
|
|
1433
|
+
Dashboard: totalPointsEarned, Mobile: lifetimePoints. Updated by transaction
|
|
1434
|
+
triggers.'
|
|
1435
|
+
redeemedPoints:
|
|
1436
|
+
readOnly: true
|
|
1437
|
+
description: (Read-only) Total redeemed points. Updated by transaction triggers.
|
|
1438
|
+
type:
|
|
1439
|
+
- integer
|
|
1440
|
+
- 'null'
|
|
1441
|
+
minimum: -9007199254740991
|
|
1442
|
+
maximum: 9007199254740991
|
|
1443
|
+
lastActivityDate:
|
|
1444
|
+
anyOf:
|
|
1445
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
1446
|
+
- type: 'null'
|
|
1447
|
+
readOnly: true
|
|
1448
|
+
description: '(Read-only) Last earn/redeem activity. Canonical name (D08).
|
|
1449
|
+
Mobile alias: lastEarnedAt.'
|
|
1450
|
+
lastRedeemedAt:
|
|
1451
|
+
anyOf:
|
|
1452
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
1453
|
+
- type: 'null'
|
|
1454
|
+
readOnly: true
|
|
1455
|
+
description: (Read-only) Last redemption timestamp.
|
|
1456
|
+
tier:
|
|
1457
|
+
type:
|
|
1458
|
+
- string
|
|
1459
|
+
- 'null'
|
|
1460
|
+
createdAt:
|
|
1461
|
+
anyOf:
|
|
1462
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
1463
|
+
- type: 'null'
|
|
1464
|
+
readOnly: true
|
|
1465
|
+
description: (Read-only) Server-generated creation timestamp.
|
|
1466
|
+
updatedAt:
|
|
1467
|
+
anyOf:
|
|
1468
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
1469
|
+
- type: 'null'
|
|
1470
|
+
readOnly: true
|
|
1471
|
+
description: (Read-only) Server-generated update timestamp.
|
|
1472
|
+
required:
|
|
1473
|
+
- pointsBalance
|
|
1474
|
+
- totalPointsEarned
|
|
1475
|
+
additionalProperties: false
|
|
1476
|
+
description: 'LoyaltyStatus model (D08). Collection: companies/{companyId}/customers/{custId}/loyalty/status.
|
|
1477
|
+
Source of truth for customer points. Customer doc loyaltyPoints is a derived
|
|
1478
|
+
summary only.'
|
|
1479
|
+
LoyaltyTransaction:
|
|
1480
|
+
type: object
|
|
1481
|
+
properties:
|
|
1482
|
+
id:
|
|
1483
|
+
type: string
|
|
1484
|
+
readOnly: true
|
|
1485
|
+
description: (Read-only) Firestore document ID.
|
|
1486
|
+
customerId:
|
|
1487
|
+
x-immutable: true
|
|
1488
|
+
description: '(Immutable) FK → Customer.id. Note: optional despite being
|
|
1489
|
+
in customer subcollection.'
|
|
1490
|
+
type:
|
|
1491
|
+
- string
|
|
1492
|
+
- 'null'
|
|
1493
|
+
type:
|
|
1494
|
+
$ref: '#/components/schemas/LoyaltyTransactionType'
|
|
1495
|
+
description: (Immutable) Transaction type (D07). SCREAMING_SNAKE per D04.
|
|
1496
|
+
MIG-05 migrates legacy lowercase values.
|
|
1497
|
+
x-immutable: true
|
|
1498
|
+
pointsChange:
|
|
1499
|
+
type: integer
|
|
1500
|
+
minimum: -9007199254740991
|
|
1501
|
+
maximum: 9007199254740991
|
|
1502
|
+
x-immutable: true
|
|
1503
|
+
description: '(Immutable) Points delta (+/-). Canonical name (D07). Dashboard:
|
|
1504
|
+
pointsChange, Mobile: points.'
|
|
1505
|
+
description:
|
|
1506
|
+
type:
|
|
1507
|
+
- string
|
|
1508
|
+
- 'null'
|
|
1509
|
+
reason:
|
|
1510
|
+
type:
|
|
1511
|
+
- string
|
|
1512
|
+
- 'null'
|
|
1513
|
+
relatedPurchaseId:
|
|
1514
|
+
x-immutable: true
|
|
1515
|
+
description: (Immutable) FK → Sale.id. Linked sale that triggered this transaction.
|
|
1516
|
+
type:
|
|
1517
|
+
- string
|
|
1518
|
+
- 'null'
|
|
1519
|
+
relatedOrderId:
|
|
1520
|
+
x-immutable: true
|
|
1521
|
+
description: (Immutable) FK → Order.id. Linked order that triggered this
|
|
1522
|
+
transaction.
|
|
1523
|
+
type:
|
|
1524
|
+
- string
|
|
1525
|
+
- 'null'
|
|
1526
|
+
relatedRewardId:
|
|
1527
|
+
x-immutable: true
|
|
1528
|
+
description: (Immutable) FK → LoyaltyReward.id. Reward redeemed in this
|
|
1529
|
+
transaction.
|
|
1530
|
+
type:
|
|
1531
|
+
- string
|
|
1532
|
+
- 'null'
|
|
1533
|
+
orderId:
|
|
1534
|
+
x-immutable: true
|
|
1535
|
+
description: '(Immutable) FK → Order.id. Note: may overlap with relatedOrderId
|
|
1536
|
+
— naming inconsistency from Mobile.'
|
|
1537
|
+
type:
|
|
1538
|
+
- string
|
|
1539
|
+
- 'null'
|
|
1540
|
+
sessionId:
|
|
1541
|
+
description: Session/booking reference. Context-dependent identifier.
|
|
1542
|
+
type:
|
|
1543
|
+
- string
|
|
1544
|
+
- 'null'
|
|
1545
|
+
orderAmount:
|
|
1546
|
+
type:
|
|
1547
|
+
- number
|
|
1548
|
+
- 'null'
|
|
1549
|
+
transactionDate:
|
|
1550
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
1551
|
+
description: '(Immutable) When the transaction occurred. Canonical name
|
|
1552
|
+
(D07). Dashboard: transactionDate, Mobile: createdAt.'
|
|
1553
|
+
x-immutable: true
|
|
1554
|
+
pointsBalanceAfter:
|
|
1555
|
+
readOnly: true
|
|
1556
|
+
description: '(Read-only) Running balance after this transaction. Canonical
|
|
1557
|
+
name (D07). Dashboard: pointsBalanceAfter, Mobile: balanceAfter. Server-calculated.'
|
|
1558
|
+
type:
|
|
1559
|
+
- integer
|
|
1560
|
+
- 'null'
|
|
1561
|
+
minimum: -9007199254740991
|
|
1562
|
+
maximum: 9007199254740991
|
|
1563
|
+
createdBy:
|
|
1564
|
+
x-immutable: true
|
|
1565
|
+
description: (Immutable) FK → User/staff UID who created this transaction.
|
|
1566
|
+
type:
|
|
1567
|
+
- string
|
|
1568
|
+
- 'null'
|
|
1569
|
+
createdByName:
|
|
1570
|
+
x-immutable: true
|
|
1571
|
+
denormalized: true
|
|
1572
|
+
description: (Immutable, Denormalized) From User display name at creation
|
|
1573
|
+
time.
|
|
1574
|
+
type:
|
|
1575
|
+
- string
|
|
1576
|
+
- 'null'
|
|
1577
|
+
required:
|
|
1578
|
+
- id
|
|
1579
|
+
- type
|
|
1580
|
+
- pointsChange
|
|
1581
|
+
- transactionDate
|
|
1582
|
+
additionalProperties: false
|
|
1583
|
+
description: 'LoyaltyTransaction model (D07). Collection: companies/{companyId}/customers/{custId}/loyaltyTransactions/{txId}.
|
|
1584
|
+
Type values use SCREAMING_SNAKE per D04 (MIG-05 migrates lowercase).'
|
|
1585
|
+
LoyaltyTransactionCreate:
|
|
1586
|
+
allOf:
|
|
1587
|
+
- $ref: '#/components/schemas/LoyaltyTransaction'
|
|
1588
|
+
description: Write payload for creating a new LoyaltyTransaction document. Fields
|
|
1589
|
+
marked `readOnly` are server-set and must not be included. Fields marked `x-immutable`
|
|
1590
|
+
may be set once at creation.
|
|
1591
|
+
required:
|
|
1592
|
+
- type
|
|
1593
|
+
- pointsChange
|
|
1594
|
+
- transactionDate
|
|
1595
|
+
LoyaltyTransactionUpdate:
|
|
1596
|
+
allOf:
|
|
1597
|
+
- $ref: '#/components/schemas/LoyaltyTransaction'
|
|
1598
|
+
description: Write payload for partial update (PATCH) of a LoyaltyTransaction
|
|
1599
|
+
document. All fields optional. Fields marked `readOnly` or `x-immutable` must
|
|
1600
|
+
not be sent.
|
|
1601
|
+
MetricsCurrent:
|
|
1602
|
+
type: object
|
|
1603
|
+
properties:
|
|
1604
|
+
todayOrdersCount:
|
|
1605
|
+
type: integer
|
|
1606
|
+
minimum: -9007199254740991
|
|
1607
|
+
maximum: 9007199254740991
|
|
1608
|
+
readOnly: true
|
|
1609
|
+
description: (Read-only) Orders created today (UTC). Resets at midnight.
|
|
1610
|
+
pendingOrdersCount:
|
|
1611
|
+
type: integer
|
|
1612
|
+
minimum: -9007199254740991
|
|
1613
|
+
maximum: 9007199254740991
|
|
1614
|
+
readOnly: true
|
|
1615
|
+
description: (Read-only) Orders currently in PENDING status (all-time cumulative).
|
|
1616
|
+
Corrected by full recalc on order updates.
|
|
1617
|
+
orderCompletionRate30d:
|
|
1618
|
+
type: number
|
|
1619
|
+
readOnly: true
|
|
1620
|
+
description: (Read-only) Percentage of orders completed or delivered in
|
|
1621
|
+
the last 30 days. Always full recalc.
|
|
1622
|
+
todayPurchasesCount:
|
|
1623
|
+
type: integer
|
|
1624
|
+
minimum: -9007199254740991
|
|
1625
|
+
maximum: 9007199254740991
|
|
1626
|
+
readOnly: true
|
|
1627
|
+
description: (Read-only) Purchases created today (UTC). Resets at midnight.
|
|
1628
|
+
todayPurchasesSum:
|
|
1629
|
+
type: number
|
|
1630
|
+
readOnly: true
|
|
1631
|
+
description: (Read-only) Total value of purchases created today (UTC). Resets
|
|
1632
|
+
at midnight.
|
|
1633
|
+
averagePurchaseAmount:
|
|
1634
|
+
type: number
|
|
1635
|
+
readOnly: true
|
|
1636
|
+
description: (Read-only) Average purchase value across last 200 purchases
|
|
1637
|
+
(rolling, not time-windowed).
|
|
1638
|
+
monthlyRevenue:
|
|
1639
|
+
type: number
|
|
1640
|
+
readOnly: true
|
|
1641
|
+
description: (Read-only) Total purchase value in the current calendar month
|
|
1642
|
+
(UTC).
|
|
1643
|
+
monthlyPurchasesCount:
|
|
1644
|
+
type: integer
|
|
1645
|
+
minimum: -9007199254740991
|
|
1646
|
+
maximum: 9007199254740991
|
|
1647
|
+
readOnly: true
|
|
1648
|
+
description: (Read-only) Number of purchases in the current calendar month
|
|
1649
|
+
(UTC).
|
|
1650
|
+
todayBookingsCount:
|
|
1651
|
+
type: integer
|
|
1652
|
+
minimum: -9007199254740991
|
|
1653
|
+
maximum: 9007199254740991
|
|
1654
|
+
readOnly: true
|
|
1655
|
+
description: (Read-only) Bookings with date == today AND status in [PENDING,
|
|
1656
|
+
CONFIRMED]. Resets at midnight.
|
|
1657
|
+
bookingsCreatedToday:
|
|
1658
|
+
type: integer
|
|
1659
|
+
minimum: -9007199254740991
|
|
1660
|
+
maximum: 9007199254740991
|
|
1661
|
+
readOnly: true
|
|
1662
|
+
description: (Read-only) Bookings with createdAt today (all statuses). Resets
|
|
1663
|
+
at midnight.
|
|
1664
|
+
todayBookingsConfirmedAmount:
|
|
1665
|
+
type: number
|
|
1666
|
+
readOnly: true
|
|
1667
|
+
description: (Read-only) Sum of totalAmount for bookings created today with
|
|
1668
|
+
status CONFIRMED or COMPLETED. Resets at midnight.
|
|
1669
|
+
monthlyBookingsConfirmedAmount:
|
|
1670
|
+
type: number
|
|
1671
|
+
readOnly: true
|
|
1672
|
+
description: (Read-only) Sum of totalAmount for bookings created this month
|
|
1673
|
+
with status CONFIRMED or COMPLETED.
|
|
1674
|
+
todayCollectedAmount:
|
|
1675
|
+
type: number
|
|
1676
|
+
readOnly: true
|
|
1677
|
+
description: (Read-only) Sum of totalAmount for bookings where PAYMENT_PAID_AT
|
|
1678
|
+
is today. Resets at midnight.
|
|
1679
|
+
todayRevenue:
|
|
1680
|
+
type: number
|
|
1681
|
+
readOnly: true
|
|
1682
|
+
description: (Read-only) Sum of totalAmount for COMPLETED bookings where
|
|
1683
|
+
startDate == endDate == today (numeric YYYYMMDD). Resets at midnight.
|
|
1684
|
+
bookingsPendingPaymentVerification:
|
|
1685
|
+
type: integer
|
|
1686
|
+
minimum: -9007199254740991
|
|
1687
|
+
maximum: 9007199254740991
|
|
1688
|
+
readOnly: true
|
|
1689
|
+
description: (Read-only) Bookings with status PENDING/CANCELLATION_REQUESTED
|
|
1690
|
+
and a payment proof uploaded but not yet verified. Current state, always
|
|
1691
|
+
full recalc.
|
|
1692
|
+
bookingsPendingValidation:
|
|
1693
|
+
type: integer
|
|
1694
|
+
minimum: -9007199254740991
|
|
1695
|
+
maximum: 9007199254740991
|
|
1696
|
+
readOnly: true
|
|
1697
|
+
description: (Read-only) PENDING bookings with startDate within ±30 days
|
|
1698
|
+
of today. Rolling window, always full recalc.
|
|
1699
|
+
bookingsPendingValidation24h:
|
|
1700
|
+
type: integer
|
|
1701
|
+
minimum: -9007199254740991
|
|
1702
|
+
maximum: 9007199254740991
|
|
1703
|
+
readOnly: true
|
|
1704
|
+
description: (Read-only) PENDING bookings created in the last 24h with startDate
|
|
1705
|
+
>= tomorrow. Always full recalc.
|
|
1706
|
+
customersCount:
|
|
1707
|
+
type: integer
|
|
1708
|
+
minimum: -9007199254740991
|
|
1709
|
+
maximum: 9007199254740991
|
|
1710
|
+
readOnly: true
|
|
1711
|
+
description: (Read-only) Total customer count (all-time cumulative).
|
|
1712
|
+
newCustomersThisMonth:
|
|
1713
|
+
type: integer
|
|
1714
|
+
minimum: -9007199254740991
|
|
1715
|
+
maximum: 9007199254740991
|
|
1716
|
+
readOnly: true
|
|
1717
|
+
description: (Read-only) Customers with createdAt in the current calendar
|
|
1718
|
+
month (UTC).
|
|
1719
|
+
averageRating:
|
|
1720
|
+
type: number
|
|
1721
|
+
readOnly: true
|
|
1722
|
+
description: (Read-only) Average rating from the last 200 reviews (rolling).
|
|
1723
|
+
Always full recalc.
|
|
1724
|
+
lowStockItemsCount:
|
|
1725
|
+
type: integer
|
|
1726
|
+
minimum: -9007199254740991
|
|
1727
|
+
maximum: 9007199254740991
|
|
1728
|
+
readOnly: true
|
|
1729
|
+
description: (Read-only) Active stock items where currentQuantity <= minimumQuantity.
|
|
1730
|
+
Current state, always full recalc.
|
|
1731
|
+
activeRecurringPaymentsCount:
|
|
1732
|
+
type: integer
|
|
1733
|
+
minimum: -9007199254740991
|
|
1734
|
+
maximum: 9007199254740991
|
|
1735
|
+
readOnly: true
|
|
1736
|
+
description: (Read-only) Recurring payments with status ACTIVE. Current
|
|
1737
|
+
state, always full recalc.
|
|
1738
|
+
monthlyRecurringRevenue:
|
|
1739
|
+
type: number
|
|
1740
|
+
readOnly: true
|
|
1741
|
+
description: (Read-only) Sum of amount for ACTIVE + MONTHLY recurring payments.
|
|
1742
|
+
Always full recalc.
|
|
1743
|
+
computedForDay:
|
|
1744
|
+
type: string
|
|
1745
|
+
readOnly: true
|
|
1746
|
+
description: (Read-only) YYYY-MM-DD string indicating which day these metrics
|
|
1747
|
+
reflect. Used to detect day boundaries and trigger midnight resets.
|
|
1748
|
+
generatedAt:
|
|
1749
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
1750
|
+
description: (Read-only) Server timestamp of the last metrics write.
|
|
1751
|
+
readOnly: true
|
|
1752
|
+
required:
|
|
1753
|
+
- todayOrdersCount
|
|
1754
|
+
- pendingOrdersCount
|
|
1755
|
+
- orderCompletionRate30d
|
|
1756
|
+
- todayPurchasesCount
|
|
1757
|
+
- todayPurchasesSum
|
|
1758
|
+
- averagePurchaseAmount
|
|
1759
|
+
- monthlyRevenue
|
|
1760
|
+
- monthlyPurchasesCount
|
|
1761
|
+
- todayBookingsCount
|
|
1762
|
+
- bookingsCreatedToday
|
|
1763
|
+
- todayBookingsConfirmedAmount
|
|
1764
|
+
- monthlyBookingsConfirmedAmount
|
|
1765
|
+
- todayCollectedAmount
|
|
1766
|
+
- todayRevenue
|
|
1767
|
+
- bookingsPendingPaymentVerification
|
|
1768
|
+
- bookingsPendingValidation
|
|
1769
|
+
- bookingsPendingValidation24h
|
|
1770
|
+
- customersCount
|
|
1771
|
+
- newCustomersThisMonth
|
|
1772
|
+
- averageRating
|
|
1773
|
+
- lowStockItemsCount
|
|
1774
|
+
- activeRecurringPaymentsCount
|
|
1775
|
+
- monthlyRecurringRevenue
|
|
1776
|
+
- computedForDay
|
|
1777
|
+
- generatedAt
|
|
1778
|
+
additionalProperties: false
|
|
1779
|
+
description: 'Server-computed company metrics. Collection: companies/{companyId}/metrics/current
|
|
1780
|
+
(singleton). All fields are server-set — clients must never write to this
|
|
1781
|
+
collection. See also MetricsDaily and MetricsMonthly for historical snapshots.'
|
|
1782
|
+
MetricsCurrentCreate:
|
|
1783
|
+
allOf:
|
|
1784
|
+
- $ref: '#/components/schemas/MetricsCurrent'
|
|
1785
|
+
description: Write payload for creating a new MetricsCurrent document. Fields
|
|
1786
|
+
marked `readOnly` are server-set and must not be included. Fields marked `x-immutable`
|
|
1787
|
+
may be set once at creation.
|
|
1788
|
+
MetricsCurrentUpdate:
|
|
1789
|
+
allOf:
|
|
1790
|
+
- $ref: '#/components/schemas/MetricsCurrent'
|
|
1791
|
+
description: Write payload for partial update (PATCH) of a MetricsCurrent document.
|
|
1792
|
+
All fields optional. Fields marked `readOnly` or `x-immutable` must not be
|
|
1793
|
+
sent.
|
|
1794
|
+
MetricsDaily:
|
|
1795
|
+
type: object
|
|
1796
|
+
properties:
|
|
1797
|
+
todayOrdersCount:
|
|
1798
|
+
type: integer
|
|
1799
|
+
minimum: -9007199254740991
|
|
1800
|
+
maximum: 9007199254740991
|
|
1801
|
+
readOnly: true
|
|
1802
|
+
description: (Read-only) Orders created today (UTC). Resets at midnight.
|
|
1803
|
+
pendingOrdersCount:
|
|
1804
|
+
type: integer
|
|
1805
|
+
minimum: -9007199254740991
|
|
1806
|
+
maximum: 9007199254740991
|
|
1807
|
+
readOnly: true
|
|
1808
|
+
description: (Read-only) Orders currently in PENDING status (all-time cumulative).
|
|
1809
|
+
Corrected by full recalc on order updates.
|
|
1810
|
+
orderCompletionRate30d:
|
|
1811
|
+
type: number
|
|
1812
|
+
readOnly: true
|
|
1813
|
+
description: (Read-only) Percentage of orders completed or delivered in
|
|
1814
|
+
the last 30 days. Always full recalc.
|
|
1815
|
+
todayPurchasesCount:
|
|
1816
|
+
type: integer
|
|
1817
|
+
minimum: -9007199254740991
|
|
1818
|
+
maximum: 9007199254740991
|
|
1819
|
+
readOnly: true
|
|
1820
|
+
description: (Read-only) Purchases created today (UTC). Resets at midnight.
|
|
1821
|
+
todayPurchasesSum:
|
|
1822
|
+
type: number
|
|
1823
|
+
readOnly: true
|
|
1824
|
+
description: (Read-only) Total value of purchases created today (UTC). Resets
|
|
1825
|
+
at midnight.
|
|
1826
|
+
averagePurchaseAmount:
|
|
1827
|
+
type: number
|
|
1828
|
+
readOnly: true
|
|
1829
|
+
description: (Read-only) Average purchase value across last 200 purchases
|
|
1830
|
+
(rolling, not time-windowed).
|
|
1831
|
+
monthlyRevenue:
|
|
1832
|
+
type: number
|
|
1833
|
+
readOnly: true
|
|
1834
|
+
description: (Read-only) Total purchase value in the current calendar month
|
|
1835
|
+
(UTC).
|
|
1836
|
+
monthlyPurchasesCount:
|
|
1837
|
+
type: integer
|
|
1838
|
+
minimum: -9007199254740991
|
|
1839
|
+
maximum: 9007199254740991
|
|
1840
|
+
readOnly: true
|
|
1841
|
+
description: (Read-only) Number of purchases in the current calendar month
|
|
1842
|
+
(UTC).
|
|
1843
|
+
todayBookingsCount:
|
|
1844
|
+
type: integer
|
|
1845
|
+
minimum: -9007199254740991
|
|
1846
|
+
maximum: 9007199254740991
|
|
1847
|
+
readOnly: true
|
|
1848
|
+
description: (Read-only) Bookings with date == today AND status in [PENDING,
|
|
1849
|
+
CONFIRMED]. Resets at midnight.
|
|
1850
|
+
bookingsCreatedToday:
|
|
1851
|
+
type: integer
|
|
1852
|
+
minimum: -9007199254740991
|
|
1853
|
+
maximum: 9007199254740991
|
|
1854
|
+
readOnly: true
|
|
1855
|
+
description: (Read-only) Bookings with createdAt today (all statuses). Resets
|
|
1856
|
+
at midnight.
|
|
1857
|
+
todayBookingsConfirmedAmount:
|
|
1858
|
+
type: number
|
|
1859
|
+
readOnly: true
|
|
1860
|
+
description: (Read-only) Sum of totalAmount for bookings created today with
|
|
1861
|
+
status CONFIRMED or COMPLETED. Resets at midnight.
|
|
1862
|
+
monthlyBookingsConfirmedAmount:
|
|
1863
|
+
type: number
|
|
1864
|
+
readOnly: true
|
|
1865
|
+
description: (Read-only) Sum of totalAmount for bookings created this month
|
|
1866
|
+
with status CONFIRMED or COMPLETED.
|
|
1867
|
+
todayCollectedAmount:
|
|
1868
|
+
type: number
|
|
1869
|
+
readOnly: true
|
|
1870
|
+
description: (Read-only) Sum of totalAmount for bookings where PAYMENT_PAID_AT
|
|
1871
|
+
is today. Resets at midnight.
|
|
1872
|
+
todayRevenue:
|
|
1873
|
+
type: number
|
|
1874
|
+
readOnly: true
|
|
1875
|
+
description: (Read-only) Sum of totalAmount for COMPLETED bookings where
|
|
1876
|
+
startDate == endDate == today (numeric YYYYMMDD). Resets at midnight.
|
|
1877
|
+
bookingsPendingPaymentVerification:
|
|
1878
|
+
type: integer
|
|
1879
|
+
minimum: -9007199254740991
|
|
1880
|
+
maximum: 9007199254740991
|
|
1881
|
+
readOnly: true
|
|
1882
|
+
description: (Read-only) Bookings with status PENDING/CANCELLATION_REQUESTED
|
|
1883
|
+
and a payment proof uploaded but not yet verified. Current state, always
|
|
1884
|
+
full recalc.
|
|
1885
|
+
bookingsPendingValidation:
|
|
1886
|
+
type: integer
|
|
1887
|
+
minimum: -9007199254740991
|
|
1888
|
+
maximum: 9007199254740991
|
|
1889
|
+
readOnly: true
|
|
1890
|
+
description: (Read-only) PENDING bookings with startDate within ±30 days
|
|
1891
|
+
of today. Rolling window, always full recalc.
|
|
1892
|
+
bookingsPendingValidation24h:
|
|
1893
|
+
type: integer
|
|
1894
|
+
minimum: -9007199254740991
|
|
1895
|
+
maximum: 9007199254740991
|
|
1896
|
+
readOnly: true
|
|
1897
|
+
description: (Read-only) PENDING bookings created in the last 24h with startDate
|
|
1898
|
+
>= tomorrow. Always full recalc.
|
|
1899
|
+
customersCount:
|
|
1900
|
+
type: integer
|
|
1901
|
+
minimum: -9007199254740991
|
|
1902
|
+
maximum: 9007199254740991
|
|
1903
|
+
readOnly: true
|
|
1904
|
+
description: (Read-only) Total customer count (all-time cumulative).
|
|
1905
|
+
newCustomersThisMonth:
|
|
1906
|
+
type: integer
|
|
1907
|
+
minimum: -9007199254740991
|
|
1908
|
+
maximum: 9007199254740991
|
|
1909
|
+
readOnly: true
|
|
1910
|
+
description: (Read-only) Customers with createdAt in the current calendar
|
|
1911
|
+
month (UTC).
|
|
1912
|
+
averageRating:
|
|
1913
|
+
type: number
|
|
1914
|
+
readOnly: true
|
|
1915
|
+
description: (Read-only) Average rating from the last 200 reviews (rolling).
|
|
1916
|
+
Always full recalc.
|
|
1917
|
+
lowStockItemsCount:
|
|
1918
|
+
type: integer
|
|
1919
|
+
minimum: -9007199254740991
|
|
1920
|
+
maximum: 9007199254740991
|
|
1921
|
+
readOnly: true
|
|
1922
|
+
description: (Read-only) Active stock items where currentQuantity <= minimumQuantity.
|
|
1923
|
+
Current state, always full recalc.
|
|
1924
|
+
activeRecurringPaymentsCount:
|
|
1925
|
+
type: integer
|
|
1926
|
+
minimum: -9007199254740991
|
|
1927
|
+
maximum: 9007199254740991
|
|
1928
|
+
readOnly: true
|
|
1929
|
+
description: (Read-only) Recurring payments with status ACTIVE. Current
|
|
1930
|
+
state, always full recalc.
|
|
1931
|
+
monthlyRecurringRevenue:
|
|
1932
|
+
type: number
|
|
1933
|
+
readOnly: true
|
|
1934
|
+
description: (Read-only) Sum of amount for ACTIVE + MONTHLY recurring payments.
|
|
1935
|
+
Always full recalc.
|
|
1936
|
+
computedForDay:
|
|
1937
|
+
type: string
|
|
1938
|
+
readOnly: true
|
|
1939
|
+
description: (Read-only) YYYY-MM-DD string indicating which day these metrics
|
|
1940
|
+
reflect. Used to detect day boundaries and trigger midnight resets.
|
|
1941
|
+
generatedAt:
|
|
1942
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
1943
|
+
description: (Read-only) Server timestamp of the last metrics write.
|
|
1944
|
+
readOnly: true
|
|
1945
|
+
date:
|
|
1946
|
+
type: string
|
|
1947
|
+
readOnly: true
|
|
1948
|
+
description: (Read-only) YYYY-MM-DD document ID repeated as a field. Identifies
|
|
1949
|
+
the day this snapshot covers.
|
|
1950
|
+
required:
|
|
1951
|
+
- todayOrdersCount
|
|
1952
|
+
- pendingOrdersCount
|
|
1953
|
+
- orderCompletionRate30d
|
|
1954
|
+
- todayPurchasesCount
|
|
1955
|
+
- todayPurchasesSum
|
|
1956
|
+
- averagePurchaseAmount
|
|
1957
|
+
- monthlyRevenue
|
|
1958
|
+
- monthlyPurchasesCount
|
|
1959
|
+
- todayBookingsCount
|
|
1960
|
+
- bookingsCreatedToday
|
|
1961
|
+
- todayBookingsConfirmedAmount
|
|
1962
|
+
- monthlyBookingsConfirmedAmount
|
|
1963
|
+
- todayCollectedAmount
|
|
1964
|
+
- todayRevenue
|
|
1965
|
+
- bookingsPendingPaymentVerification
|
|
1966
|
+
- bookingsPendingValidation
|
|
1967
|
+
- bookingsPendingValidation24h
|
|
1968
|
+
- customersCount
|
|
1969
|
+
- newCustomersThisMonth
|
|
1970
|
+
- averageRating
|
|
1971
|
+
- lowStockItemsCount
|
|
1972
|
+
- activeRecurringPaymentsCount
|
|
1973
|
+
- monthlyRecurringRevenue
|
|
1974
|
+
- computedForDay
|
|
1975
|
+
- generatedAt
|
|
1976
|
+
- date
|
|
1977
|
+
additionalProperties: false
|
|
1978
|
+
description: 'Daily metrics snapshot. Collection: companies/{companyId}/metrics_daily/{YYYY-MM-DD}.
|
|
1979
|
+
Same fields as MetricsCurrent plus `date`. Written by computeDailyCompanyMetrics
|
|
1980
|
+
cron (02:00 UTC) and inline after full recalcs.'
|
|
1981
|
+
MetricsDailyCreate:
|
|
1982
|
+
allOf:
|
|
1983
|
+
- $ref: '#/components/schemas/MetricsDaily'
|
|
1984
|
+
description: Write payload for creating a new MetricsDaily document. Fields
|
|
1985
|
+
marked `readOnly` are server-set and must not be included. Fields marked `x-immutable`
|
|
1986
|
+
may be set once at creation.
|
|
1987
|
+
MetricsDailyUpdate:
|
|
1988
|
+
allOf:
|
|
1989
|
+
- $ref: '#/components/schemas/MetricsDaily'
|
|
1990
|
+
description: Write payload for partial update (PATCH) of a MetricsDaily document.
|
|
1991
|
+
All fields optional. Fields marked `readOnly` or `x-immutable` must not be
|
|
1992
|
+
sent.
|
|
1993
|
+
MetricsMonthly:
|
|
1994
|
+
type: object
|
|
1995
|
+
properties:
|
|
1996
|
+
todayOrdersCount:
|
|
1997
|
+
type: integer
|
|
1998
|
+
minimum: -9007199254740991
|
|
1999
|
+
maximum: 9007199254740991
|
|
2000
|
+
readOnly: true
|
|
2001
|
+
description: (Read-only) Orders created today (UTC). Resets at midnight.
|
|
2002
|
+
pendingOrdersCount:
|
|
2003
|
+
type: integer
|
|
2004
|
+
minimum: -9007199254740991
|
|
2005
|
+
maximum: 9007199254740991
|
|
2006
|
+
readOnly: true
|
|
2007
|
+
description: (Read-only) Orders currently in PENDING status (all-time cumulative).
|
|
2008
|
+
Corrected by full recalc on order updates.
|
|
2009
|
+
orderCompletionRate30d:
|
|
2010
|
+
type: number
|
|
2011
|
+
readOnly: true
|
|
2012
|
+
description: (Read-only) Percentage of orders completed or delivered in
|
|
2013
|
+
the last 30 days. Always full recalc.
|
|
2014
|
+
todayPurchasesCount:
|
|
2015
|
+
type: integer
|
|
2016
|
+
minimum: -9007199254740991
|
|
2017
|
+
maximum: 9007199254740991
|
|
2018
|
+
readOnly: true
|
|
2019
|
+
description: (Read-only) Purchases created today (UTC). Resets at midnight.
|
|
2020
|
+
todayPurchasesSum:
|
|
2021
|
+
type: number
|
|
2022
|
+
readOnly: true
|
|
2023
|
+
description: (Read-only) Total value of purchases created today (UTC). Resets
|
|
2024
|
+
at midnight.
|
|
2025
|
+
averagePurchaseAmount:
|
|
2026
|
+
type: number
|
|
2027
|
+
readOnly: true
|
|
2028
|
+
description: (Read-only) Average purchase value across last 200 purchases
|
|
2029
|
+
(rolling, not time-windowed).
|
|
2030
|
+
monthlyRevenue:
|
|
2031
|
+
type: number
|
|
2032
|
+
readOnly: true
|
|
2033
|
+
description: (Read-only) Total purchase value in the current calendar month
|
|
2034
|
+
(UTC).
|
|
2035
|
+
monthlyPurchasesCount:
|
|
2036
|
+
type: integer
|
|
2037
|
+
minimum: -9007199254740991
|
|
2038
|
+
maximum: 9007199254740991
|
|
2039
|
+
readOnly: true
|
|
2040
|
+
description: (Read-only) Number of purchases in the current calendar month
|
|
2041
|
+
(UTC).
|
|
2042
|
+
todayBookingsCount:
|
|
2043
|
+
type: integer
|
|
2044
|
+
minimum: -9007199254740991
|
|
2045
|
+
maximum: 9007199254740991
|
|
2046
|
+
readOnly: true
|
|
2047
|
+
description: (Read-only) Bookings with date == today AND status in [PENDING,
|
|
2048
|
+
CONFIRMED]. Resets at midnight.
|
|
2049
|
+
bookingsCreatedToday:
|
|
2050
|
+
type: integer
|
|
2051
|
+
minimum: -9007199254740991
|
|
2052
|
+
maximum: 9007199254740991
|
|
2053
|
+
readOnly: true
|
|
2054
|
+
description: (Read-only) Bookings with createdAt today (all statuses). Resets
|
|
2055
|
+
at midnight.
|
|
2056
|
+
todayBookingsConfirmedAmount:
|
|
2057
|
+
type: number
|
|
2058
|
+
readOnly: true
|
|
2059
|
+
description: (Read-only) Sum of totalAmount for bookings created today with
|
|
2060
|
+
status CONFIRMED or COMPLETED. Resets at midnight.
|
|
2061
|
+
monthlyBookingsConfirmedAmount:
|
|
2062
|
+
type: number
|
|
2063
|
+
readOnly: true
|
|
2064
|
+
description: (Read-only) Sum of totalAmount for bookings created this month
|
|
2065
|
+
with status CONFIRMED or COMPLETED.
|
|
2066
|
+
todayCollectedAmount:
|
|
2067
|
+
type: number
|
|
2068
|
+
readOnly: true
|
|
2069
|
+
description: (Read-only) Sum of totalAmount for bookings where PAYMENT_PAID_AT
|
|
2070
|
+
is today. Resets at midnight.
|
|
2071
|
+
todayRevenue:
|
|
2072
|
+
type: number
|
|
2073
|
+
readOnly: true
|
|
2074
|
+
description: (Read-only) Sum of totalAmount for COMPLETED bookings where
|
|
2075
|
+
startDate == endDate == today (numeric YYYYMMDD). Resets at midnight.
|
|
2076
|
+
bookingsPendingPaymentVerification:
|
|
2077
|
+
type: integer
|
|
2078
|
+
minimum: -9007199254740991
|
|
2079
|
+
maximum: 9007199254740991
|
|
2080
|
+
readOnly: true
|
|
2081
|
+
description: (Read-only) Bookings with status PENDING/CANCELLATION_REQUESTED
|
|
2082
|
+
and a payment proof uploaded but not yet verified. Current state, always
|
|
2083
|
+
full recalc.
|
|
2084
|
+
bookingsPendingValidation:
|
|
2085
|
+
type: integer
|
|
2086
|
+
minimum: -9007199254740991
|
|
2087
|
+
maximum: 9007199254740991
|
|
2088
|
+
readOnly: true
|
|
2089
|
+
description: (Read-only) PENDING bookings with startDate within ±30 days
|
|
2090
|
+
of today. Rolling window, always full recalc.
|
|
2091
|
+
bookingsPendingValidation24h:
|
|
2092
|
+
type: integer
|
|
2093
|
+
minimum: -9007199254740991
|
|
2094
|
+
maximum: 9007199254740991
|
|
2095
|
+
readOnly: true
|
|
2096
|
+
description: (Read-only) PENDING bookings created in the last 24h with startDate
|
|
2097
|
+
>= tomorrow. Always full recalc.
|
|
2098
|
+
customersCount:
|
|
2099
|
+
type: integer
|
|
2100
|
+
minimum: -9007199254740991
|
|
2101
|
+
maximum: 9007199254740991
|
|
2102
|
+
readOnly: true
|
|
2103
|
+
description: (Read-only) Total customer count (all-time cumulative).
|
|
2104
|
+
newCustomersThisMonth:
|
|
2105
|
+
type: integer
|
|
2106
|
+
minimum: -9007199254740991
|
|
2107
|
+
maximum: 9007199254740991
|
|
2108
|
+
readOnly: true
|
|
2109
|
+
description: (Read-only) Customers with createdAt in the current calendar
|
|
2110
|
+
month (UTC).
|
|
2111
|
+
averageRating:
|
|
2112
|
+
type: number
|
|
2113
|
+
readOnly: true
|
|
2114
|
+
description: (Read-only) Average rating from the last 200 reviews (rolling).
|
|
2115
|
+
Always full recalc.
|
|
2116
|
+
lowStockItemsCount:
|
|
2117
|
+
type: integer
|
|
2118
|
+
minimum: -9007199254740991
|
|
2119
|
+
maximum: 9007199254740991
|
|
2120
|
+
readOnly: true
|
|
2121
|
+
description: (Read-only) Active stock items where currentQuantity <= minimumQuantity.
|
|
2122
|
+
Current state, always full recalc.
|
|
2123
|
+
activeRecurringPaymentsCount:
|
|
2124
|
+
type: integer
|
|
2125
|
+
minimum: -9007199254740991
|
|
2126
|
+
maximum: 9007199254740991
|
|
2127
|
+
readOnly: true
|
|
2128
|
+
description: (Read-only) Recurring payments with status ACTIVE. Current
|
|
2129
|
+
state, always full recalc.
|
|
2130
|
+
monthlyRecurringRevenue:
|
|
2131
|
+
type: number
|
|
2132
|
+
readOnly: true
|
|
2133
|
+
description: (Read-only) Sum of amount for ACTIVE + MONTHLY recurring payments.
|
|
2134
|
+
Always full recalc.
|
|
2135
|
+
computedForDay:
|
|
2136
|
+
type: string
|
|
2137
|
+
readOnly: true
|
|
2138
|
+
description: (Read-only) YYYY-MM-DD string indicating which day these metrics
|
|
2139
|
+
reflect. Used to detect day boundaries and trigger midnight resets.
|
|
2140
|
+
generatedAt:
|
|
2141
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
2142
|
+
description: (Read-only) Server timestamp of the last metrics write.
|
|
2143
|
+
readOnly: true
|
|
2144
|
+
month:
|
|
2145
|
+
type: string
|
|
2146
|
+
readOnly: true
|
|
2147
|
+
description: (Read-only) YYYY-MM document ID repeated as a field. Identifies
|
|
2148
|
+
the month this rollup covers.
|
|
2149
|
+
required:
|
|
2150
|
+
- todayOrdersCount
|
|
2151
|
+
- pendingOrdersCount
|
|
2152
|
+
- orderCompletionRate30d
|
|
2153
|
+
- todayPurchasesCount
|
|
2154
|
+
- todayPurchasesSum
|
|
2155
|
+
- averagePurchaseAmount
|
|
2156
|
+
- monthlyRevenue
|
|
2157
|
+
- monthlyPurchasesCount
|
|
2158
|
+
- todayBookingsCount
|
|
2159
|
+
- bookingsCreatedToday
|
|
2160
|
+
- todayBookingsConfirmedAmount
|
|
2161
|
+
- monthlyBookingsConfirmedAmount
|
|
2162
|
+
- todayCollectedAmount
|
|
2163
|
+
- todayRevenue
|
|
2164
|
+
- bookingsPendingPaymentVerification
|
|
2165
|
+
- bookingsPendingValidation
|
|
2166
|
+
- bookingsPendingValidation24h
|
|
2167
|
+
- customersCount
|
|
2168
|
+
- newCustomersThisMonth
|
|
2169
|
+
- averageRating
|
|
2170
|
+
- lowStockItemsCount
|
|
2171
|
+
- activeRecurringPaymentsCount
|
|
2172
|
+
- monthlyRecurringRevenue
|
|
2173
|
+
- computedForDay
|
|
2174
|
+
- generatedAt
|
|
2175
|
+
- month
|
|
2176
|
+
additionalProperties: false
|
|
2177
|
+
description: 'Monthly metrics rollup. Collection: companies/{companyId}/metrics_monthly/{YYYY-MM}.
|
|
2178
|
+
Same fields as MetricsCurrent plus `month`. Written alongside daily snapshots;
|
|
2179
|
+
reflects state at last full recalc within the month.'
|
|
2180
|
+
MetricsMonthlyCreate:
|
|
2181
|
+
allOf:
|
|
2182
|
+
- $ref: '#/components/schemas/MetricsMonthly'
|
|
2183
|
+
description: Write payload for creating a new MetricsMonthly document. Fields
|
|
2184
|
+
marked `readOnly` are server-set and must not be included. Fields marked `x-immutable`
|
|
2185
|
+
may be set once at creation.
|
|
2186
|
+
MetricsMonthlyUpdate:
|
|
2187
|
+
allOf:
|
|
2188
|
+
- $ref: '#/components/schemas/MetricsMonthly'
|
|
2189
|
+
description: Write payload for partial update (PATCH) of a MetricsMonthly document.
|
|
2190
|
+
All fields optional. Fields marked `readOnly` or `x-immutable` must not be
|
|
2191
|
+
sent.
|
|
2192
|
+
Order:
|
|
2193
|
+
type: object
|
|
2194
|
+
properties:
|
|
2195
|
+
id:
|
|
2196
|
+
type: string
|
|
2197
|
+
readOnly: true
|
|
2198
|
+
description: '(Read-only) Firestore document ID. Note: some models also
|
|
2199
|
+
have uid; see ID conventions.'
|
|
2200
|
+
uid:
|
|
2201
|
+
type: string
|
|
2202
|
+
readOnly: true
|
|
2203
|
+
description: (Read-only) Entity UID. Often mirrors id.
|
|
2204
|
+
companyId:
|
|
2205
|
+
type: string
|
|
2206
|
+
x-immutable: true
|
|
2207
|
+
description: (Immutable) FK → Company document ID. Scopes all queries.
|
|
2208
|
+
orderNumber:
|
|
2209
|
+
type: string
|
|
2210
|
+
readOnly: true
|
|
2211
|
+
description: (Read-only) Server-generated order number.
|
|
2212
|
+
status:
|
|
2213
|
+
$ref: '#/components/schemas/OrderStatus'
|
|
2214
|
+
description: Core lifecycle status (D34, MIG-11). See OrderStatus enum for
|
|
2215
|
+
the legacy value migration mapping.
|
|
2216
|
+
x-migration:
|
|
2217
|
+
source: Dashboard flat 20-value OrderStatus
|
|
2218
|
+
migration: MIG-11
|
|
2219
|
+
note: REFUND_PROCESSING and REFUNDED map to paymentStatus, not returnStatus
|
|
2220
|
+
— an order can be refunded without a physical return.
|
|
2221
|
+
mapping:
|
|
2222
|
+
- old: PENDING
|
|
2223
|
+
status: PENDING
|
|
2224
|
+
- old: CONFIRMED
|
|
2225
|
+
status: CONFIRMED
|
|
2226
|
+
- old: PROCESSING
|
|
2227
|
+
status: PROCESSING
|
|
2228
|
+
- old: READY
|
|
2229
|
+
status: READY
|
|
2230
|
+
- old: COMPLETED
|
|
2231
|
+
status: COMPLETED
|
|
2232
|
+
- old: CANCELLED
|
|
2233
|
+
status: CANCELLED
|
|
2234
|
+
- old: EXPIRED
|
|
2235
|
+
status: EXPIRED
|
|
2236
|
+
- old: AWAITING_PAYMENT
|
|
2237
|
+
status: PENDING
|
|
2238
|
+
paymentStatus: PENDING
|
|
2239
|
+
- old: SHIPPED
|
|
2240
|
+
status: PROCESSING
|
|
2241
|
+
fulfillmentStatus: SHIPPED
|
|
2242
|
+
- old: PARTIALLY_SHIPPED
|
|
2243
|
+
status: PROCESSING
|
|
2244
|
+
fulfillmentStatus: PARTIALLY_SHIPPED
|
|
2245
|
+
- old: ON_THE_WAY
|
|
2246
|
+
status: PROCESSING
|
|
2247
|
+
fulfillmentStatus: IN_TRANSIT
|
|
2248
|
+
- old: DELIVERED
|
|
2249
|
+
status: COMPLETED
|
|
2250
|
+
fulfillmentStatus: DELIVERED
|
|
2251
|
+
- old: PICKED_UP
|
|
2252
|
+
status: COMPLETED
|
|
2253
|
+
fulfillmentStatus: PICKED_UP
|
|
2254
|
+
- old: RETURN_REQUESTED
|
|
2255
|
+
status: COMPLETED
|
|
2256
|
+
returnStatus: RETURN_REQUESTED
|
|
2257
|
+
- old: RETURN_PROCESSING
|
|
2258
|
+
status: COMPLETED
|
|
2259
|
+
returnStatus: RETURN_PROCESSING
|
|
2260
|
+
- old: RETURNED
|
|
2261
|
+
status: COMPLETED
|
|
2262
|
+
returnStatus: RETURNED
|
|
2263
|
+
- old: EXCHANGE_REQUESTED
|
|
2264
|
+
status: COMPLETED
|
|
2265
|
+
returnStatus: EXCHANGE_REQUESTED
|
|
2266
|
+
- old: EXCHANGE_PROCESSING
|
|
2267
|
+
status: COMPLETED
|
|
2268
|
+
returnStatus: EXCHANGE_PROCESSING
|
|
2269
|
+
- old: EXCHANGE_COMPLETED
|
|
2270
|
+
status: COMPLETED
|
|
2271
|
+
returnStatus: EXCHANGE_COMPLETED
|
|
2272
|
+
- old: REFUND_PROCESSING
|
|
2273
|
+
status: COMPLETED
|
|
2274
|
+
paymentStatus: REFUND_PROCESSING
|
|
2275
|
+
- old: REFUNDED
|
|
2276
|
+
status: COMPLETED
|
|
2277
|
+
paymentStatus: REFUNDED
|
|
2278
|
+
paymentStatus:
|
|
2279
|
+
anyOf:
|
|
2280
|
+
- $ref: '#/components/schemas/PaymentStatus'
|
|
2281
|
+
- type: 'null'
|
|
2282
|
+
description: Payment lifecycle (D34). Null until payment is initiated.
|
|
2283
|
+
fulfillmentStatus:
|
|
2284
|
+
anyOf:
|
|
2285
|
+
- $ref: '#/components/schemas/FulfillmentStatus'
|
|
2286
|
+
- type: 'null'
|
|
2287
|
+
x-when: Null for ON_SITE and PICK_UP orders. Set when deliveryType is DELIVERY
|
|
2288
|
+
and a physical shipment or pickup is involved.
|
|
2289
|
+
x-see:
|
|
2290
|
+
decisions:
|
|
2291
|
+
- D34
|
|
2292
|
+
description: Delivery/fulfillment lifecycle (D34).
|
|
2293
|
+
returnStatus:
|
|
2294
|
+
anyOf:
|
|
2295
|
+
- $ref: '#/components/schemas/ReturnStatus'
|
|
2296
|
+
- type: 'null'
|
|
2297
|
+
description: Return/exchange lifecycle (D34). Null until a return or exchange
|
|
2298
|
+
is initiated.
|
|
2299
|
+
deliveryType:
|
|
2300
|
+
anyOf:
|
|
2301
|
+
- $ref: '#/components/schemas/DeliveryType'
|
|
2302
|
+
- type: 'null'
|
|
2303
|
+
x-note: Drives whether fulfillmentStatus is relevant. ON_SITE and PICK_UP
|
|
2304
|
+
orders typically have no fulfillmentStatus.
|
|
2305
|
+
description: Fulfillment channel for this order (ON_SITE, PICK_UP, DELIVERY).
|
|
2306
|
+
paymentMethod:
|
|
2307
|
+
anyOf:
|
|
2308
|
+
- $ref: '#/components/schemas/PaymentMethod'
|
|
2309
|
+
- type: 'null'
|
|
2310
|
+
description: Unified payment method set with African + global methods (D02).
|
|
2311
|
+
invoiceId:
|
|
2312
|
+
description: FK → Invoice document ID.
|
|
2313
|
+
type:
|
|
2314
|
+
- string
|
|
2315
|
+
- 'null'
|
|
2316
|
+
customerId:
|
|
2317
|
+
description: FK → Customer.id (Firestore doc ID). Used to resolve customer
|
|
2318
|
+
details.
|
|
2319
|
+
type:
|
|
2320
|
+
- string
|
|
2321
|
+
- 'null'
|
|
2322
|
+
customerName:
|
|
2323
|
+
denormalized: true
|
|
2324
|
+
description: (Denormalized) From Customer.name at write time.
|
|
2325
|
+
type:
|
|
2326
|
+
- string
|
|
2327
|
+
- 'null'
|
|
2328
|
+
customerEmail:
|
|
2329
|
+
denormalized: true
|
|
2330
|
+
description: (Denormalized) From Customer.email at write time. Canonical
|
|
2331
|
+
field per D24.
|
|
2332
|
+
type:
|
|
2333
|
+
- string
|
|
2334
|
+
- 'null'
|
|
2335
|
+
customerPhone:
|
|
2336
|
+
denormalized: true
|
|
2337
|
+
description: (Denormalized) From Customer.phone at write time. Canonical
|
|
2338
|
+
field per D24.
|
|
2339
|
+
type:
|
|
2340
|
+
- string
|
|
2341
|
+
- 'null'
|
|
2342
|
+
clientEmail:
|
|
2343
|
+
denormalized: true
|
|
2344
|
+
deprecated: true
|
|
2345
|
+
x-replaced-by: customerEmail
|
|
2346
|
+
description: (Denormalized) Legacy — use `customerEmail`. D24 standardized
|
|
2347
|
+
to customer* prefix.
|
|
2348
|
+
type:
|
|
2349
|
+
- string
|
|
2350
|
+
- 'null'
|
|
2351
|
+
clientPhoneNumber:
|
|
2352
|
+
denormalized: true
|
|
2353
|
+
deprecated: true
|
|
2354
|
+
x-replaced-by: customerPhone
|
|
2355
|
+
description: (Denormalized) Legacy — use `customerPhone`. D24 standardized
|
|
2356
|
+
to customer* prefix.
|
|
2357
|
+
type:
|
|
2358
|
+
- string
|
|
2359
|
+
- 'null'
|
|
2360
|
+
items:
|
|
2361
|
+
type:
|
|
2362
|
+
- array
|
|
2363
|
+
- 'null'
|
|
2364
|
+
items:
|
|
2365
|
+
$ref: '#/components/schemas/OrderItem'
|
|
2366
|
+
description: 'Line item within an Order or Sale/Purchase. Canonical fields:
|
|
2367
|
+
name, quantity, price, productId. Optional commerce fields (increment,
|
|
2368
|
+
variantId, supplierId, supplierName) and kitchen tracking fields (sentAt,
|
|
2369
|
+
startedCookingAt, readyAt, servedAt) are TBD/WIP pending cross-platform
|
|
2370
|
+
alignment.'
|
|
2371
|
+
amount:
|
|
2372
|
+
type: number
|
|
2373
|
+
description: Total order amount. Canonical field for the order total.
|
|
2374
|
+
amountPaid:
|
|
2375
|
+
description: Amount of `amount` paid to date. Derived from payment allocations.
|
|
2376
|
+
type:
|
|
2377
|
+
- number
|
|
2378
|
+
- 'null'
|
|
2379
|
+
total:
|
|
2380
|
+
deprecated: true
|
|
2381
|
+
x-replaced-by: amount
|
|
2382
|
+
x-note: Sent by Mobile only. Mirrors `amount`. Use `amount` for all new
|
|
2383
|
+
writes. Pending deduplication cleanup.
|
|
2384
|
+
description: Mobile-only legacy total field. Deprecated — use `amount`.
|
|
2385
|
+
type:
|
|
2386
|
+
- number
|
|
2387
|
+
- 'null'
|
|
2388
|
+
createdAt:
|
|
2389
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
2390
|
+
description: (Read-only) Server-generated creation timestamp.
|
|
2391
|
+
readOnly: true
|
|
2392
|
+
orderDate:
|
|
2393
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
2394
|
+
description: Firestore Timestamp serialized representation
|
|
2395
|
+
PROCESSING_ON:
|
|
2396
|
+
anyOf:
|
|
2397
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
2398
|
+
- type: 'null'
|
|
2399
|
+
readOnly: true
|
|
2400
|
+
x-note: Never write this field directly. The server sets it automatically
|
|
2401
|
+
on status transition to PROCESSING.
|
|
2402
|
+
x-see:
|
|
2403
|
+
decisions:
|
|
2404
|
+
- D04
|
|
2405
|
+
migrations:
|
|
2406
|
+
- MIG-01
|
|
2407
|
+
description: (Read-only) Timestamp when order entered PROCESSING (D04 SCREAMING_SNAKE).
|
|
2408
|
+
MIG-01 renames from camelCase.
|
|
2409
|
+
COMPLETED_ON:
|
|
2410
|
+
anyOf:
|
|
2411
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
2412
|
+
- type: 'null'
|
|
2413
|
+
readOnly: true
|
|
2414
|
+
description: (Read-only) Timestamp when order completed (D04 SCREAMING_SNAKE).
|
|
2415
|
+
MIG-01 renames from camelCase.
|
|
2416
|
+
CANCELLED_ON:
|
|
2417
|
+
anyOf:
|
|
2418
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
2419
|
+
- type: 'null'
|
|
2420
|
+
readOnly: true
|
|
2421
|
+
description: (Read-only) Timestamp when order cancelled (D04 SCREAMING_SNAKE).
|
|
2422
|
+
MIG-01 renames from camelCase.
|
|
2423
|
+
cancellationReason:
|
|
2424
|
+
type:
|
|
2425
|
+
- string
|
|
2426
|
+
- 'null'
|
|
2427
|
+
shippingCarrier:
|
|
2428
|
+
type:
|
|
2429
|
+
- string
|
|
2430
|
+
- 'null'
|
|
2431
|
+
trackingNumber:
|
|
2432
|
+
type:
|
|
2433
|
+
- string
|
|
2434
|
+
- 'null'
|
|
2435
|
+
estimatedDeliveryDate:
|
|
2436
|
+
anyOf:
|
|
2437
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
2438
|
+
- type: 'null'
|
|
2439
|
+
description: Firestore Timestamp serialized representation
|
|
2440
|
+
shippingCost:
|
|
2441
|
+
type:
|
|
2442
|
+
- number
|
|
2443
|
+
- 'null'
|
|
2444
|
+
paymentProofUrl:
|
|
2445
|
+
description: URL to uploaded payment proof image/document.
|
|
2446
|
+
type:
|
|
2447
|
+
- string
|
|
2448
|
+
- 'null'
|
|
2449
|
+
paymentProofStatus:
|
|
2450
|
+
anyOf:
|
|
2451
|
+
- $ref: '#/components/schemas/PaymentProofStatus'
|
|
2452
|
+
- type: 'null'
|
|
2453
|
+
description: Payment proof review status.
|
|
2454
|
+
paymentProofAddedAt:
|
|
2455
|
+
anyOf:
|
|
2456
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
2457
|
+
- type: 'null'
|
|
2458
|
+
readOnly: true
|
|
2459
|
+
description: (Read-only) Timestamp when proof was uploaded.
|
|
2460
|
+
paymentProofAddedBy:
|
|
2461
|
+
description: FK → User/staff UID who uploaded the payment proof.
|
|
2462
|
+
type:
|
|
2463
|
+
- string
|
|
2464
|
+
- 'null'
|
|
2465
|
+
paymentProofReviewedAt:
|
|
2466
|
+
anyOf:
|
|
2467
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
2468
|
+
- type: 'null'
|
|
2469
|
+
readOnly: true
|
|
2470
|
+
description: (Read-only) Timestamp when proof was reviewed.
|
|
2471
|
+
paymentProofReviewedBy:
|
|
2472
|
+
description: FK → User/staff UID who reviewed the payment proof.
|
|
2473
|
+
type:
|
|
2474
|
+
- string
|
|
2475
|
+
- 'null'
|
|
2476
|
+
paymentProofRejectionReason:
|
|
2477
|
+
type:
|
|
2478
|
+
- string
|
|
2479
|
+
- 'null'
|
|
2480
|
+
paymentStatusChangeReason:
|
|
2481
|
+
type:
|
|
2482
|
+
- string
|
|
2483
|
+
- 'null'
|
|
2484
|
+
paymentStatusChangedBy:
|
|
2485
|
+
description: FK → User/staff UID who changed payment status.
|
|
2486
|
+
type:
|
|
2487
|
+
- string
|
|
2488
|
+
- 'null'
|
|
2489
|
+
paymentStatusChangedAt:
|
|
2490
|
+
anyOf:
|
|
2491
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
2492
|
+
- type: 'null'
|
|
2493
|
+
readOnly: true
|
|
2494
|
+
description: (Read-only) Timestamp of last payment status change.
|
|
2495
|
+
payments:
|
|
2496
|
+
x-note: Shape and sync rules are TBD pending IG-4 resolution. Do not build
|
|
2497
|
+
production logic against this field until IG-4 is closed.
|
|
2498
|
+
x-see:
|
|
2499
|
+
issues:
|
|
2500
|
+
- IG-4
|
|
2501
|
+
description: '[TBD/WIP — IG-4] Denormalized snapshots of CustomerPayments
|
|
2502
|
+
allocated to this order. Sync rules pending IG-4 resolution.'
|
|
2503
|
+
type:
|
|
2504
|
+
- array
|
|
2505
|
+
- 'null'
|
|
2506
|
+
items:
|
|
2507
|
+
type: object
|
|
2508
|
+
properties:
|
|
2509
|
+
paymentId:
|
|
2510
|
+
type: string
|
|
2511
|
+
x-immutable: true
|
|
2512
|
+
description: (Immutable) FK → CustomerPayment.id. Source document
|
|
2513
|
+
for this snapshot.
|
|
2514
|
+
amount:
|
|
2515
|
+
type: number
|
|
2516
|
+
description: Total payment amount.
|
|
2517
|
+
currency:
|
|
2518
|
+
type: string
|
|
2519
|
+
const: XOF
|
|
2520
|
+
description: Currency code. Locked to XOF.
|
|
2521
|
+
paymentMethod:
|
|
2522
|
+
$ref: '#/components/schemas/PaymentMethod'
|
|
2523
|
+
description: Payment method used (D02).
|
|
2524
|
+
paymentDate:
|
|
2525
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
2526
|
+
description: Firestore Timestamp serialized representation
|
|
2527
|
+
referenceNumber:
|
|
2528
|
+
description: Payment reference (receipt number, transaction ID, etc.).
|
|
2529
|
+
type: string
|
|
2530
|
+
status:
|
|
2531
|
+
$ref: '#/components/schemas/CustomerPaymentStatus'
|
|
2532
|
+
description: Payment status at time of snapshot. May lag CustomerPayment.status
|
|
2533
|
+
until re-synced.
|
|
2534
|
+
required:
|
|
2535
|
+
- paymentId
|
|
2536
|
+
- amount
|
|
2537
|
+
- currency
|
|
2538
|
+
- paymentMethod
|
|
2539
|
+
- paymentDate
|
|
2540
|
+
- status
|
|
2541
|
+
additionalProperties: false
|
|
2542
|
+
description: '[TBD/WIP — IG-4] Denormalized payment snapshot. Subset of
|
|
2543
|
+
CustomerPayment (D22), written when a payment is allocated to this order.
|
|
2544
|
+
Sync rules pending IG-4 resolution.'
|
|
2545
|
+
totalOverridden:
|
|
2546
|
+
x-when: Set only by the mobile app when the user manually edits the order
|
|
2547
|
+
total. Dashboard and Cloud Functions should treat this field as read-only.
|
|
2548
|
+
x-see:
|
|
2549
|
+
decisions:
|
|
2550
|
+
- D14
|
|
2551
|
+
description: Mobile-only. When true, total was manually overridden by user
|
|
2552
|
+
(D14).
|
|
2553
|
+
type:
|
|
2554
|
+
- boolean
|
|
2555
|
+
- 'null'
|
|
2556
|
+
notes:
|
|
2557
|
+
type:
|
|
2558
|
+
- array
|
|
2559
|
+
- 'null'
|
|
2560
|
+
items:
|
|
2561
|
+
type: object
|
|
2562
|
+
properties:
|
|
2563
|
+
id:
|
|
2564
|
+
type: string
|
|
2565
|
+
readOnly: true
|
|
2566
|
+
description: (Read-only) Note ID. Server-generated.
|
|
2567
|
+
text:
|
|
2568
|
+
type: string
|
|
2569
|
+
createdAt:
|
|
2570
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
2571
|
+
description: (Read-only) Firestore Timestamp serialized representation.
|
|
2572
|
+
readOnly: true
|
|
2573
|
+
createdBy:
|
|
2574
|
+
x-immutable: true
|
|
2575
|
+
description: (Immutable) FK → User/staff UID who created this note.
|
|
2576
|
+
type: string
|
|
2577
|
+
createdByName:
|
|
2578
|
+
denormalized: true
|
|
2579
|
+
description: (Denormalized) From User display name at write time.
|
|
2580
|
+
type: string
|
|
2581
|
+
required:
|
|
2582
|
+
- id
|
|
2583
|
+
- text
|
|
2584
|
+
- createdAt
|
|
2585
|
+
additionalProperties: false
|
|
2586
|
+
description: Timestamped note attached to an Order.
|
|
2587
|
+
additionalInfo:
|
|
2588
|
+
type:
|
|
2589
|
+
- string
|
|
2590
|
+
- 'null'
|
|
2591
|
+
appliedDiscountCode:
|
|
2592
|
+
type:
|
|
2593
|
+
- string
|
|
2594
|
+
- 'null'
|
|
2595
|
+
purchaseId:
|
|
2596
|
+
description: FK → Sale.id. Link to associated Sale document.
|
|
2597
|
+
type:
|
|
2598
|
+
- string
|
|
2599
|
+
- 'null'
|
|
2600
|
+
required:
|
|
2601
|
+
- id
|
|
2602
|
+
- uid
|
|
2603
|
+
- companyId
|
|
2604
|
+
- orderNumber
|
|
2605
|
+
- status
|
|
2606
|
+
- amount
|
|
2607
|
+
- createdAt
|
|
2608
|
+
- orderDate
|
|
2609
|
+
additionalProperties: false
|
|
2610
|
+
description: 'Order model (D34). Collection: companies/{companyId}/orders/{orderId}.
|
|
2611
|
+
Status decomposed into 4 orthogonal fields per D34: status (OrderStatus),
|
|
2612
|
+
paymentStatus, fulfillmentStatus, returnStatus. deliveryType determines the
|
|
2613
|
+
fulfillment channel. MIG-11 migrates the old flat 20-value enum.'
|
|
2614
|
+
OrderCreate:
|
|
2615
|
+
allOf:
|
|
2616
|
+
- $ref: '#/components/schemas/Order'
|
|
2617
|
+
description: Write payload for creating a new Order document. Fields marked
|
|
2618
|
+
`readOnly` are server-set and must not be included. Fields marked `x-immutable`
|
|
2619
|
+
may be set once at creation.
|
|
2620
|
+
required:
|
|
2621
|
+
- companyId
|
|
2622
|
+
- status
|
|
2623
|
+
- amount
|
|
2624
|
+
- orderDate
|
|
2625
|
+
OrderUpdate:
|
|
2626
|
+
allOf:
|
|
2627
|
+
- $ref: '#/components/schemas/Order'
|
|
2628
|
+
description: Write payload for partial update (PATCH) of a Order document. All
|
|
2629
|
+
fields optional. Fields marked `readOnly` or `x-immutable` must not be sent.
|
|
2630
|
+
OrderItem:
|
|
2631
|
+
type: object
|
|
2632
|
+
properties:
|
|
2633
|
+
name:
|
|
2634
|
+
type: string
|
|
2635
|
+
description: Display name of the product or service.
|
|
2636
|
+
quantity:
|
|
2637
|
+
type: number
|
|
2638
|
+
description: Number of units ordered.
|
|
2639
|
+
price:
|
|
2640
|
+
type: number
|
|
2641
|
+
description: Unit price. Canonical name per D11.
|
|
2642
|
+
productId:
|
|
2643
|
+
description: FK → Product document ID.
|
|
2644
|
+
type:
|
|
2645
|
+
- string
|
|
2646
|
+
- 'null'
|
|
2647
|
+
increment:
|
|
2648
|
+
x-note: TBD/WIP — Dashboard/Firebase only. Canonical status pending cross-platform
|
|
2649
|
+
alignment.
|
|
2650
|
+
description: Quantity step for bundle/bulk items (e.g. 5 for a 5-pack).
|
|
2651
|
+
Dashboard/Firebase only.
|
|
2652
|
+
type:
|
|
2653
|
+
- number
|
|
2654
|
+
- 'null'
|
|
2655
|
+
variantId:
|
|
2656
|
+
x-note: TBD/WIP — Dashboard/Firebase only. Canonical status pending cross-platform
|
|
2657
|
+
alignment.
|
|
2658
|
+
description: FK → ProductVariant ID within the product. Dashboard/Firebase
|
|
2659
|
+
only.
|
|
2660
|
+
type:
|
|
2661
|
+
- string
|
|
2662
|
+
- 'null'
|
|
2663
|
+
supplierId:
|
|
2664
|
+
x-note: TBD/WIP — B2B orders only. Canonical status pending cross-platform
|
|
2665
|
+
alignment.
|
|
2666
|
+
description: FK → Supplier document ID. B2B orders only.
|
|
2667
|
+
type:
|
|
2668
|
+
- string
|
|
2669
|
+
- 'null'
|
|
2670
|
+
supplierName:
|
|
2671
|
+
denormalized: true
|
|
2672
|
+
x-note: TBD/WIP — B2B orders only. Canonical status pending cross-platform
|
|
2673
|
+
alignment.
|
|
2674
|
+
description: (Denormalized) From Supplier.name at write time. B2B orders
|
|
2675
|
+
only.
|
|
2676
|
+
type:
|
|
2677
|
+
- string
|
|
2678
|
+
- 'null'
|
|
2679
|
+
sentAt:
|
|
2680
|
+
anyOf:
|
|
2681
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
2682
|
+
- type: 'null'
|
|
2683
|
+
readOnly: true
|
|
2684
|
+
x-note: TBD/WIP — Originally from the archived Couchbase Lite (CBL) restaurant
|
|
2685
|
+
flow. Canonical inclusion in Firestore model is pending review.
|
|
2686
|
+
description: (Read-only) Timestamp when the item was sent to the kitchen.
|
|
2687
|
+
TBD/WIP — archived CBL flow.
|
|
2688
|
+
startedCookingAt:
|
|
2689
|
+
anyOf:
|
|
2690
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
2691
|
+
- type: 'null'
|
|
2692
|
+
readOnly: true
|
|
2693
|
+
x-note: TBD/WIP — Originally from the archived Couchbase Lite (CBL) restaurant
|
|
2694
|
+
flow. Canonical inclusion in Firestore model is pending review.
|
|
2695
|
+
description: (Read-only) Timestamp when the kitchen started preparing this
|
|
2696
|
+
item. TBD/WIP — archived CBL flow.
|
|
2697
|
+
readyAt:
|
|
2698
|
+
anyOf:
|
|
2699
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
2700
|
+
- type: 'null'
|
|
2701
|
+
readOnly: true
|
|
2702
|
+
x-note: TBD/WIP — Originally from the archived Couchbase Lite (CBL) restaurant
|
|
2703
|
+
flow. Canonical inclusion in Firestore model is pending review.
|
|
2704
|
+
description: (Read-only) Timestamp when the item was ready for pickup or
|
|
2705
|
+
service. TBD/WIP — archived CBL flow.
|
|
2706
|
+
servedAt:
|
|
2707
|
+
anyOf:
|
|
2708
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
2709
|
+
- type: 'null'
|
|
2710
|
+
readOnly: true
|
|
2711
|
+
x-note: TBD/WIP — Originally from the archived Couchbase Lite (CBL) restaurant
|
|
2712
|
+
flow. Canonical inclusion in Firestore model is pending review.
|
|
2713
|
+
description: (Read-only) Timestamp when the item was served to the customer.
|
|
2714
|
+
TBD/WIP — archived CBL flow.
|
|
2715
|
+
required:
|
|
2716
|
+
- name
|
|
2717
|
+
- quantity
|
|
2718
|
+
- price
|
|
2719
|
+
additionalProperties: false
|
|
2720
|
+
description: 'Line item within an Order or Sale/Purchase. Canonical fields:
|
|
2721
|
+
name, quantity, price, productId. Optional commerce fields (increment, variantId,
|
|
2722
|
+
supplierId, supplierName) and kitchen tracking fields (sentAt, startedCookingAt,
|
|
2723
|
+
readyAt, servedAt) are TBD/WIP pending cross-platform alignment.'
|
|
2724
|
+
OrderItemCreate:
|
|
2725
|
+
allOf:
|
|
2726
|
+
- $ref: '#/components/schemas/OrderItem'
|
|
2727
|
+
description: Write payload for creating a new OrderItem document. Fields marked
|
|
2728
|
+
`readOnly` are server-set and must not be included. Fields marked `x-immutable`
|
|
2729
|
+
may be set once at creation.
|
|
2730
|
+
required:
|
|
2731
|
+
- name
|
|
2732
|
+
- quantity
|
|
2733
|
+
- price
|
|
2734
|
+
OrderItemUpdate:
|
|
2735
|
+
allOf:
|
|
2736
|
+
- $ref: '#/components/schemas/OrderItem'
|
|
2737
|
+
description: Write payload for partial update (PATCH) of a OrderItem document.
|
|
2738
|
+
All fields optional. Fields marked `readOnly` or `x-immutable` must not be
|
|
2739
|
+
sent.
|
|
2740
|
+
Sale:
|
|
2741
|
+
type: object
|
|
2742
|
+
properties:
|
|
2743
|
+
id:
|
|
2744
|
+
readOnly: true
|
|
2745
|
+
description: '(Read-only) Firestore document ID. Note: optional in current
|
|
2746
|
+
schema — some legacy docs may lack this field.'
|
|
2747
|
+
type:
|
|
2748
|
+
- string
|
|
2749
|
+
- 'null'
|
|
2750
|
+
companyId:
|
|
2751
|
+
x-immutable: true
|
|
2752
|
+
description: '(Immutable) FK → Company document ID. Note: optional in current
|
|
2753
|
+
schema — should be required (see ID consistency audit).'
|
|
2754
|
+
type:
|
|
2755
|
+
- string
|
|
2756
|
+
- 'null'
|
|
2757
|
+
customerId:
|
|
2758
|
+
description: FK → Customer.id (Firestore doc ID).
|
|
2759
|
+
type:
|
|
2760
|
+
- string
|
|
2761
|
+
- 'null'
|
|
2762
|
+
customerName:
|
|
2763
|
+
denormalized: true
|
|
2764
|
+
description: (Denormalized) From Customer.name at write time.
|
|
2765
|
+
type:
|
|
2766
|
+
- string
|
|
2767
|
+
- 'null'
|
|
2768
|
+
amount:
|
|
2769
|
+
type:
|
|
2770
|
+
- number
|
|
2771
|
+
- 'null'
|
|
2772
|
+
items:
|
|
2773
|
+
description: Line items. Reuses Order item schema.
|
|
2774
|
+
type:
|
|
2775
|
+
- array
|
|
2776
|
+
- 'null'
|
|
2777
|
+
items:
|
|
2778
|
+
$ref: '#/components/schemas/OrderItem'
|
|
2779
|
+
description: 'Line item within an Order or Sale/Purchase. Canonical fields:
|
|
2780
|
+
name, quantity, price, productId. Optional commerce fields (increment,
|
|
2781
|
+
variantId, supplierId, supplierName) and kitchen tracking fields (sentAt,
|
|
2782
|
+
startedCookingAt, readyAt, servedAt) are TBD/WIP pending cross-platform
|
|
2783
|
+
alignment.'
|
|
2784
|
+
imageUrl:
|
|
2785
|
+
type:
|
|
2786
|
+
- string
|
|
2787
|
+
- 'null'
|
|
2788
|
+
notes:
|
|
2789
|
+
type:
|
|
2790
|
+
- string
|
|
2791
|
+
- 'null'
|
|
2792
|
+
orderId:
|
|
2793
|
+
description: FK → Order.id. Link to associated Order document.
|
|
2794
|
+
type:
|
|
2795
|
+
- string
|
|
2796
|
+
- 'null'
|
|
2797
|
+
bookingId:
|
|
2798
|
+
description: FK → Booking.id. Link to associated Booking document (IG-12).
|
|
2799
|
+
type:
|
|
2800
|
+
- string
|
|
2801
|
+
- 'null'
|
|
2802
|
+
purchaseDate:
|
|
2803
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
2804
|
+
description: Firestore Timestamp serialized representation
|
|
2805
|
+
createdAt:
|
|
2806
|
+
anyOf:
|
|
2807
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
2808
|
+
- type: 'null'
|
|
2809
|
+
readOnly: true
|
|
2810
|
+
description: (Read-only) Server-generated creation timestamp.
|
|
2811
|
+
required:
|
|
2812
|
+
- purchaseDate
|
|
2813
|
+
additionalProperties: false
|
|
2814
|
+
description: 'Sale/Purchase model (D06). Collection: companies/{companyId}/purchases/{purchaseId}.
|
|
2815
|
+
Code alias: SalesService. [Deprecated path: customers/{custId}/purchases/{purchaseId}
|
|
2816
|
+
— migrate to company-wide path per MIG-04/IG-5]'
|
|
2817
|
+
SaleCreate:
|
|
2818
|
+
allOf:
|
|
2819
|
+
- $ref: '#/components/schemas/Sale'
|
|
2820
|
+
description: Write payload for creating a new Sale document. Fields marked `readOnly`
|
|
2821
|
+
are server-set and must not be included. Fields marked `x-immutable` may be
|
|
2822
|
+
set once at creation.
|
|
2823
|
+
required:
|
|
2824
|
+
- purchaseDate
|
|
2825
|
+
SaleUpdate:
|
|
2826
|
+
allOf:
|
|
2827
|
+
- $ref: '#/components/schemas/Sale'
|
|
2828
|
+
description: Write payload for partial update (PATCH) of a Sale document. All
|
|
2829
|
+
fields optional. Fields marked `readOnly` or `x-immutable` must not be sent.
|
|
2830
|
+
Ticket:
|
|
2831
|
+
type: object
|
|
2832
|
+
properties:
|
|
2833
|
+
id:
|
|
2834
|
+
type: string
|
|
2835
|
+
readOnly: true
|
|
2836
|
+
description: '(Read-only) Firestore document ID. Note: Ticket does not have
|
|
2837
|
+
a uid field.'
|
|
2838
|
+
eventId:
|
|
2839
|
+
type: string
|
|
2840
|
+
x-immutable: true
|
|
2841
|
+
description: (Immutable) FK → Event.id. Parent event this ticket belongs
|
|
2842
|
+
to. Set at creation.
|
|
2843
|
+
companyId:
|
|
2844
|
+
type: string
|
|
2845
|
+
x-immutable: true
|
|
2846
|
+
denormalized: true
|
|
2847
|
+
description: (Immutable, Denormalized) FK → Company document ID. Denormalized
|
|
2848
|
+
from parent Event for direct queries.
|
|
2849
|
+
customerId:
|
|
2850
|
+
x-see:
|
|
2851
|
+
decisions:
|
|
2852
|
+
- D29
|
|
2853
|
+
x-note: Added additively per D29. Denormalized customerName/email/phone
|
|
2854
|
+
are kept for backwards compatibility. Null on tickets created before D29
|
|
2855
|
+
was applied.
|
|
2856
|
+
description: FK → Customer.id. Optional structured link to Customer document
|
|
2857
|
+
(D29). Added additively alongside denormalized fields.
|
|
2858
|
+
type:
|
|
2859
|
+
- string
|
|
2860
|
+
- 'null'
|
|
2861
|
+
customerName:
|
|
2862
|
+
denormalized: true
|
|
2863
|
+
description: (Denormalized) From Customer.name at write time.
|
|
2864
|
+
type:
|
|
2865
|
+
- string
|
|
2866
|
+
- 'null'
|
|
2867
|
+
customerEmail:
|
|
2868
|
+
denormalized: true
|
|
2869
|
+
description: (Denormalized) From Customer.email at write time.
|
|
2870
|
+
type:
|
|
2871
|
+
- string
|
|
2872
|
+
- 'null'
|
|
2873
|
+
customerPhone:
|
|
2874
|
+
denormalized: true
|
|
2875
|
+
description: (Denormalized) From Customer.phone at write time.
|
|
2876
|
+
type:
|
|
2877
|
+
- string
|
|
2878
|
+
- 'null'
|
|
2879
|
+
status:
|
|
2880
|
+
$ref: '#/components/schemas/TicketStatus'
|
|
2881
|
+
description: Ticket lifecycle (D32). SCREAMING_SNAKE per D04. MIG-10 migrates
|
|
2882
|
+
legacy lowercase values.
|
|
2883
|
+
usedAt:
|
|
2884
|
+
anyOf:
|
|
2885
|
+
- $ref: '#/components/schemas/FirestoreTimestamp'
|
|
2886
|
+
- type: 'null'
|
|
2887
|
+
readOnly: true
|
|
2888
|
+
description: (Read-only) Timestamp when ticket was scanned/used. Set by
|
|
2889
|
+
scan operation.
|
|
2890
|
+
usedBy:
|
|
2891
|
+
readOnly: true
|
|
2892
|
+
description: (Read-only) FK → User/staff UID who scanned the ticket.
|
|
2893
|
+
type:
|
|
2894
|
+
- string
|
|
2895
|
+
- 'null'
|
|
2896
|
+
usedByName:
|
|
2897
|
+
readOnly: true
|
|
2898
|
+
denormalized: true
|
|
2899
|
+
description: (Read-only, Denormalized) From User display name at scan time.
|
|
2900
|
+
type:
|
|
2901
|
+
- string
|
|
2902
|
+
- 'null'
|
|
2903
|
+
price:
|
|
2904
|
+
type:
|
|
2905
|
+
- number
|
|
2906
|
+
- 'null'
|
|
2907
|
+
notes:
|
|
2908
|
+
type:
|
|
2909
|
+
- string
|
|
2910
|
+
- 'null'
|
|
2911
|
+
createdAt:
|
|
2912
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
2913
|
+
description: (Read-only) Server-generated creation timestamp.
|
|
2914
|
+
readOnly: true
|
|
2915
|
+
updatedAt:
|
|
2916
|
+
$ref: '#/components/schemas/FirestoreTimestamp'
|
|
2917
|
+
description: (Read-only) Server-generated update timestamp.
|
|
2918
|
+
readOnly: true
|
|
2919
|
+
createdBy:
|
|
2920
|
+
x-immutable: true
|
|
2921
|
+
description: (Immutable) FK → User/staff UID who created this ticket.
|
|
2922
|
+
type:
|
|
2923
|
+
- string
|
|
2924
|
+
- 'null'
|
|
2925
|
+
required:
|
|
2926
|
+
- id
|
|
2927
|
+
- eventId
|
|
2928
|
+
- companyId
|
|
2929
|
+
- status
|
|
2930
|
+
- createdAt
|
|
2931
|
+
- updatedAt
|
|
2932
|
+
additionalProperties: false
|
|
2933
|
+
description: 'Ticket model (D32). Collection: companies/{companyId}/events/{eventId}/tickets/{ticketId}.
|
|
2934
|
+
Mobile-only today; Dashboard in Wave 4.'
|
|
2935
|
+
TicketCreate:
|
|
2936
|
+
allOf:
|
|
2937
|
+
- $ref: '#/components/schemas/Ticket'
|
|
2938
|
+
description: Write payload for creating a new Ticket document. Fields marked
|
|
2939
|
+
`readOnly` are server-set and must not be included. Fields marked `x-immutable`
|
|
2940
|
+
may be set once at creation.
|
|
2941
|
+
required:
|
|
2942
|
+
- eventId
|
|
2943
|
+
- companyId
|
|
2944
|
+
- status
|
|
2945
|
+
TicketUpdate:
|
|
2946
|
+
allOf:
|
|
2947
|
+
- $ref: '#/components/schemas/Ticket'
|
|
2948
|
+
description: Write payload for partial update (PATCH) of a Ticket document.
|
|
2949
|
+
All fields optional. Fields marked `readOnly` or `x-immutable` must not be
|
|
2950
|
+
sent.
|
|
2951
|
+
PaymentSummary:
|
|
2952
|
+
type: object
|
|
2953
|
+
properties:
|
|
2954
|
+
id:
|
|
2955
|
+
type: string
|
|
2956
|
+
readOnly: true
|
|
2957
|
+
description: (Read-only) Firestore document ID. Matches the period key (e.g.
|
|
2958
|
+
"2026-03-09" for DAILY, "2026-03" for MONTHLY).
|
|
2959
|
+
companyId:
|
|
2960
|
+
type: string
|
|
2961
|
+
x-immutable: true
|
|
2962
|
+
description: (Immutable) FK → Company document ID. Scopes all queries.
|
|
2963
|
+
period:
|
|
2964
|
+
type: string
|
|
2965
|
+
x-note: 'Document ID matches this value. Format: YYYY-MM-DD (DAILY), YYYY-Www
|
|
2966
|
+
(WEEKLY), YYYY-MM (MONTHLY).'
|
|
2967
|
+
description: Period key. Determines the document ID and the time window
|
|
2968
|
+
covered.
|
|
2969
|
+
periodType:
|
|
2970
|
+
type: string
|
|
2971
|
+
enum:
|
|
2972
|
+
- DAILY
|
|
2973
|
+
- WEEKLY
|
|
2974
|
+
- MONTHLY
|
|
2975
|
+
description: Granularity of this summary document.
|
|
2976
|
+
paymentsByMethod:
|
|
2977
|
+
type: object
|
|
2978
|
+
propertyNames:
|
|
2979
|
+
type: string
|
|
2980
|
+
enum:
|
|
2981
|
+
- CASH
|
|
2982
|
+
- CREDIT_CARD
|
|
2983
|
+
- ORANGE_MONEY
|
|
2984
|
+
- WAVE
|
|
2985
|
+
- MTN_MONEY
|
|
2986
|
+
- MOOV_MONEY
|
|
2987
|
+
- BANK_TRANSFER
|
|
2988
|
+
- PAYPAL
|
|
2989
|
+
- STRIPE
|
|
2990
|
+
- OTHER
|
|
2991
|
+
additionalProperties:
|
|
2992
|
+
type: object
|
|
2993
|
+
properties:
|
|
2994
|
+
total:
|
|
2995
|
+
type: number
|
|
2996
|
+
description: Sum of payment amounts for this method in the period.
|
|
2997
|
+
Updated via FieldValue.increment().
|
|
2998
|
+
count:
|
|
2999
|
+
type: integer
|
|
3000
|
+
minimum: -9007199254740991
|
|
3001
|
+
maximum: 9007199254740991
|
|
3002
|
+
description: Number of individual payments for this method in the
|
|
3003
|
+
period. Updated via FieldValue.increment().
|
|
3004
|
+
required:
|
|
3005
|
+
- total
|
|
3006
|
+
- count
|
|
3007
|
+
additionalProperties: false
|
|
3008
|
+
required:
|
|
3009
|
+
- CASH
|
|
3010
|
+
- CREDIT_CARD
|
|
3011
|
+
- ORANGE_MONEY
|
|
3012
|
+
- WAVE
|
|
3013
|
+
- MTN_MONEY
|
|
3014
|
+
- MOOV_MONEY
|
|
3015
|
+
- BANK_TRANSFER
|
|
3016
|
+
- PAYPAL
|
|
3017
|
+
- STRIPE
|
|
3018
|
+
- OTHER
|
|
3019
|
+
x-note: Keys are PaymentMethod enum values (CASH, WAVE, ORANGE_MONEY, etc.).
|
|
3020
|
+
Missing keys imply zero for that method. Updated incrementally via FieldValue.increment().
|
|
3021
|
+
x-see:
|
|
3022
|
+
decisions:
|
|
3023
|
+
- D02
|
|
3024
|
+
- D12
|
|
3025
|
+
description: Payment totals broken down by PaymentMethod. Each entry holds
|
|
3026
|
+
the total amount and transaction count for the period.
|
|
3027
|
+
grandTotal:
|
|
3028
|
+
type: number
|
|
3029
|
+
readOnly: true
|
|
3030
|
+
description: (Read-only) Sum of all paymentsByMethod[*].total. Server-calculated.
|
|
3031
|
+
totalCount:
|
|
3032
|
+
type: integer
|
|
3033
|
+
minimum: -9007199254740991
|
|
3034
|
+
maximum: 9007199254740991
|
|
3035
|
+
readOnly: true
|
|
3036
|
+
description: (Read-only) Sum of all paymentsByMethod[*].count. Server-calculated.
|
|
3037
|
+
currency:
|
|
3038
|
+
type: string
|
|
3039
|
+
const: XOF
|
|
3040
|
+
description: Currency code. Locked to XOF (West African CFA franc).
|
|
3041
|
+
lastUpdatedAt:
|
|
3042
|
+
readOnly: true
|
|
3043
|
+
description: (Read-only) Server timestamp of the last increment write.
|
|
3044
|
+
type: object
|
|
3045
|
+
properties:
|
|
3046
|
+
_seconds:
|
|
3047
|
+
type: integer
|
|
3048
|
+
minimum: -9007199254740991
|
|
3049
|
+
maximum: 9007199254740991
|
|
3050
|
+
_nanoseconds:
|
|
3051
|
+
type: integer
|
|
3052
|
+
minimum: -9007199254740991
|
|
3053
|
+
maximum: 9007199254740991
|
|
3054
|
+
required:
|
|
3055
|
+
- _seconds
|
|
3056
|
+
- _nanoseconds
|
|
3057
|
+
additionalProperties: false
|
|
3058
|
+
createdAt:
|
|
3059
|
+
type: object
|
|
3060
|
+
properties:
|
|
3061
|
+
_seconds:
|
|
3062
|
+
type: integer
|
|
3063
|
+
minimum: -9007199254740991
|
|
3064
|
+
maximum: 9007199254740991
|
|
3065
|
+
_nanoseconds:
|
|
3066
|
+
type: integer
|
|
3067
|
+
minimum: -9007199254740991
|
|
3068
|
+
maximum: 9007199254740991
|
|
3069
|
+
required:
|
|
3070
|
+
- _seconds
|
|
3071
|
+
- _nanoseconds
|
|
3072
|
+
additionalProperties: false
|
|
3073
|
+
description: (Read-only) Server-generated creation timestamp.
|
|
3074
|
+
readOnly: true
|
|
3075
|
+
required:
|
|
3076
|
+
- id
|
|
3077
|
+
- companyId
|
|
3078
|
+
- period
|
|
3079
|
+
- periodType
|
|
3080
|
+
- paymentsByMethod
|
|
3081
|
+
- grandTotal
|
|
3082
|
+
- totalCount
|
|
3083
|
+
- currency
|
|
3084
|
+
- createdAt
|
|
3085
|
+
additionalProperties: false
|
|
3086
|
+
description: '[PROPOSED] Aggregated payment totals by method for a given period.
|
|
3087
|
+
Collection: companies/{companyId}/paymentSummaries/{period}. Server-owned
|
|
3088
|
+
— all fields are set by Cloud Function triggers on Order.payments[] and CustomerPayment
|
|
3089
|
+
writes. Clients must never write to this collection.'
|
|
3090
|
+
x-status: proposed
|