@lucaapp/service-utils 5.15.0 → 5.16.0

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.
@@ -6,6 +6,7 @@ export type OperatorDevice = {
6
6
  role: OperatorDeviceRole;
7
7
  operatorId: string;
8
8
  locationId: string | null;
9
+ terminalId: string | null;
9
10
  createdAt: Date;
10
11
  updatedAt: Date;
11
12
  };
@@ -1,205 +1,90 @@
1
1
  import { SupportedCurrencies } from '../../money/supportedCurrencies';
2
- /**
3
- * JSON-serialisable value tree.
4
- *
5
- * Used for opaque payloads carried across the wire. Anything stored here
6
- * must round-trip through `JSON.stringify` / `JSON.parse` without loss.
7
- */
8
2
  export type JsonValue = string | number | boolean | null | JsonValue[] | {
9
3
  [key: string]: JsonValue;
10
4
  };
11
- /** Legacy 3-letter terminal status code from the original payment provider integration. */
12
5
  export type RapydPaymentStatus = 'ACT' | 'CAN' | 'CLO' | 'ERR' | 'EXP' | 'NEW' | 'REV';
13
- /** Provider-neutral payment lifecycle status. */
14
6
  export type PaymentStatus = 'PAID' | 'NEW' | 'ACTIVE' | 'CANCELLED' | 'EXPIRED' | 'REFUNDED' | 'ERROR' | 'UNKNOWN';
15
- /**
16
- * Lifecycle timestamps shared by all payment events.
17
- *
18
- * Each timestamp marks the first time the payment entered the corresponding
19
- * state. A null value means the state was never reached.
20
- */
21
7
  export type PaymentStatusTimings = {
22
- /** Timestamp when the payment record was created (session start, NOT settlement). */
23
8
  paymentCreatedAt: Date;
24
- /** Payment record created; awaiting consumer action (e.g. order created, link sent, QR displayed). */
25
9
  statusNewAt: Date | null;
26
- /** Consumer engaged with the payment flow (e.g. opened a 3DS challenge, tapped a terminal, clicked the payment link). */
27
10
  statusActiveAt: Date | null;
28
- /** Provider authorised and captured the funds (online auth + capture or terminal sale complete). */
29
11
  statusCompleteAt?: Date | null;
30
- /** Cancelled by consumer or operator before completion. */
31
12
  statusCanceledAt: Date | null;
32
- /** Payment session expired before completion. */
33
13
  statusExpiredAt: Date | null;
34
- /** Provider returned an error or refused the payment. */
35
14
  statusErrorAt: Date | null;
36
- /** Authorised payment was reversed before settlement (e.g. chargeback pre-arbitration). */
37
15
  statusReversedAt?: Date | null;
38
- /** Projected or actual settlement date to the merchant balance. Null until the provider schedules settlement. */
39
16
  settleAt?: Date | null;
40
17
  };
41
- /** Fields shared by both the legacy {@link Payment} event and the provider-neutral {@link PaymentEvent}. */
42
18
  export type PaymentBase = {
43
- /** Stable payment id. Uniquely identifies the payment across all systems. */
44
19
  uuid: string;
45
- /** Merchant location id (UUID). */
46
20
  locationId: string;
47
- /** Human-readable location name. Null when not provided. */
48
21
  locationName: string | null;
49
- /** Table or seat identifier from the POS. Null for non-dine-in payments. */
50
22
  table: string | null;
51
- /** Pre-created payment-request id. Null for spontaneous payments. */
52
23
  paymentRequestId: string | null;
53
- /** Short verifier token used by consumer-facing flows to prove ownership of the payment session. */
54
24
  paymentVerifier: string;
55
- /** Net goods/services amount before tip, in the smallest currency subunit. */
56
25
  invoiceAmount: number;
57
- /** Consumer-added gratuity, in the smallest currency subunit. Zero when no tip was given. */
58
26
  tipAmount: number;
59
27
  } & PaymentStatusTimings;
60
- /**
61
- * Legacy payment event tied to the original provider integration.
62
- *
63
- * Kept for backward compatibility. New consumers should subscribe to
64
- * {@link PaymentEvent}.
65
- */
28
+ export declare const PAYMENT_LEGACY_VERSION = 1;
29
+ export type PaymentLegacyVersion = typeof PAYMENT_LEGACY_VERSION;
66
30
  export type Payment = PaymentBase & {
67
- /** Total paid by the consumer (= `invoiceAmount + tipAmount`), in the smallest currency subunit. Kept for legacy consumers. */
31
+ version: PaymentLegacyVersion;
68
32
  totalAmount: number;
69
- /** Timestamp when the payment was marked paid. */
70
33
  paidAt: Date | null;
71
- /** @deprecated Legacy terminal "CLO" state. Use `statusCompleteAt`. */
72
34
  statusClosedAt: Date | null;
73
- /** Fixed processing fee, in the smallest currency subunit. */
74
35
  fixedFee: number;
75
- /** Variable fee (commission + markup), in the smallest currency subunit. */
76
36
  variableFee: number;
77
- /** Legacy provider payment id. */
78
37
  rapydPaymentId: string | null;
79
- /** Legacy provider error code on failure. */
80
38
  rapydErrorCode: string | null;
81
- /** Legacy provider error message on failure. */
82
39
  rapydErrorMessage: string | null;
83
- /** Legacy 3-letter status code from the provider. */
84
40
  rapydPaymentStatus: RapydPaymentStatus;
85
- /** Legacy provider customer / saved-card alias. */
86
41
  rapydCustomerId: string | null;
87
- /** Aggregated payout batch id. Null until the payment is included in a payout. */
88
42
  payoutId: string | null;
89
43
  };
