@ingenx-io/valets-schema-mcp-server 0.2.6 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/data/docs/collections/firestore-paths.md +20 -0
- package/data/docs/enums/app-status.md +1 -1
- package/data/docs/enums/attention-status.md +1 -1
- package/data/docs/enums/booking-status.md +1 -1
- package/data/docs/enums/contract-status.md +1 -1
- package/data/docs/enums/customer-payment-status.md +1 -1
- package/data/docs/enums/customer-payment-target-type.md +1 -1
- package/data/docs/enums/delivery-type.md +1 -1
- package/data/docs/enums/deployment-link-type.md +1 -1
- package/data/docs/enums/event-status.md +1 -1
- package/data/docs/enums/expense-payment-status.md +24 -0
- package/data/docs/enums/fulfillment-status.md +2 -2
- package/data/docs/enums/loyalty-transaction-type.md +2 -2
- package/data/docs/enums/milestone-status.md +2 -2
- package/data/docs/enums/notification-channel.md +2 -2
- package/data/docs/enums/notification-entity-type.md +2 -2
- package/data/docs/enums/notification-status.md +2 -2
- package/data/docs/enums/order-status.md +2 -2
- package/data/docs/enums/outbound-message-format.md +2 -2
- package/data/docs/enums/outbound-message-purpose.md +2 -2
- package/data/docs/enums/outbound-message-status.md +2 -2
- package/data/docs/enums/payment-method.md +4 -3
- package/data/docs/enums/payment-proof-status.md +2 -2
- package/data/docs/enums/payment-status.md +2 -2
- package/data/docs/enums/pending-issue.md +2 -2
- package/data/docs/enums/return-status.md +2 -2
- package/data/docs/enums/session-status.md +2 -2
- package/data/docs/enums/site-status.md +2 -2
- package/data/docs/enums/stocktake-frequency.md +2 -2
- package/data/docs/enums/stocktake-item-status.md +2 -2
- package/data/docs/enums/stocktake-status.md +2 -2
- package/data/docs/enums/ticket-status.md +2 -2
- package/data/docs/enums/waba-label.md +2 -2
- package/data/docs/enums/whatsapp-button-sub-type.md +2 -2
- package/data/docs/enums/whatsapp-template-component.md +2 -2
- package/data/docs/enums/whatsapp-template-status.md +2 -2
- package/data/docs/index.md +8 -5
- package/data/docs/models/allowed-user.md +1 -1
- package/data/docs/models/analytics-backfill.md +1 -1
- package/data/docs/models/analytics-daily.md +1 -1
- package/data/docs/models/analytics-event.md +1 -1
- package/data/docs/models/analytics-hourly.md +1 -1
- package/data/docs/models/app-payment.md +1 -1
- package/data/docs/models/app.md +1 -1
- package/data/docs/models/booking-version.md +1 -1
- package/data/docs/models/booking.md +1 -1
- package/data/docs/models/contract.md +1 -1
- package/data/docs/models/customer-payment-allocation.md +1 -1
- package/data/docs/models/customer-payment.md +22 -21
- package/data/docs/models/customer.md +1 -1
- package/data/docs/models/event.md +1 -1
- package/data/docs/models/expense.md +434 -0
- package/data/docs/models/loyalty-config.md +2 -2
- package/data/docs/models/loyalty-reward.md +2 -2
- package/data/docs/models/loyalty-status.md +2 -2
- package/data/docs/models/loyalty-transaction.md +2 -2
- package/data/docs/models/magic-link-request.md +2 -2
- package/data/docs/models/metrics-current.md +22 -2
- package/data/docs/models/metrics-daily.md +92 -41
- package/data/docs/models/metrics-monthly.md +22 -2
- package/data/docs/models/notification-record.md +68 -35
- package/data/docs/models/order-item.md +2 -2
- package/data/docs/models/order.md +56 -55
- package/data/docs/models/outbound-payment-allocation.md +2 -2
- package/data/docs/models/outbound-payment.md +3 -2
- package/data/docs/models/payment-webhook-delivery.md +321 -0
- package/data/docs/models/payment-webhook-endpoint.md +2 -2
- package/data/docs/models/sale.md +2 -2
- package/data/docs/models/site-payment.md +2 -2
- package/data/docs/models/site.md +2 -2
- package/data/docs/models/stocktake-item.md +2 -2
- package/data/docs/models/stocktake.md +2 -2
- package/data/docs/models/ticket.md +2 -2
- package/data/docs/models/user.md +2 -2
- package/data/docs/models/whatsapp-inbound-message.md +42 -18
- package/data/docs/models/whatsapp-outbound-lifecycle-event.md +2 -2
- package/data/docs/models/whatsapp-outbound-message.md +56 -32
- package/data/docs/models/whatsapp-template.md +2 -2
- package/data/static/llms.txt +110 -11
- package/data/static/openapi.yaml +444 -15
- package/data/static/schemas.json +394 -13
- package/package.json +1 -1
package/data/static/schemas.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
3
|
"description": "@valets/schema \u2014 consolidated schema bundle",
|
|
4
|
-
"generated": "2026-05-
|
|
4
|
+
"generated": "2026-05-30T14:38:11.260961+00:00",
|
|
5
5
|
"schemas": {
|
|
6
6
|
"allowed-user": {
|
|
7
7
|
"type": "object",
|
|
@@ -2334,7 +2334,7 @@
|
|
|
2334
2334
|
},
|
|
2335
2335
|
"paymentMethod": {
|
|
2336
2336
|
"$ref": "#/definitions/payment-method",
|
|
2337
|
-
"description": "Unified payment method set with African + global methods (D02)."
|
|
2337
|
+
"description": "Unified payment method set with African + global methods (D02). Note: the metrics writer historically emits \"OM\" instead of \"ORANGE_MONEY\" as a paymentsByMethod map key \u2014 treat OM as deprecated; canonical value is ORANGE_MONEY (#21)."
|
|
2338
2338
|
},
|
|
2339
2339
|
"referenceNumber": {
|
|
2340
2340
|
"type": "string",
|
|
@@ -2732,6 +2732,182 @@
|
|
|
2732
2732
|
],
|
|
2733
2733
|
"description": "Ticketed event lifecycle (D32). Mobile-only today; Dashboard in Wave 4."
|
|
2734
2734
|
},
|
|
2735
|
+
"expense": {
|
|
2736
|
+
"type": "object",
|
|
2737
|
+
"properties": {
|
|
2738
|
+
"id": {
|
|
2739
|
+
"readOnly": true,
|
|
2740
|
+
"description": "(Read-only) Firestore document ID, auto-generated.",
|
|
2741
|
+
"type": [
|
|
2742
|
+
"string",
|
|
2743
|
+
"null"
|
|
2744
|
+
]
|
|
2745
|
+
},
|
|
2746
|
+
"companyId": {
|
|
2747
|
+
"type": "string",
|
|
2748
|
+
"x-immutable": true,
|
|
2749
|
+
"description": "(Immutable) FK \u2192 Company document ID."
|
|
2750
|
+
},
|
|
2751
|
+
"title": {
|
|
2752
|
+
"type": "string",
|
|
2753
|
+
"description": "Human-readable expense title (e.g. \"Loyer mars 2026\", \"Facture EAU\")."
|
|
2754
|
+
},
|
|
2755
|
+
"description": {
|
|
2756
|
+
"description": "Optional longer description or notes.",
|
|
2757
|
+
"type": [
|
|
2758
|
+
"string",
|
|
2759
|
+
"null"
|
|
2760
|
+
]
|
|
2761
|
+
},
|
|
2762
|
+
"amount": {
|
|
2763
|
+
"type": "number",
|
|
2764
|
+
"description": "Total expense amount (XOF)."
|
|
2765
|
+
},
|
|
2766
|
+
"currency": {
|
|
2767
|
+
"type": "string",
|
|
2768
|
+
"const": "XOF",
|
|
2769
|
+
"description": "Currency code. Locked to XOF."
|
|
2770
|
+
},
|
|
2771
|
+
"dueDate": {
|
|
2772
|
+
"anyOf": [
|
|
2773
|
+
{
|
|
2774
|
+
"$ref": "#/definitions/firestore-timestamp"
|
|
2775
|
+
},
|
|
2776
|
+
{
|
|
2777
|
+
"type": "null"
|
|
2778
|
+
}
|
|
2779
|
+
],
|
|
2780
|
+
"description": "When the expense is due. Used to compute OVERDUE state at read time (not stored in paymentStatus)."
|
|
2781
|
+
},
|
|
2782
|
+
"paymentStatus": {
|
|
2783
|
+
"$ref": "#/definitions/expense-payment-status",
|
|
2784
|
+
"x-note": "OVERDUE is intentionally excluded \u2014 it is never stored in Firestore. Compute it at read time: expense.paymentStatus !== PAID && expense.dueDate < now() (#13). Helper: isExpenseOverdue(expense: Expense): boolean.",
|
|
2785
|
+
"description": "Current payment status. OVERDUE is never stored \u2014 derive from dueDate at read time (#13)."
|
|
2786
|
+
},
|
|
2787
|
+
"amountDue": {
|
|
2788
|
+
"x-note": "Authoritative for simple (non-allocation) expenses. Legacy field maintained for backward compatibility when no OutboundPaymentAllocation records exist (#12).",
|
|
2789
|
+
"description": "Amount still owed. Authoritative when no OutboundPaymentAllocation records exist for this expense.",
|
|
2790
|
+
"type": [
|
|
2791
|
+
"number",
|
|
2792
|
+
"null"
|
|
2793
|
+
]
|
|
2794
|
+
},
|
|
2795
|
+
"amountPaid": {
|
|
2796
|
+
"description": "Amount paid to date (simple tracking, no allocations).",
|
|
2797
|
+
"type": [
|
|
2798
|
+
"number",
|
|
2799
|
+
"null"
|
|
2800
|
+
]
|
|
2801
|
+
},
|
|
2802
|
+
"allocatedAmount": {
|
|
2803
|
+
"readOnly": true,
|
|
2804
|
+
"x-note": "Server-set \u2014 computed from OutboundPaymentAllocation records. Clients must never write this field (#12).",
|
|
2805
|
+
"description": "(Read-only) Total amount allocated via OutboundPaymentAllocation records. Authoritative when allocations exist.",
|
|
2806
|
+
"type": [
|
|
2807
|
+
"number",
|
|
2808
|
+
"null"
|
|
2809
|
+
]
|
|
2810
|
+
},
|
|
2811
|
+
"balance": {
|
|
2812
|
+
"readOnly": true,
|
|
2813
|
+
"x-note": "Server-set \u2014 computed as amount - allocatedAmount. Authoritative remaining amount when allocations exist. Prefer this over amountDue when OutboundPaymentAllocation records are present (#12).",
|
|
2814
|
+
"description": "(Read-only) Remaining balance: amount minus allocatedAmount. Authoritative when OutboundPaymentAllocation records exist.",
|
|
2815
|
+
"type": [
|
|
2816
|
+
"number",
|
|
2817
|
+
"null"
|
|
2818
|
+
]
|
|
2819
|
+
},
|
|
2820
|
+
"paidDate": {
|
|
2821
|
+
"anyOf": [
|
|
2822
|
+
{
|
|
2823
|
+
"$ref": "#/definitions/firestore-timestamp"
|
|
2824
|
+
},
|
|
2825
|
+
{
|
|
2826
|
+
"type": "null"
|
|
2827
|
+
}
|
|
2828
|
+
],
|
|
2829
|
+
"x-when": "Set when paymentStatus transitions to PAID (fully settled). Null for partially paid or unpaid expenses. For multi-payment history, read OutboundPaymentAllocation records (#19).",
|
|
2830
|
+
"description": "When the expense was fully settled (paymentStatus = PAID). Null otherwise."
|
|
2831
|
+
},
|
|
2832
|
+
"paymentReference": {
|
|
2833
|
+
"x-note": "Reference for the most recent payment transaction (check number, wire ID, Wave ref, etc.). Overwritten on each payment. For full payment history read OutboundPaymentAllocation records (#19).",
|
|
2834
|
+
"description": "Most recent payment transaction reference. Overwritten on each payment; not a full history.",
|
|
2835
|
+
"type": [
|
|
2836
|
+
"string",
|
|
2837
|
+
"null"
|
|
2838
|
+
]
|
|
2839
|
+
},
|
|
2840
|
+
"createdBy": {
|
|
2841
|
+
"type": "string",
|
|
2842
|
+
"x-immutable": true,
|
|
2843
|
+
"description": "(Immutable) FK \u2192 User/staff UID who created this expense record."
|
|
2844
|
+
},
|
|
2845
|
+
"createdAt": {
|
|
2846
|
+
"anyOf": [
|
|
2847
|
+
{
|
|
2848
|
+
"$ref": "#/definitions/firestore-timestamp"
|
|
2849
|
+
},
|
|
2850
|
+
{
|
|
2851
|
+
"type": "null"
|
|
2852
|
+
}
|
|
2853
|
+
],
|
|
2854
|
+
"readOnly": true,
|
|
2855
|
+
"description": "(Read-only) Server-generated creation timestamp."
|
|
2856
|
+
},
|
|
2857
|
+
"updatedAt": {
|
|
2858
|
+
"anyOf": [
|
|
2859
|
+
{
|
|
2860
|
+
"$ref": "#/definitions/firestore-timestamp"
|
|
2861
|
+
},
|
|
2862
|
+
{
|
|
2863
|
+
"type": "null"
|
|
2864
|
+
}
|
|
2865
|
+
],
|
|
2866
|
+
"readOnly": true,
|
|
2867
|
+
"description": "(Read-only) Server-generated last-update timestamp."
|
|
2868
|
+
}
|
|
2869
|
+
},
|
|
2870
|
+
"required": [
|
|
2871
|
+
"companyId",
|
|
2872
|
+
"title",
|
|
2873
|
+
"amount",
|
|
2874
|
+
"currency",
|
|
2875
|
+
"paymentStatus",
|
|
2876
|
+
"createdBy"
|
|
2877
|
+
],
|
|
2878
|
+
"additionalProperties": false,
|
|
2879
|
+
"description": "Expense (GH#12/#13/#19 partial). Collection: companies/{companyId}/expenses/{expenseId}. Dual balance tracking: amountPaid/amountDue for simple expenses; allocatedAmount/balance (server-set) for allocation-settled expenses. OVERDUE excluded from stored enum \u2014 derive at read time. Full domain (Payee FK, Contract FK) in #20.",
|
|
2880
|
+
"example": {
|
|
2881
|
+
"id": null,
|
|
2882
|
+
"companyId": "comp_xyz789",
|
|
2883
|
+
"title": "title",
|
|
2884
|
+
"description": null,
|
|
2885
|
+
"amount": 45000,
|
|
2886
|
+
"currency": "XOF",
|
|
2887
|
+
"dueDate": "dueDate",
|
|
2888
|
+
"paymentStatus": "paymentStatus",
|
|
2889
|
+
"amountDue": null,
|
|
2890
|
+
"amountPaid": null,
|
|
2891
|
+
"allocatedAmount": null,
|
|
2892
|
+
"balance": null,
|
|
2893
|
+
"paidDate": "pai_ref123",
|
|
2894
|
+
"paymentReference": null,
|
|
2895
|
+
"createdBy": "staff_k0f1",
|
|
2896
|
+
"createdAt": "createdAt",
|
|
2897
|
+
"updatedAt": "updatedAt"
|
|
2898
|
+
}
|
|
2899
|
+
},
|
|
2900
|
+
"expense-payment-status": {
|
|
2901
|
+
"type": "string",
|
|
2902
|
+
"enum": [
|
|
2903
|
+
"PENDING",
|
|
2904
|
+
"PARTIALLY_PAID",
|
|
2905
|
+
"PAID",
|
|
2906
|
+
"FAILED"
|
|
2907
|
+
],
|
|
2908
|
+
"x-note": "OVERDUE is intentionally excluded \u2014 it is never stored in Firestore. Compute it at read time: expense.paymentStatus !== PAID && expense.dueDate < now() (#13). Helper: isExpenseOverdue(expense: Expense): boolean.",
|
|
2909
|
+
"description": "Payment status of an Expense. Stored enum \u2014 OVERDUE is not stored, it is derived at read time from dueDate (#13)."
|
|
2910
|
+
},
|
|
2735
2911
|
"fulfillment-status": {
|
|
2736
2912
|
"type": "string",
|
|
2737
2913
|
"enum": [
|
|
@@ -3362,6 +3538,7 @@
|
|
|
3362
3538
|
"orderCompletionRate30d": {
|
|
3363
3539
|
"type": "number",
|
|
3364
3540
|
"readOnly": true,
|
|
3541
|
+
"x-note": "Firestore REST API v1 writes integerValue when the stored value is whole (e.g. 0), doubleValue when fractional (e.g. 82.17). Admin SDK smooths this to a JS number; REST clients must coerce the union (#11).",
|
|
3365
3542
|
"description": "(Read-only) Percentage of orders completed or delivered in the last 30 days. Always full recalc."
|
|
3366
3543
|
},
|
|
3367
3544
|
"todayPurchasesCount": {
|
|
@@ -3379,11 +3556,13 @@
|
|
|
3379
3556
|
"averagePurchaseAmount": {
|
|
3380
3557
|
"type": "number",
|
|
3381
3558
|
"readOnly": true,
|
|
3559
|
+
"x-note": "Firestore REST API v1 writes integerValue when whole (e.g. 10070), doubleValue when fractional (e.g. 10006.5). Admin SDK smooths this; REST clients must coerce (#11).",
|
|
3382
3560
|
"description": "(Read-only) Average purchase value across last 200 purchases (rolling, not time-windowed)."
|
|
3383
3561
|
},
|
|
3384
3562
|
"monthlyRevenue": {
|
|
3385
3563
|
"type": "number",
|
|
3386
3564
|
"readOnly": true,
|
|
3565
|
+
"x-note": "Observed as integerValue on all sampled tenants (whole XOF amounts). Will be doubleValue if fractional. REST clients must coerce (#11).",
|
|
3387
3566
|
"description": "(Read-only) Total purchase value in the current calendar month (UTC)."
|
|
3388
3567
|
},
|
|
3389
3568
|
"monthlyPurchasesCount": {
|
|
@@ -3420,6 +3599,7 @@
|
|
|
3420
3599
|
"todayCollectedAmount": {
|
|
3421
3600
|
"type": "number",
|
|
3422
3601
|
"readOnly": true,
|
|
3602
|
+
"x-note": "Observed as integerValue \"0\" on all sampled tenants. Will be doubleValue if fractional payments occur. REST clients must coerce (#11).",
|
|
3423
3603
|
"description": "(Read-only) Sum of totalAmount for bookings where PAYMENT_PAID_AT is today. Resets at midnight."
|
|
3424
3604
|
},
|
|
3425
3605
|
"todayRevenue": {
|
|
@@ -3465,6 +3645,7 @@
|
|
|
3465
3645
|
"averageRating": {
|
|
3466
3646
|
"type": "number",
|
|
3467
3647
|
"readOnly": true,
|
|
3648
|
+
"x-note": "Observed as integerValue \"0\" on all tenants (no reviews yet). Will be doubleValue once real ratings exist. REST clients must coerce (#11).",
|
|
3468
3649
|
"description": "(Read-only) Average rating from the last 200 reviews (rolling). Always full recalc."
|
|
3469
3650
|
},
|
|
3470
3651
|
"lowStockItemsCount": {
|
|
@@ -3638,6 +3819,7 @@
|
|
|
3638
3819
|
"orderCompletionRate30d": {
|
|
3639
3820
|
"type": "number",
|
|
3640
3821
|
"readOnly": true,
|
|
3822
|
+
"x-note": "Firestore REST API v1 writes integerValue when the stored value is whole (e.g. 0), doubleValue when fractional (e.g. 82.17). Admin SDK smooths this to a JS number; REST clients must coerce the union (#11).",
|
|
3641
3823
|
"description": "(Read-only) Percentage of orders completed or delivered in the last 30 days. Always full recalc."
|
|
3642
3824
|
},
|
|
3643
3825
|
"todayPurchasesCount": {
|
|
@@ -3655,11 +3837,13 @@
|
|
|
3655
3837
|
"averagePurchaseAmount": {
|
|
3656
3838
|
"type": "number",
|
|
3657
3839
|
"readOnly": true,
|
|
3840
|
+
"x-note": "Firestore REST API v1 writes integerValue when whole (e.g. 10070), doubleValue when fractional (e.g. 10006.5). Admin SDK smooths this; REST clients must coerce (#11).",
|
|
3658
3841
|
"description": "(Read-only) Average purchase value across last 200 purchases (rolling, not time-windowed)."
|
|
3659
3842
|
},
|
|
3660
3843
|
"monthlyRevenue": {
|
|
3661
3844
|
"type": "number",
|
|
3662
3845
|
"readOnly": true,
|
|
3846
|
+
"x-note": "Observed as integerValue on all sampled tenants (whole XOF amounts). Will be doubleValue if fractional. REST clients must coerce (#11).",
|
|
3663
3847
|
"description": "(Read-only) Total purchase value in the current calendar month (UTC)."
|
|
3664
3848
|
},
|
|
3665
3849
|
"monthlyPurchasesCount": {
|
|
@@ -3696,6 +3880,7 @@
|
|
|
3696
3880
|
"todayCollectedAmount": {
|
|
3697
3881
|
"type": "number",
|
|
3698
3882
|
"readOnly": true,
|
|
3883
|
+
"x-note": "Observed as integerValue \"0\" on all sampled tenants. Will be doubleValue if fractional payments occur. REST clients must coerce (#11).",
|
|
3699
3884
|
"description": "(Read-only) Sum of totalAmount for bookings where PAYMENT_PAID_AT is today. Resets at midnight."
|
|
3700
3885
|
},
|
|
3701
3886
|
"todayRevenue": {
|
|
@@ -3741,6 +3926,7 @@
|
|
|
3741
3926
|
"averageRating": {
|
|
3742
3927
|
"type": "number",
|
|
3743
3928
|
"readOnly": true,
|
|
3929
|
+
"x-note": "Observed as integerValue \"0\" on all tenants (no reviews yet). Will be doubleValue once real ratings exist. REST clients must coerce (#11).",
|
|
3744
3930
|
"description": "(Read-only) Average rating from the last 200 reviews (rolling). Always full recalc."
|
|
3745
3931
|
},
|
|
3746
3932
|
"lowStockItemsCount": {
|
|
@@ -3808,8 +3994,8 @@
|
|
|
3808
3994
|
},
|
|
3809
3995
|
"paymentsByMethod": {
|
|
3810
3996
|
"readOnly": true,
|
|
3811
|
-
"x-note": "
|
|
3812
|
-
"description": "(Read-only, Optional)
|
|
3997
|
+
"x-note": "Map keys use short codes in practice (OM, CASH, WAVE) \u2014 OM is a non-canonical alias for ORANGE_MONEY emitted by the metrics writer (#21). Value shape { total, count } differs from MetricsCurrent.paymentsByMethod (bare number).",
|
|
3998
|
+
"description": "(Read-only, Optional) Payment breakdown by method for the day. Keys are PaymentMethod values (or legacy short code OM). Value is { total: XOF amount, count: number of payments }.",
|
|
3813
3999
|
"type": [
|
|
3814
4000
|
"object",
|
|
3815
4001
|
"null"
|
|
@@ -3818,7 +4004,24 @@
|
|
|
3818
4004
|
"type": "string"
|
|
3819
4005
|
},
|
|
3820
4006
|
"additionalProperties": {
|
|
3821
|
-
"type": "
|
|
4007
|
+
"type": "object",
|
|
4008
|
+
"properties": {
|
|
4009
|
+
"total": {
|
|
4010
|
+
"type": "number",
|
|
4011
|
+
"description": "Sum of payment amounts for this method on the given day (XOF)."
|
|
4012
|
+
},
|
|
4013
|
+
"count": {
|
|
4014
|
+
"type": "integer",
|
|
4015
|
+
"minimum": -9007199254740991,
|
|
4016
|
+
"maximum": 9007199254740991,
|
|
4017
|
+
"description": "Number of payments using this method on the given day."
|
|
4018
|
+
}
|
|
4019
|
+
},
|
|
4020
|
+
"required": [
|
|
4021
|
+
"total",
|
|
4022
|
+
"count"
|
|
4023
|
+
],
|
|
4024
|
+
"additionalProperties": false
|
|
3822
4025
|
}
|
|
3823
4026
|
},
|
|
3824
4027
|
"computedForDay": {
|
|
@@ -3866,7 +4069,8 @@
|
|
|
3866
4069
|
"date"
|
|
3867
4070
|
],
|
|
3868
4071
|
"additionalProperties": false,
|
|
3869
|
-
"
|
|
4072
|
+
"x-note": "Zero-activity behavior (#9): the computeDailyCompanyMetrics cron (02:00 UTC) does NOT write a snapshot for days with no activity. A missing document means either zero activity or the cron did not run \u2014 consumers cannot distinguish the two from the absence alone. To detect cron gaps, compare the latest document date with today; a gap larger than 1 day on an otherwise active tenant indicates a cron failure. Observed: 3 of 4 zahoui tenants had gaps; bingerville (active) had a document every day.",
|
|
4073
|
+
"description": "Daily metrics snapshot. Collection: companies/{companyId}/metrics_daily/{YYYY-MM-DD}. Same fields as MetricsCurrent plus `date`. Written by computeDailyCompanyMetrics cron (02:00 UTC) when the company had activity that day; zero-activity days may produce no document (#9).",
|
|
3870
4074
|
"example": {
|
|
3871
4075
|
"todayOrdersCount": 2,
|
|
3872
4076
|
"pendingOrdersCount": 2,
|
|
@@ -3921,6 +4125,7 @@
|
|
|
3921
4125
|
"orderCompletionRate30d": {
|
|
3922
4126
|
"type": "number",
|
|
3923
4127
|
"readOnly": true,
|
|
4128
|
+
"x-note": "Firestore REST API v1 writes integerValue when the stored value is whole (e.g. 0), doubleValue when fractional (e.g. 82.17). Admin SDK smooths this to a JS number; REST clients must coerce the union (#11).",
|
|
3924
4129
|
"description": "(Read-only) Percentage of orders completed or delivered in the last 30 days. Always full recalc."
|
|
3925
4130
|
},
|
|
3926
4131
|
"todayPurchasesCount": {
|
|
@@ -3938,11 +4143,13 @@
|
|
|
3938
4143
|
"averagePurchaseAmount": {
|
|
3939
4144
|
"type": "number",
|
|
3940
4145
|
"readOnly": true,
|
|
4146
|
+
"x-note": "Firestore REST API v1 writes integerValue when whole (e.g. 10070), doubleValue when fractional (e.g. 10006.5). Admin SDK smooths this; REST clients must coerce (#11).",
|
|
3941
4147
|
"description": "(Read-only) Average purchase value across last 200 purchases (rolling, not time-windowed)."
|
|
3942
4148
|
},
|
|
3943
4149
|
"monthlyRevenue": {
|
|
3944
4150
|
"type": "number",
|
|
3945
4151
|
"readOnly": true,
|
|
4152
|
+
"x-note": "Observed as integerValue on all sampled tenants (whole XOF amounts). Will be doubleValue if fractional. REST clients must coerce (#11).",
|
|
3946
4153
|
"description": "(Read-only) Total purchase value in the current calendar month (UTC)."
|
|
3947
4154
|
},
|
|
3948
4155
|
"monthlyPurchasesCount": {
|
|
@@ -3979,6 +4186,7 @@
|
|
|
3979
4186
|
"todayCollectedAmount": {
|
|
3980
4187
|
"type": "number",
|
|
3981
4188
|
"readOnly": true,
|
|
4189
|
+
"x-note": "Observed as integerValue \"0\" on all sampled tenants. Will be doubleValue if fractional payments occur. REST clients must coerce (#11).",
|
|
3982
4190
|
"description": "(Read-only) Sum of totalAmount for bookings where PAYMENT_PAID_AT is today. Resets at midnight."
|
|
3983
4191
|
},
|
|
3984
4192
|
"todayRevenue": {
|
|
@@ -4024,6 +4232,7 @@
|
|
|
4024
4232
|
"averageRating": {
|
|
4025
4233
|
"type": "number",
|
|
4026
4234
|
"readOnly": true,
|
|
4235
|
+
"x-note": "Observed as integerValue \"0\" on all tenants (no reviews yet). Will be doubleValue once real ratings exist. REST clients must coerce (#11).",
|
|
4027
4236
|
"description": "(Read-only) Average rating from the last 200 reviews (rolling). Always full recalc."
|
|
4028
4237
|
},
|
|
4029
4238
|
"lowStockItemsCount": {
|
|
@@ -4258,7 +4467,14 @@
|
|
|
4258
4467
|
"type": "string"
|
|
4259
4468
|
},
|
|
4260
4469
|
"phone": {
|
|
4261
|
-
"description": "Recipient phone number (E.164). Present for whatsapp/sms notifications.",
|
|
4470
|
+
"description": "Recipient phone number as passed by the sender (may be raw wa_id or E.164). Present for whatsapp/sms notifications.",
|
|
4471
|
+
"type": "string"
|
|
4472
|
+
},
|
|
4473
|
+
"contactE164": {
|
|
4474
|
+
"readOnly": true,
|
|
4475
|
+
"x-note": "Canonical E.164 phone, normalized from `phone` by the backend writer. Use this for joins and search, not the raw `phone` field (#56). Absent on pre-migration docs.",
|
|
4476
|
+
"x-when": "Populated by Cloud Functions on every new NotificationRecord for whatsapp/sms channels. CI normalization applied (8\u219210-digit 07/05/01 series).",
|
|
4477
|
+
"description": "(Read-only) E.164-normalized phone (e.g. +2250777471485). Canonical join key across WhatsApp and notification collections (#56).",
|
|
4262
4478
|
"type": "string"
|
|
4263
4479
|
},
|
|
4264
4480
|
"name": {
|
|
@@ -4286,7 +4502,14 @@
|
|
|
4286
4502
|
"type": "string"
|
|
4287
4503
|
},
|
|
4288
4504
|
"phone": {
|
|
4289
|
-
"description": "Recipient phone number (E.164). Present for whatsapp/sms notifications.",
|
|
4505
|
+
"description": "Recipient phone number as passed by the sender (may be raw wa_id or E.164). Present for whatsapp/sms notifications.",
|
|
4506
|
+
"type": "string"
|
|
4507
|
+
},
|
|
4508
|
+
"contactE164": {
|
|
4509
|
+
"readOnly": true,
|
|
4510
|
+
"x-note": "Canonical E.164 phone, normalized from `phone` by the backend writer. Use this for joins and search, not the raw `phone` field (#56). Absent on pre-migration docs.",
|
|
4511
|
+
"x-when": "Populated by Cloud Functions on every new NotificationRecord for whatsapp/sms channels. CI normalization applied (8\u219210-digit 07/05/01 series).",
|
|
4512
|
+
"description": "(Read-only) E.164-normalized phone (e.g. +2250777471485). Canonical join key across WhatsApp and notification collections (#56).",
|
|
4290
4513
|
"type": "string"
|
|
4291
4514
|
},
|
|
4292
4515
|
"name": {
|
|
@@ -4313,7 +4536,14 @@
|
|
|
4313
4536
|
"type": "string"
|
|
4314
4537
|
},
|
|
4315
4538
|
"phone": {
|
|
4316
|
-
"description": "Recipient phone number (E.164). Present for whatsapp/sms notifications.",
|
|
4539
|
+
"description": "Recipient phone number as passed by the sender (may be raw wa_id or E.164). Present for whatsapp/sms notifications.",
|
|
4540
|
+
"type": "string"
|
|
4541
|
+
},
|
|
4542
|
+
"contactE164": {
|
|
4543
|
+
"readOnly": true,
|
|
4544
|
+
"x-note": "Canonical E.164 phone, normalized from `phone` by the backend writer. Use this for joins and search, not the raw `phone` field (#56). Absent on pre-migration docs.",
|
|
4545
|
+
"x-when": "Populated by Cloud Functions on every new NotificationRecord for whatsapp/sms channels. CI normalization applied (8\u219210-digit 07/05/01 series).",
|
|
4546
|
+
"description": "(Read-only) E.164-normalized phone (e.g. +2250777471485). Canonical join key across WhatsApp and notification collections (#56).",
|
|
4317
4547
|
"type": "string"
|
|
4318
4548
|
},
|
|
4319
4549
|
"name": {
|
|
@@ -4668,7 +4898,7 @@
|
|
|
4668
4898
|
"type": "null"
|
|
4669
4899
|
}
|
|
4670
4900
|
],
|
|
4671
|
-
"description": "Unified payment method set with African + global methods (D02)."
|
|
4901
|
+
"description": "Unified payment method set with African + global methods (D02). Note: the metrics writer historically emits \"OM\" instead of \"ORANGE_MONEY\" as a paymentsByMethod map key \u2014 treat OM as deprecated; canonical value is ORANGE_MONEY (#21)."
|
|
4672
4902
|
},
|
|
4673
4903
|
"invoiceId": {
|
|
4674
4904
|
"description": "FK \u2192 Invoice document ID.",
|
|
@@ -5605,9 +5835,10 @@
|
|
|
5605
5835
|
"BANK_TRANSFER",
|
|
5606
5836
|
"PAYPAL",
|
|
5607
5837
|
"STRIPE",
|
|
5608
|
-
"OTHER"
|
|
5838
|
+
"OTHER",
|
|
5839
|
+
"OM"
|
|
5609
5840
|
],
|
|
5610
|
-
"description": "Unified payment method set with African + global methods (D02)."
|
|
5841
|
+
"description": "Unified payment method set with African + global methods (D02). Note: the metrics writer historically emits \"OM\" instead of \"ORANGE_MONEY\" as a paymentsByMethod map key \u2014 treat OM as deprecated; canonical value is ORANGE_MONEY (#21)."
|
|
5611
5842
|
},
|
|
5612
5843
|
"payment-proof-status": {
|
|
5613
5844
|
"type": "string",
|
|
@@ -5631,6 +5862,134 @@
|
|
|
5631
5862
|
],
|
|
5632
5863
|
"description": "Payment lifecycle status (D01 amended). Used by Order, Sale/Purchase, Booking."
|
|
5633
5864
|
},
|
|
5865
|
+
"payment-webhook-delivery": {
|
|
5866
|
+
"type": "object",
|
|
5867
|
+
"properties": {
|
|
5868
|
+
"id": {
|
|
5869
|
+
"readOnly": true,
|
|
5870
|
+
"description": "(Read-only) Firestore document ID, auto-generated.",
|
|
5871
|
+
"type": [
|
|
5872
|
+
"string",
|
|
5873
|
+
"null"
|
|
5874
|
+
]
|
|
5875
|
+
},
|
|
5876
|
+
"company": {
|
|
5877
|
+
"type": "string",
|
|
5878
|
+
"x-immutable": true,
|
|
5879
|
+
"description": "(Immutable) Company document ID (e.g. \"gerko_studios\"). Resolved from the matched endpoint at delivery time."
|
|
5880
|
+
},
|
|
5881
|
+
"provider": {
|
|
5882
|
+
"type": "string",
|
|
5883
|
+
"x-note": "Observed value: \"jeko\". The inner payload.paymentMethod may differ (e.g. \"wave\") \u2014 provider here is the webhook sender, not the payment rail (#42).",
|
|
5884
|
+
"description": "Payment provider that sent this webhook (e.g. \"jeko\", \"wave\")."
|
|
5885
|
+
},
|
|
5886
|
+
"eventType": {
|
|
5887
|
+
"type": "string",
|
|
5888
|
+
"x-note": "Observed value: \"transaction.payment\". Jeko docs say \"transaction.completed\" \u2014 full set per provider unconfirmed (#42). Use z.string() to avoid rejecting unseen values.",
|
|
5889
|
+
"description": "Provider-defined event type. Observed: \"transaction.payment\". Full set per provider TBD (#42)."
|
|
5890
|
+
},
|
|
5891
|
+
"status": {
|
|
5892
|
+
"type": "string",
|
|
5893
|
+
"x-note": "Observed values: \"success\", \"error\". Indicates whether the webhook was processed without errors.",
|
|
5894
|
+
"description": "Processing outcome. Observed values: \"success\" | \"error\"."
|
|
5895
|
+
},
|
|
5896
|
+
"verified": {
|
|
5897
|
+
"type": "string",
|
|
5898
|
+
"x-note": "Observed value: \"verified\". Indicates HMAC-SHA256 signature verification result. Full set of failure values unconfirmed (#42).",
|
|
5899
|
+
"description": "Signature verification result. Observed: \"verified\". Other values (e.g. \"unverified\", \"error\") may exist but are unconfirmed."
|
|
5900
|
+
},
|
|
5901
|
+
"endpointStatus": {
|
|
5902
|
+
"type": "string",
|
|
5903
|
+
"x-note": "Observed value: \"matched\". Indicates whether the token resolved to a known PaymentWebhookEndpoint. Other values (e.g. \"not_found\", \"inactive\") unconfirmed (#42).",
|
|
5904
|
+
"description": "Endpoint resolution result. Observed: \"matched\". Other values unconfirmed (#42)."
|
|
5905
|
+
},
|
|
5906
|
+
"processed": {
|
|
5907
|
+
"type": "boolean",
|
|
5908
|
+
"x-note": "Set to true once the delivery has been reconciled to the AppPayment ledger (companies/{cid}/apps/{appId}/payments). Back-reference FK not stored on this doc \u2014 reconciliation is tracked on the AppPayment side.",
|
|
5909
|
+
"description": "Whether this delivery has been reconciled to the AppPayment ledger."
|
|
5910
|
+
},
|
|
5911
|
+
"reference": {
|
|
5912
|
+
"type": "string",
|
|
5913
|
+
"x-note": "Equals payload.id (provider transaction ID). Used as dedup key \u2014 the backend checks this before processing (#42 ask 3).",
|
|
5914
|
+
"description": "Provider transaction ID (= payload.id). Canonical dedup key."
|
|
5915
|
+
},
|
|
5916
|
+
"amount": {
|
|
5917
|
+
"type": "number",
|
|
5918
|
+
"description": "Payment amount, denormalized from payload.amount.amount (XOF)."
|
|
5919
|
+
},
|
|
5920
|
+
"currency": {
|
|
5921
|
+
"type": "string",
|
|
5922
|
+
"description": "Currency code, denormalized from payload.amount.currency (e.g. \"XOF\")."
|
|
5923
|
+
},
|
|
5924
|
+
"payload": {
|
|
5925
|
+
"type": "object",
|
|
5926
|
+
"propertyNames": {
|
|
5927
|
+
"type": "string"
|
|
5928
|
+
},
|
|
5929
|
+
"additionalProperties": {},
|
|
5930
|
+
"x-note": "Parsed provider request body. Contains PII: counterpartIdentifier and counterpartLabel hold customer phone numbers. Retention/TTL policy TBD (#42 ask 5).",
|
|
5931
|
+
"description": "Full parsed provider payload. Shape varies by provider. Contains PII (customer phone). See x-note for retention policy status."
|
|
5932
|
+
},
|
|
5933
|
+
"rawBody": {
|
|
5934
|
+
"type": "string",
|
|
5935
|
+
"x-note": "Verbatim request body string used for HMAC-SHA256 signature verification. Contains same PII as payload. Retention/TTL policy TBD (#42 ask 5).",
|
|
5936
|
+
"description": "Verbatim raw request body \u2014 used for HMAC-SHA256 verification. Contains PII."
|
|
5937
|
+
},
|
|
5938
|
+
"headers": {
|
|
5939
|
+
"x-note": "Request headers including provider signature (e.g. \"jeko-signature\") and tracing headers. Sensitive \u2014 do not expose to clients.",
|
|
5940
|
+
"description": "Incoming HTTP headers. Includes provider signature header and Sentry trace. Sensitive.",
|
|
5941
|
+
"type": [
|
|
5942
|
+
"object",
|
|
5943
|
+
"null"
|
|
5944
|
+
],
|
|
5945
|
+
"propertyNames": {
|
|
5946
|
+
"type": "string"
|
|
5947
|
+
},
|
|
5948
|
+
"additionalProperties": {
|
|
5949
|
+
"type": "string"
|
|
5950
|
+
}
|
|
5951
|
+
},
|
|
5952
|
+
"receivedAt": {
|
|
5953
|
+
"$ref": "#/definitions/firestore-timestamp",
|
|
5954
|
+
"description": "When the webhook delivery was received by the backend."
|
|
5955
|
+
}
|
|
5956
|
+
},
|
|
5957
|
+
"required": [
|
|
5958
|
+
"company",
|
|
5959
|
+
"provider",
|
|
5960
|
+
"eventType",
|
|
5961
|
+
"status",
|
|
5962
|
+
"verified",
|
|
5963
|
+
"endpointStatus",
|
|
5964
|
+
"processed",
|
|
5965
|
+
"reference",
|
|
5966
|
+
"amount",
|
|
5967
|
+
"currency",
|
|
5968
|
+
"payload",
|
|
5969
|
+
"rawBody",
|
|
5970
|
+
"receivedAt"
|
|
5971
|
+
],
|
|
5972
|
+
"additionalProperties": false,
|
|
5973
|
+
"x-internal": true,
|
|
5974
|
+
"description": "PaymentWebhookDelivery (GH#42). Collection: payment_webhooks/{deliveryId} (top-level). One document per received provider callback. Contains raw payload + verification outcome. x-internal: written/read only by backend; dashboard reads via admin UI. PII in payload/rawBody \u2014 retention policy TBD.",
|
|
5975
|
+
"example": {
|
|
5976
|
+
"id": null,
|
|
5977
|
+
"company": "company",
|
|
5978
|
+
"provider": "pro_ref123",
|
|
5979
|
+
"eventType": "eventType",
|
|
5980
|
+
"status": "status",
|
|
5981
|
+
"verified": "verified",
|
|
5982
|
+
"endpointStatus": "endpointStatus",
|
|
5983
|
+
"processed": true,
|
|
5984
|
+
"reference": "reference",
|
|
5985
|
+
"amount": 45000,
|
|
5986
|
+
"currency": "XOF",
|
|
5987
|
+
"payload": {},
|
|
5988
|
+
"rawBody": "rawBody",
|
|
5989
|
+
"headers": null,
|
|
5990
|
+
"receivedAt": "receivedAt"
|
|
5991
|
+
}
|
|
5992
|
+
},
|
|
5634
5993
|
"payment-webhook-endpoint": {
|
|
5635
5994
|
"type": "object",
|
|
5636
5995
|
"properties": {
|
|
@@ -7023,6 +7382,16 @@
|
|
|
7023
7382
|
}
|
|
7024
7383
|
},
|
|
7025
7384
|
"additionalProperties": false
|
|
7385
|
+
},
|
|
7386
|
+
"contactE164": {
|
|
7387
|
+
"readOnly": true,
|
|
7388
|
+
"x-note": "E.164-normalized form of `from` (wa_id). Canonical join key across WhatsappInboundMessage, WhatsappOutboundMessage, and NotificationRecord. Use this for conversation threading, search, and cross-collection joins \u2014 not the raw `from` wa_id (#56).",
|
|
7389
|
+
"x-when": "Populated by whatsapp-server on every new inbound doc. Absent on pre-#56 docs until the backfill migration runs. CI normalization: wa_id 22577471485 \u2192 +2250777471485 (insert trunk 0 after country code for 8-digit numbers in the 07/05/01 series that predate the 2014 10-digit migration).",
|
|
7390
|
+
"description": "(Read-only) E.164-normalized sender phone (e.g. +2250777471485). Canonical join key (#56). Populated by the backend; absent on pre-migration docs.",
|
|
7391
|
+
"type": [
|
|
7392
|
+
"string",
|
|
7393
|
+
"null"
|
|
7394
|
+
]
|
|
7026
7395
|
}
|
|
7027
7396
|
},
|
|
7028
7397
|
"required": [
|
|
@@ -7049,7 +7418,8 @@
|
|
|
7049
7418
|
"mediaId": null,
|
|
7050
7419
|
"caption": null,
|
|
7051
7420
|
"storageUrl": null,
|
|
7052
|
-
"context": null
|
|
7421
|
+
"context": null,
|
|
7422
|
+
"contactE164": null
|
|
7053
7423
|
}
|
|
7054
7424
|
},
|
|
7055
7425
|
"whatsapp-outbound-lifecycle-event": {
|
|
@@ -7285,6 +7655,16 @@
|
|
|
7285
7655
|
"description": "(Immutable) Enqueue timestamp, set by the dashboard at create.",
|
|
7286
7656
|
"x-immutable": true
|
|
7287
7657
|
},
|
|
7658
|
+
"contactE164": {
|
|
7659
|
+
"readOnly": true,
|
|
7660
|
+
"x-note": "E.164-normalized form of `to` (wa_id). Canonical join key across WhatsappOutboundMessage, WhatsappInboundMessage, and NotificationRecord. Use this for conversation threading, search, and cross-collection joins \u2014 not the raw `to` wa_id (#56).",
|
|
7661
|
+
"x-when": "Populated by whatsapp-server on every new outbound doc. Absent on pre-#56 docs until the backfill migration runs. CI normalization: wa_id 22577471485 \u2192 +2250777471485 (insert trunk 0 after country code for 8-digit numbers in the 07/05/01 series that predate the 2014 10-digit migration).",
|
|
7662
|
+
"description": "(Read-only) E.164-normalized recipient phone (e.g. +2250777471485). Canonical join key (#56). Populated by the backend; absent on pre-migration docs.",
|
|
7663
|
+
"type": [
|
|
7664
|
+
"string",
|
|
7665
|
+
"null"
|
|
7666
|
+
]
|
|
7667
|
+
},
|
|
7288
7668
|
"status": {
|
|
7289
7669
|
"$ref": "#/definitions/outbound-message-status",
|
|
7290
7670
|
"description": "Delivery status. Created as `queued` by the dashboard; updated in place by the backend.",
|
|
@@ -7381,6 +7761,7 @@
|
|
|
7381
7761
|
"uid": "user_u8x92kqm"
|
|
7382
7762
|
},
|
|
7383
7763
|
"createdAt": "createdAt",
|
|
7764
|
+
"contactE164": null,
|
|
7384
7765
|
"status": "status",
|
|
7385
7766
|
"wamid": null,
|
|
7386
7767
|
"error": null,
|