@ingenx-io/valets-schema-mcp-server 0.1.1 → 0.1.2
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 +48 -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 +95 -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/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 +1046 -0
- package/data/static/openapi.yaml +3090 -0
- package/data/static/schemas.json +4012 -0
- package/package.json +1 -1
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Loyalty Automation Triggers"
|
|
3
|
+
sidebar_label: "Loyalty Automation"
|
|
4
|
+
sidebar_position: 1
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Loyalty Automation Triggers
|
|
8
|
+
|
|
9
|
+
> **Decision**: D23 (locked) — Firebase owns loyalty point automation: award, expire, and validate server-side.
|
|
10
|
+
> **Wave**: 3 — Server-Side Logic.
|
|
11
|
+
> **Status**: Specified. Not yet implemented.
|
|
12
|
+
|
|
13
|
+
These triggers run when loyalty transactions are written to Firestore. Their job is to keep `loyalty/status` counters consistent and set `pointsBalanceAfter` on each transaction.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## `onLoyaltyTransactionCreate`
|
|
18
|
+
|
|
19
|
+
Fires when a new [`LoyaltyTransaction`](/models/loyalty-transaction) document is created.
|
|
20
|
+
|
|
21
|
+
**Path**: `companies/{companyId}/customers/{customerId}/loyaltyTransactions/{transactionId}`
|
|
22
|
+
**Event**: `onCreate`
|
|
23
|
+
|
|
24
|
+
### Behavior
|
|
25
|
+
|
|
26
|
+
1. Read the new `LoyaltyTransaction` document.
|
|
27
|
+
2. **Atomically** update the `loyalty/status` document at `companies/{companyId}/customers/{customerId}/loyalty/status`:
|
|
28
|
+
|
|
29
|
+
| Transaction type | `pointsBalance` | `totalPointsEarned` | `redeemedPoints` | `lastActivityDate` |
|
|
30
|
+
|---|---|---|---|---|
|
|
31
|
+
| `EARNED` | `+= pointsChange` | `+= pointsChange` | — | set to `changedAt` |
|
|
32
|
+
| `BONUS` | `+= pointsChange` | `+= pointsChange` | — | set to `changedAt` |
|
|
33
|
+
| `REDEEMED` | `-= pointsChange` (subtract abs value) | — | `+= pointsChange` | set to `changedAt` |
|
|
34
|
+
| `ADJUSTED` | `+= pointsChange` (can be negative) | — | — | set to `changedAt` |
|
|
35
|
+
| `EXPIRED` | `-= pointsChange` (subtract abs value) | — | — | set to `changedAt` |
|
|
36
|
+
| `REFUND` | `+= pointsChange` | — | `-= pointsChange` | set to `changedAt` |
|
|
37
|
+
|
|
38
|
+
3. Write `pointsBalanceAfter` back to the transaction document (the running balance **after** this operation).
|
|
39
|
+
4. Create or initialise the `loyalty/status` document if it does not exist.
|
|
40
|
+
|
|
41
|
+
### Inputs
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
// onCreate event data
|
|
45
|
+
interface LoyaltyTransactionCreateEvent {
|
|
46
|
+
data: LoyaltyTransaction; // the new document
|
|
47
|
+
params: {
|
|
48
|
+
companyId: string;
|
|
49
|
+
customerId: string;
|
|
50
|
+
transactionId: string;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Outputs
|
|
56
|
+
|
|
57
|
+
**Write 1** — Update `loyalty/status`:
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
// Partial update applied to: companies/{companyId}/customers/{customerId}/loyalty/status
|
|
61
|
+
{
|
|
62
|
+
pointsBalance: FieldValue.increment(delta), // sign depends on transaction type
|
|
63
|
+
totalPointsEarned: FieldValue.increment(delta), // only for EARNED and BONUS
|
|
64
|
+
redeemedPoints: FieldValue.increment(delta), // only for REDEEMED; decremented for REFUND
|
|
65
|
+
lastActivityDate: FieldValue.serverTimestamp(),
|
|
66
|
+
updatedAt: FieldValue.serverTimestamp(),
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Write 2** — Patch `pointsBalanceAfter` back on the transaction:
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
// Patch applied to: companies/{companyId}/customers/{customerId}/loyaltyTransactions/{transactionId}
|
|
74
|
+
{
|
|
75
|
+
pointsBalanceAfter: <computed new balance>,
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
:::warning Race condition
|
|
80
|
+
Both writes must be in a single **Firestore transaction** (not a batch). Using a transaction on the `loyalty/status` doc prevents two concurrent `onLoyaltyTransactionCreate` calls from producing an incorrect balance.
|
|
81
|
+
:::
|
|
82
|
+
|
|
83
|
+
:::note Welcome bonus
|
|
84
|
+
A `BONUS` transaction with `reason: "welcome_bonus"` is created by the server when a customer first enrolls. The trigger handles it identically to `EARNED`.
|
|
85
|
+
:::
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## `onLoyaltyTransactionUpdate` (admin corrections only)
|
|
90
|
+
|
|
91
|
+
**Path**: `companies/{companyId}/customers/{customerId}/loyaltyTransactions/{transactionId}`
|
|
92
|
+
**Event**: `onUpdate`
|
|
93
|
+
|
|
94
|
+
### Behavior
|
|
95
|
+
|
|
96
|
+
LoyaltyTransaction documents are marked `immutable` — clients must not update them. This trigger exists only to detect accidental or admin-tool writes and **re-heal** the `loyalty/status` balance.
|
|
97
|
+
|
|
98
|
+
1. Compute the delta between the old and new `pointsChange` values.
|
|
99
|
+
2. Apply the delta to `loyalty/status.pointsBalance`.
|
|
100
|
+
3. Log the correction to `_validation_issues` (D36 log-and-heal).
|
|
101
|
+
|
|
102
|
+
:::info Scope
|
|
103
|
+
Only `pointsChange` corrections trigger a re-heal. Status updates or annotation changes are ignored.
|
|
104
|
+
:::
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Points Expiration (scheduled)
|
|
109
|
+
|
|
110
|
+
D23 also requires server-side expiration of stale points. This is a **scheduled Cloud Function** (not a Firestore trigger).
|
|
111
|
+
|
|
112
|
+
**Schedule**: Daily (configurable per company via `LoyaltyConfig.pointsExpirationDays`).
|
|
113
|
+
|
|
114
|
+
### Behavior
|
|
115
|
+
|
|
116
|
+
For each company with `loyaltyConfig.pointsExpirationDays` set:
|
|
117
|
+
1. Query `loyaltyTransactions` where `type = EARNED` and `transactionDate` is older than `pointsExpirationDays`.
|
|
118
|
+
2. For each expiring transaction, create a new `LoyaltyTransaction` with `type = EXPIRED` and `pointsChange = -(originalPointsChange)`.
|
|
119
|
+
3. The `onLoyaltyTransactionCreate` trigger handles the balance update automatically.
|
|
120
|
+
|
|
121
|
+
:::note
|
|
122
|
+
Expiration creates a new EXPIRED transaction rather than mutating the original EARNED transaction. This preserves the immutable audit trail.
|
|
123
|
+
:::
|