90
- /**
91
- * Provider-neutral payment lifecycle event.
92
- *
93
- * Carries the full domain context needed for fiscalisation, receipt
94
- * rendering, and downstream reconciliation. Wire format is JSON: monetary
95
- * fields are integers in the smallest currency subunit and `currency`
96
- * declares the unit.
97
- */
44
+ export declare const PAYMENT_EVENT_VERSION = 2;
45
+ export type PaymentEventVersion = typeof PAYMENT_EVENT_VERSION;
98
46
  export type PaymentEvent = PaymentBase & {
99
- /** Checkout session id. Optional — some flows emit payment events without a checkout. */
47
+ version: PaymentEventVersion;
100
48
  checkoutId?: string;
101
- /** Order id (e.g. POS / fiscalisation order reference). Absent for payments not tied to an order. */
102
49
  orderId?: string;
103
- /** Operator-added service charge / convenience fee, in the smallest currency subunit. Zero if none. */
104
50
  surchargeAmount: number;
105
- /** ISO 4217 code that applies to every monetary field on this event. Single-currency invariant. */
106
51
  currency: SupportedCurrencies;
107
- /** Lifecycle status at event-emission time. */
108
52
  status: PaymentStatus;
109
- /** Method identifier, e.g. `'CARD'`, `'CASH'`, `'WALLET'`. */
110
53
  method: string;
111
- /** True if `method` is a cash variant. Cash flows skip provider webhooks and short-circuit fiscalisation. */
112
54
  isCash: boolean;
113
- /** Origin service identifier (free-form short string). */
114
55
  source: string;
115
- /** Aggregated payout batch id. Null until included in a payout. */
116
56
  payoutId?: string | null;
117
- /** Provider-side identifiers, errors, and raw provider payload. Absent for cash. */
118
57
  merchantDetails?: PaymentMerchantDetails;
119
- /** Card-specific identifiers and terminal context. Absent for non-card methods. */
120
58
  cardDetails?: PaymentCardDetails;
121
- /** Per-item breakdown for fiscalisation and receipt rendering. */
122
59
  lineItems?: PaymentEventLineItem[];
123
60
  };
124
- /** Amount the consumer actually pays = `invoiceAmount + tipAmount + surchargeAmount` (smallest currency subunit). */
125
61
  export declare const consumerPayAmount: (event: PaymentEvent) => number;
126
- /**
127
- * Amount receivable by the operator before Luca / provider fees are
128
- * deducted = `invoiceAmount + tipAmount` (smallest currency subunit).
129
- *
130
- * Surcharge is excluded — it covers the consumer-side fee, not operator
131
- * revenue. Net payout to the operator is this minus the per-payment fees.
132
- */
133
62
  export declare const operatorReceivableAmount: (event: PaymentEvent) => number;
134
- /**
135
- * Provider-side metadata for a payment.
136
- *
137
- * All fields optional — populated by whichever provider handled the
138
- * payment. Absent on cash and other non-provider flows.
139
- */
140
63
  export type PaymentMerchantDetails = {
141
- /** Payment-processor identifier (lowercase short string). Null when not yet routed to a provider. */
142
64
  provider?: string | null;
143
- /** Provider's payment id. Null until the provider authorises. */
144
65
  providerIdentifier?: string | null;
145
- /** Machine-readable error / decline code from the provider. Null on success. */
146
66
  providerErrorCode?: string | null;
147
- /** Human-readable provider error detail. Null on success. */
148
67
  providerErrorMessage?: string | null;
149
- /** Raw provider payload (notification or response body). Used for audits and chargeback evidence. */
150
68
  providerData?: {
151
69
  [key: string]: JsonValue;
152
70
  } | null;
153
- /** Provider-facing merchant reference used to reconcile internal records against the provider's records. */
154
71
  externalReference?: string | null;
155
72
  };
156
- /**
157
- * Card and terminal context.
158
- *
159
- * Card fields populated for card payments; terminal/consumer fields
160
- * populated when applicable, regardless of card vs. wallet.
161
- */
162
73
  export type PaymentCardDetails = {
163
- /** Last 4 digits of the card. Null for non-card methods. */
164
74
  last4?: string | null;
165
- /** Provider authorisation code. Null until authorised. */
166
75
  authCode?: string | null;
167
- /** Saved-card alias for tokenised cards. Null for one-time payments. */
168
76
  consumerAlias?: string | null;
169
- /** Physical terminal id. Null for online / QR payments. */
170
77
  terminalId?: string | null;
171
- /** Consumer account id. Null for anonymous payments. */
172
78
  consumerId?: string | null;
173
79
  };
