@fire-spark/payments 0.3.5 → 0.4.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.
- package/dist/index.d.ts +10 -12
- package/dist/index.js +42 -39
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ type AllocateTenderInput = {
|
|
|
9
9
|
sequence: number;
|
|
10
10
|
method: PaymentMethod;
|
|
11
11
|
allocation: TenderAllocationInput | null;
|
|
12
|
-
/** Value a REDEMPTION tender covers (`details.
|
|
12
|
+
/** Value a REDEMPTION tender covers (`details.amount`). */
|
|
13
13
|
redemption_amount?: number;
|
|
14
14
|
};
|
|
15
15
|
type AllocateTendersInput = {
|
|
@@ -472,16 +472,14 @@ type RedemptionDetails = Extract<TenderDetails, {
|
|
|
472
472
|
/** One reward inside a grouped REDEMPTION tender (entry totals). */
|
|
473
473
|
type RedemptionReward = RedemptionDetails["rewards"][number];
|
|
474
474
|
/**
|
|
475
|
-
* Payment redeem as stored in `orders.redeem`. `amount`
|
|
476
|
-
*
|
|
475
|
+
* Payment redeem as stored in `orders.redeem`. `amount` is the total of
|
|
476
|
+
* the entry (every unit); `quantity` is informational.
|
|
477
477
|
*/
|
|
478
478
|
type PaymentRedeemLike = {
|
|
479
479
|
reward_id: string;
|
|
480
480
|
quantity?: number;
|
|
481
481
|
payment_id?: string | null;
|
|
482
482
|
amount?: number;
|
|
483
|
-
points?: number;
|
|
484
|
-
program?: string;
|
|
485
483
|
};
|
|
486
484
|
/** Payment redeems of one `payment_id`, ready to seed its tender. */
|
|
487
485
|
type RedemptionGroup = {
|
|
@@ -491,7 +489,7 @@ type RedemptionGroup = {
|
|
|
491
489
|
details: RedemptionDetails;
|
|
492
490
|
};
|
|
493
491
|
/**
|
|
494
|
-
*
|
|
492
|
+
* Reward (voucher, balance…) paid with a REDEMPTION tender, not a discount (D16):
|
|
495
493
|
* it never discounts lines nor has a `redemption_steps` entry.
|
|
496
494
|
*/
|
|
497
495
|
declare const isPaymentRedeem: (redeem: {
|
|
@@ -529,16 +527,16 @@ declare const paymentRedeemsCoverTotal: (redeem: readonly PaymentRedeemLike[], t
|
|
|
529
527
|
*/
|
|
530
528
|
declare const groupPaymentRedeems: (redeem: readonly PaymentRedeemLike[]) => RedemptionGroup[];
|
|
531
529
|
/**
|
|
532
|
-
* REDEMPTION `details` in the
|
|
533
|
-
*
|
|
530
|
+
* REDEMPTION `details` in the current shape, or null for other methods.
|
|
531
|
+
* Details persisted earlier (one `reward_id`, or money as `points_value`)
|
|
532
|
+
* read as the same shape; their old keys are dropped.
|
|
534
533
|
*/
|
|
535
534
|
declare const redemptionDetailsOf: (details: unknown) => RedemptionDetails | null;
|
|
536
535
|
/** Rewards of a REDEMPTION tender; empty for other methods. */
|
|
537
536
|
declare const redemptionRewardsOf: (details: unknown) => {
|
|
538
537
|
reward_id: string;
|
|
539
538
|
quantity: number;
|
|
540
|
-
|
|
541
|
-
points_value: number;
|
|
539
|
+
amount: number;
|
|
542
540
|
}[];
|
|
543
541
|
//#endregion
|
|
544
542
|
//#region src/reference.d.ts
|
|
@@ -624,7 +622,7 @@ declare const primaryTender: <T extends TenderLike>(intent: {
|
|
|
624
622
|
primary_tender_id: string | null;
|
|
625
623
|
tenders: readonly T[];
|
|
626
624
|
} | null | undefined) => T | null;
|
|
627
|
-
/** A REDEMPTION tender whose
|
|
625
|
+
/** A REDEMPTION tender whose reward is held for the order (L2 / D30). */
|
|
628
626
|
declare const isRedemptionReserved: (tender: TenderLike) => boolean;
|
|
629
627
|
/** Paid, or a reserved REDEMPTION (confirmed later, §3.3). */
|
|
630
628
|
declare const isTenderSettled: (tender: TenderLike) => boolean;
|
|
@@ -635,7 +633,7 @@ declare const isIntentCovered: (intent: IntentLike | null | undefined, orderTota
|
|
|
635
633
|
/**
|
|
636
634
|
* Order `payment_status` from the live tenders of the current intent
|
|
637
635
|
* (D32). Reserved REDEMPTION tenders count as settled, so a redemption-only
|
|
638
|
-
* intent is `PAID` once its
|
|
636
|
+
* intent is `PAID` once its rewards are held (D30).
|
|
639
637
|
*/
|
|
640
638
|
declare const derivePaymentStatus: (intent: IntentLike | null | undefined) => PaymentStatus;
|
|
641
639
|
/** Live tenders a `PAYING` node waits for (§7.3); no scope = all. */
|
package/dist/index.js
CHANGED
|
@@ -137,7 +137,7 @@ const primaryTender = (intent) => {
|
|
|
137
137
|
const id = intent.primary_tender_id;
|
|
138
138
|
return intent.tenders.find((tender) => tender.id === id) ?? null;
|
|
139
139
|
};
|
|
140
|
-
/** A REDEMPTION tender whose
|
|
140
|
+
/** A REDEMPTION tender whose reward is held for the order (L2 / D30). */
|
|
141
141
|
const isRedemptionReserved = (tender) => {
|
|
142
142
|
if (isRealPaymentMethod(tender.method)) return false;
|
|
143
143
|
return typeof tender.metadata?.reserved_at === "string";
|
|
@@ -167,7 +167,7 @@ const isIntentCovered = (intent, orderTotal) => {
|
|
|
167
167
|
/**
|
|
168
168
|
* Order `payment_status` from the live tenders of the current intent
|
|
169
169
|
* (D32). Reserved REDEMPTION tenders count as settled, so a redemption-only
|
|
170
|
-
* intent is `PAID` once its
|
|
170
|
+
* intent is `PAID` once its rewards are held (D30).
|
|
171
171
|
*/
|
|
172
172
|
const derivePaymentStatus = (intent) => {
|
|
173
173
|
const tenders = liveTenders(intent);
|
|
@@ -1174,7 +1174,7 @@ const batchCloseDay = (now) => localDay(now);
|
|
|
1174
1174
|
const SUM_DECIMALS = 6;
|
|
1175
1175
|
const add = (a, b) => roundTo(a + b, SUM_DECIMALS);
|
|
1176
1176
|
/**
|
|
1177
|
-
*
|
|
1177
|
+
* Reward (voucher, balance…) paid with a REDEMPTION tender, not a discount (D16):
|
|
1178
1178
|
* it never discounts lines nor has a `redemption_steps` entry.
|
|
1179
1179
|
*/
|
|
1180
1180
|
const isPaymentRedeem = (redeem) => {
|
|
@@ -1206,32 +1206,22 @@ const paymentRedeemsCoverTotal = (redeem, totals) => {
|
|
|
1206
1206
|
return roundTo(paid, decimals) >= roundTo(totals.total, decimals);
|
|
1207
1207
|
};
|
|
1208
1208
|
const rewardOf = (redeem) => {
|
|
1209
|
-
const r1 = {
|
|
1210
|
-
reward_id: redeem.reward_id,
|
|
1211
|
-
quantity: redeem.quantity ?? 1
|
|
1212
|
-
};
|
|
1213
|
-
const r2 = {
|
|
1214
|
-
points: redeem.points ?? 0,
|
|
1215
|
-
points_value: redeem.amount ?? 0
|
|
1216
|
-
};
|
|
1217
1209
|
return {
|
|
1218
|
-
|
|
1219
|
-
|
|
1210
|
+
reward_id: redeem.reward_id,
|
|
1211
|
+
quantity: redeem.quantity ?? 1,
|
|
1212
|
+
amount: redeem.amount ?? 0
|
|
1220
1213
|
};
|
|
1221
1214
|
};
|
|
1222
|
-
const detailsOf = (rewards,
|
|
1215
|
+
const detailsOf = (rewards, loyalty_transaction_id) => {
|
|
1223
1216
|
const d1 = {
|
|
1224
1217
|
method: REDEMPTION_METHOD,
|
|
1225
1218
|
rewards,
|
|
1226
|
-
|
|
1227
|
-
points_value: rewards.reduce((sum, item) => add(sum, item.points_value), 0)
|
|
1219
|
+
amount: rewards.reduce((sum, item) => add(sum, item.amount), 0)
|
|
1228
1220
|
};
|
|
1229
|
-
const d2 =
|
|
1230
|
-
const d3 = loyalty_transaction_id ? { loyalty_transaction_id } : {};
|
|
1221
|
+
const d2 = loyalty_transaction_id ? { loyalty_transaction_id } : {};
|
|
1231
1222
|
return {
|
|
1232
1223
|
...d1,
|
|
1233
|
-
...d2
|
|
1234
|
-
...d3
|
|
1224
|
+
...d2
|
|
1235
1225
|
};
|
|
1236
1226
|
};
|
|
1237
1227
|
/**
|
|
@@ -1248,11 +1238,10 @@ const groupPaymentRedeems = (redeem) => {
|
|
|
1248
1238
|
groups.set(payment_id, list);
|
|
1249
1239
|
}
|
|
1250
1240
|
return [...groups].map(([payment_id, items]) => {
|
|
1251
|
-
const
|
|
1252
|
-
const details = detailsOf(items.map(rewardOf), program);
|
|
1241
|
+
const details = detailsOf(items.map(rewardOf));
|
|
1253
1242
|
return {
|
|
1254
1243
|
payment_id,
|
|
1255
|
-
amount: details.
|
|
1244
|
+
amount: details.amount,
|
|
1256
1245
|
details
|
|
1257
1246
|
};
|
|
1258
1247
|
});
|
|
@@ -1260,27 +1249,41 @@ const groupPaymentRedeems = (redeem) => {
|
|
|
1260
1249
|
const isRecord = (value) => {
|
|
1261
1250
|
return typeof value === "object" && value !== null;
|
|
1262
1251
|
};
|
|
1252
|
+
const numberOr = (value, fallback) => {
|
|
1253
|
+
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
1254
|
+
};
|
|
1255
|
+
/** Money of a persisted reward: `amount`, or `points_value` before it. */
|
|
1256
|
+
const rewardAmountOf = (reward) => {
|
|
1257
|
+
return numberOr(reward.amount, numberOr(reward.points_value, 0));
|
|
1258
|
+
};
|
|
1259
|
+
const persistedRewardOf = (value) => {
|
|
1260
|
+
if (!isRecord(value) || typeof value.reward_id !== "string") return null;
|
|
1261
|
+
const quantity = numberOr(value.quantity, 1);
|
|
1262
|
+
return {
|
|
1263
|
+
reward_id: value.reward_id,
|
|
1264
|
+
quantity,
|
|
1265
|
+
amount: rewardAmountOf(value)
|
|
1266
|
+
};
|
|
1267
|
+
};
|
|
1263
1268
|
/**
|
|
1264
|
-
* REDEMPTION `details` in the
|
|
1265
|
-
*
|
|
1269
|
+
* REDEMPTION `details` in the current shape, or null for other methods.
|
|
1270
|
+
* Details persisted earlier (one `reward_id`, or money as `points_value`)
|
|
1271
|
+
* read as the same shape; their old keys are dropped.
|
|
1266
1272
|
*/
|
|
1267
1273
|
const redemptionDetailsOf = (details) => {
|
|
1268
1274
|
if (!isRecord(details) || details.method !== "REDEMPTION") return null;
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1275
|
+
const id = details.loyalty_transaction_id;
|
|
1276
|
+
const reference = typeof id === "string" ? id : void 0;
|
|
1277
|
+
if (Array.isArray(details.rewards)) {
|
|
1278
|
+
const rewards = details.rewards.map(persistedRewardOf);
|
|
1279
|
+
if (rewards.some((reward) => reward === null)) return null;
|
|
1280
|
+
return detailsOf(rewards, reference);
|
|
1281
|
+
}
|
|
1282
|
+
const reward = persistedRewardOf({
|
|
1283
|
+
...details,
|
|
1274
1284
|
quantity: 1
|
|
1275
|
-
};
|
|
1276
|
-
|
|
1277
|
-
const reward = {
|
|
1278
|
-
...r1,
|
|
1279
|
-
...r2,
|
|
1280
|
-
points_value: legacy.points_value ?? 0
|
|
1281
|
-
};
|
|
1282
|
-
const id = legacy.loyalty_transaction_id;
|
|
1283
|
-
return detailsOf([reward], legacy.program, id);
|
|
1285
|
+
});
|
|
1286
|
+
return reward ? detailsOf([reward], reference) : null;
|
|
1284
1287
|
};
|
|
1285
1288
|
/** Rewards of a REDEMPTION tender; empty for other methods. */
|
|
1286
1289
|
const redemptionRewardsOf = (details) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fire-spark/payments",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Fire Spark payments contract: adapters, errors, amounts and policy",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@fire-spark/types": "^0.
|
|
20
|
+
"@fire-spark/types": "^0.4.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"tsdown": "^0.22.14",
|