174
- /**
175
- * One billable line in the order, used for fiscalisation and receipt
176
- * rendering.
177
- *
178
- * Sub-items represent components of a parent line (e.g. base drink + paid
179
- * topping) and follow the same shape recursively. Amounts are integers in
180
- * the smallest currency subunit.
181
- */
182
80
  export type PaymentEventLineItem = {
183
- /** Stable line-item id. Omitted on synthetic sub-items that have no own row. */
184
81
  uuid?: string;
185
- /** POS-system menu item / SKU id. Null when not synced from the POS menu. */
186
82
  posItemId?: string | null;
187
- /** Display name (e.g. `'Espresso'`). May be omitted when the consumer can resolve it from `posItemId`. */
188
83
  name?: string;
189
- /** Number of units, e.g. `2` for two coffees. */
190
84
  quantity: number;
191
- /** Price for one unit, in the smallest currency subunit. */
192
85
  pricePerUnit: number;
193
- /** `quantity × pricePerUnit + Σ subItems.totalPrice`, in the smallest currency subunit. */
194
86
  totalPrice: number;
195
- /**
196
- * VAT / sales-tax rate as a percentage value (e.g. `19` for 19%, `7` for
197
- * 7%). NOT a decimal fraction — `0.19` would mean 0.19%. Null if
198
- * tax-exempt or unknown.
199
- */
200
87
  taxPercentage?: number | null;
201
- /** Item currency. Typically equals the parent payment currency. */
202
88
  currency: SupportedCurrencies;
203
- /** Recursive components of this line. Each sub-item follows the same shape. */
204
89
  subItems?: PaymentEventLineItem[];
205
90
  };
@@ -1,15 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.operatorReceivableAmount = exports.consumerPayAmount = void 0;
4
- /** Amount the consumer actually pays = `invoiceAmount + tipAmount + surchargeAmount` (smallest currency subunit). */
3
+ exports.operatorReceivableAmount = exports.consumerPayAmount = exports.PAYMENT_EVENT_VERSION = exports.PAYMENT_LEGACY_VERSION = void 0;
4
+ exports.PAYMENT_LEGACY_VERSION = 1;
5
+ exports.PAYMENT_EVENT_VERSION = 2;
5
6
  const consumerPayAmount = (event) => event.invoiceAmount + event.tipAmount + event.surchargeAmount;
6
7
  exports.consumerPayAmount = consumerPayAmount;
7
- /**
8
- * Amount receivable by the operator before Luca / provider fees are
9
- * deducted = `invoiceAmount + tipAmount` (smallest currency subunit).
10
- *
11
- * Surcharge is excluded — it covers the consumer-side fee, not operator
12
- * revenue. Net payout to the operator is this minus the per-payment fees.
13
- */
14
8
  const operatorReceivableAmount = (event) => event.invoiceAmount + event.tipAmount;
15
9
  exports.operatorReceivableAmount = operatorReceivableAmount;
@@ -1,4 +1,4 @@
1
- import type { Payment } from './events/payment';
1
+ import type { Payment, PaymentEvent } from './events/payment';
2
2
  import type { Consumer } from './events/consumer';
3
3
  import type { Operator } from './events/operator';
4
4
  import type { LocationGroupEmployees } from './events/locationGroupEmployees';
@@ -39,7 +39,7 @@ declare enum KafkaTopic {
39
39
  TOKENIZATION_JOB_ITEM = "tokenization_job_item"
40
40
  }
41
41
  type MessageFormats = {
42
- [KafkaTopic.PAYMENTS]: Payment;
42
+ [KafkaTopic.PAYMENTS]: Payment | PaymentEvent;
43
43
  [KafkaTopic.CONSUMERS]: Consumer;
44
44
  [KafkaTopic.OPERATORS]: Operator;
45
45
  [KafkaTopic.OPERATORS_PAY]: OperatorPay;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lucaapp/service-utils",
3
- "version": "5.15.0",
3
+ "version": "5.16.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [
@@ -86,7 +86,7 @@
86
86
  "resolutions": {
87
87
  "tar": "^7.5.11",
88
88
  "lodash": "^4.18.1",
89
- "qs": "^6.14.2",
89
+ "qs": "6.15.2",
90
90
  "dottie": "2.0.7",
91
91
  "fast-xml-parser": "^5.7.1",
92
92
  "yaml": "^2.8.3",
@@ -100,6 +100,7 @@
100
100
  "axios": "1.16.0",
101
101
  "path-to-regexp": "0.1.13",
102
102
  "ip-address": "10.1.1",
103
- "fast-xml-builder": "^1.1.7"
103
+ "fast-xml-builder": "^1.1.7",
104
+ "brace-expansion": "2.0.3"
104
105
  }
105
106
  }