@voyant-travel/finance 0.137.4 → 0.137.6
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.
|
@@ -20,6 +20,8 @@ export interface EnsureOrderSessionParams {
|
|
|
20
20
|
payerName?: string | null;
|
|
21
21
|
/** Human summary surfaced as `payment_sessions.notes`. */
|
|
22
22
|
notes?: string | null;
|
|
23
|
+
/** Payment method to stamp on a newly-created session, when known. */
|
|
24
|
+
paymentMethod?: CreatePaymentSessionInput["paymentMethod"] | null;
|
|
23
25
|
}
|
|
24
26
|
/**
|
|
25
27
|
* Best-effort provider start hook. Called after a session is created so the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"order-payment-sessions.d.ts","sourceRoot":"","sources":["../src/order-payment-sessions.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAExF,2EAA2E;AAC3E,MAAM,MAAM,6BAA6B,GAAG,yBAAyB,CAAC,YAAY,CAAC,CAAA;AAEnF,wDAAwD;AACxD,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,kFAAkF;AAClF,MAAM,WAAW,wBAAwB;IACvC,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAA;IAChB,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAA;IAChB,2EAA2E;IAC3E,WAAW,EAAE,MAAM,CAAA;IACnB,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"order-payment-sessions.d.ts","sourceRoot":"","sources":["../src/order-payment-sessions.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAExF,2EAA2E;AAC3E,MAAM,MAAM,6BAA6B,GAAG,yBAAyB,CAAC,YAAY,CAAC,CAAA;AAEnF,wDAAwD;AACxD,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,kFAAkF;AAClF,MAAM,WAAW,wBAAwB;IACvC,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAA;IAChB,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAA;IAChB,2EAA2E;IAC3E,WAAW,EAAE,MAAM,CAAA;IACnB,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,sEAAsE;IACtE,aAAa,CAAC,EAAE,yBAAyB,CAAC,eAAe,CAAC,GAAG,IAAI,CAAA;CAClE;AAED;;;;GAIG;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,EAAE,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAOpG,MAAM,WAAW,oBAAoB;IACnC;;;;;;;OAOG;IACH,aAAa,CACX,EAAE,EAAE,kBAAkB,EACtB,MAAM,EAAE,wBAAwB,EAChC,aAAa,CAAC,EAAE,yBAAyB,GACxC,OAAO,CAAC,0BAA0B,GAAG,IAAI,CAAC,CAAA;IAC7C;;;;OAIG;IACH,aAAa,CACX,EAAE,EAAE,kBAAkB,EACtB,SAAS,EAAE,MAAM,EAAE,GAClB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC,CAAA;CACpD;AAED,MAAM,WAAW,iCAAiC;IAChD,mFAAmF;IACnF,UAAU,EAAE,6BAA6B,CAAA;IACzC;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB;;;OAGG;IACH,aAAa,CAAC,EAAE,yBAAyB,CAAC,eAAe,CAAC,GAAG,IAAI,CAAA;CAClE;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,iCAAiC,GACzC,oBAAoB,CAuFtB"}
|
|
@@ -50,7 +50,7 @@ export function createOrderPaymentSessions(options) {
|
|
|
50
50
|
amountCents: params.amountCents,
|
|
51
51
|
status: "pending",
|
|
52
52
|
provider,
|
|
53
|
-
paymentMethod,
|
|
53
|
+
paymentMethod: params.paymentMethod ?? paymentMethod,
|
|
54
54
|
payerEmail: params.payerEmail ?? null,
|
|
55
55
|
payerName: params.payerName ?? null,
|
|
56
56
|
notes: params.notes ?? null,
|
package/dist/payment-policy.d.ts
CHANGED
|
@@ -49,6 +49,7 @@ export interface PaymentPolicy {
|
|
|
49
49
|
/** Default policy: 100% up-front, no deposit. Safe fallback for
|
|
50
50
|
* agencies that haven't configured anything yet. */
|
|
51
51
|
export declare const noDepositPolicy: PaymentPolicy;
|
|
52
|
+
export declare function isPaymentPolicy(value: unknown): value is PaymentPolicy;
|
|
52
53
|
export type PaymentScheduleEntryType = "deposit" | "balance" | "full";
|
|
53
54
|
export interface ComputedScheduleEntry {
|
|
54
55
|
scheduleType: PaymentScheduleEntryType;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payment-policy.d.ts","sourceRoot":"","sources":["../src/payment-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,SAAS,GAAG,aAAa,CAAA;AAE5D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,WAAW,CAAA;IACjB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,WAAW,CAAA;IACpB;gEAC4D;IAC5D,gCAAgC,EAAE,MAAM,CAAA;IACxC,uDAAuD;IACvD,6BAA6B,EAAE,MAAM,CAAA;IACrC;;+DAE2D;IAC3D,wBAAwB,EAAE,MAAM,CAAA;CACjC;AAED;qDACqD;AACrD,eAAO,MAAM,eAAe,EAAE,aAK7B,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,CAAA;AAErE,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,wBAAwB,CAAA;IACtC,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,wBAAwB;IACxB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,wEAAwE;IACxE,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;IACxC,oEAAoE;IACpE,KAAK,CAAC,EAAE,IAAI,CAAA;CACb;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,oBAAoB,EAC3B,MAAM,EAAE,aAAa,GACpB,qBAAqB,EAAE,
|
|
1
|
+
{"version":3,"file":"payment-policy.d.ts","sourceRoot":"","sources":["../src/payment-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,SAAS,GAAG,aAAa,CAAA;AAE5D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,WAAW,CAAA;IACjB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,WAAW,CAAA;IACpB;gEAC4D;IAC5D,gCAAgC,EAAE,MAAM,CAAA;IACxC,uDAAuD;IACvD,6BAA6B,EAAE,MAAM,CAAA;IACrC;;+DAE2D;IAC3D,wBAAwB,EAAE,MAAM,CAAA;CACjC;AAED;qDACqD;AACrD,eAAO,MAAM,eAAe,EAAE,aAK7B,CAAA;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAStE;AAmBD,MAAM,MAAM,wBAAwB,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,CAAA;AAErE,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,wBAAwB,CAAA;IACtC,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,wBAAwB;IACxB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,wEAAwE;IACxE,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;IACxC,oEAAoE;IACpE,KAAK,CAAC,EAAE,IAAI,CAAA;CACb;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,oBAAoB,EAC3B,MAAM,EAAE,aAAa,GACpB,qBAAqB,EAAE,CA+DzB;AAaD,8DAA8D;AAC9D,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAgBtF;AAED,MAAM,MAAM,mBAAmB,GAC3B,SAAS,GACT,SAAS,GACT,UAAU,GACV,UAAU,GACV,kBAAkB,CAAA;AAEtB,MAAM,WAAW,0BAA0B;IACzC,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI,CAAA;IACpC,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI,CAAA;IACpC,cAAc,CAAC,EAAE,aAAa,GAAG,IAAI,CAAA;IACrC,cAAc,CAAC,EAAE,aAAa,GAAG,IAAI,CAAA;IACrC,eAAe,EAAE,aAAa,CAAA;CAC/B;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,aAAa,CAAA;IACrB,MAAM,EAAE,mBAAmB,CAAA;CAC5B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,0BAA0B,GACjC,qBAAqB,CAevB;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,aAAa,EACrB,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACxC,KAAK,GAAE,IAAiB,GACvB,OAAO,CAMT"}
|
package/dist/payment-policy.js
CHANGED
|
@@ -34,6 +34,32 @@ export const noDepositPolicy = {
|
|
|
34
34
|
balanceDueDaysBeforeDeparture: 0,
|
|
35
35
|
balanceDueMinDaysFromNow: 0,
|
|
36
36
|
};
|
|
37
|
+
export function isPaymentPolicy(value) {
|
|
38
|
+
if (!value || typeof value !== "object")
|
|
39
|
+
return false;
|
|
40
|
+
const policy = value;
|
|
41
|
+
return (isDepositRule(policy.deposit) &&
|
|
42
|
+
isNonNegativeInteger(policy.minDaysBeforeDepartureForDeposit) &&
|
|
43
|
+
isNonNegativeInteger(policy.balanceDueDaysBeforeDeparture) &&
|
|
44
|
+
isNonNegativeInteger(policy.balanceDueMinDaysFromNow));
|
|
45
|
+
}
|
|
46
|
+
function isDepositRule(value) {
|
|
47
|
+
if (!value || typeof value !== "object")
|
|
48
|
+
return false;
|
|
49
|
+
const rule = value;
|
|
50
|
+
if (rule.kind === "none")
|
|
51
|
+
return true;
|
|
52
|
+
if (rule.kind === "percent") {
|
|
53
|
+
return typeof rule.percent === "number" && rule.percent >= 0 && rule.percent <= 100;
|
|
54
|
+
}
|
|
55
|
+
if (rule.kind === "fixed_cents") {
|
|
56
|
+
return isNonNegativeInteger(rule.amountCents);
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
function isNonNegativeInteger(value) {
|
|
61
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 0;
|
|
62
|
+
}
|
|
37
63
|
/**
|
|
38
64
|
* Compute the customer-facing payment schedule for a booking.
|
|
39
65
|
*
|
|
@@ -42,13 +68,14 @@ export const noDepositPolicy = {
|
|
|
42
68
|
* scheduled for today.
|
|
43
69
|
*/
|
|
44
70
|
export function computePaymentSchedule(input, policy) {
|
|
71
|
+
const effectivePolicy = isPaymentPolicy(policy) ? policy : noDepositPolicy;
|
|
45
72
|
const total = Math.max(0, Math.round(input.totalCents));
|
|
46
73
|
const today = input.today ?? new Date();
|
|
47
74
|
const todayIso = isoDate(today);
|
|
48
75
|
if (total === 0) {
|
|
49
76
|
return [{ scheduleType: "full", amountCents: 0, currency: input.currency, dueDate: todayIso }];
|
|
50
77
|
}
|
|
51
|
-
if (
|
|
78
|
+
if (effectivePolicy.deposit.kind === "none") {
|
|
52
79
|
return [
|
|
53
80
|
{ scheduleType: "full", amountCents: total, currency: input.currency, dueDate: todayIso },
|
|
54
81
|
];
|
|
@@ -63,12 +90,12 @@ export function computePaymentSchedule(input, policy) {
|
|
|
63
90
|
];
|
|
64
91
|
}
|
|
65
92
|
const daysUntilDeparture = wholeDaysBetween(today, departure);
|
|
66
|
-
if (daysUntilDeparture <
|
|
93
|
+
if (daysUntilDeparture < effectivePolicy.minDaysBeforeDepartureForDeposit) {
|
|
67
94
|
return [
|
|
68
95
|
{ scheduleType: "full", amountCents: total, currency: input.currency, dueDate: todayIso },
|
|
69
96
|
];
|
|
70
97
|
}
|
|
71
|
-
const depositCents = clampCents(computeDepositCents(total,
|
|
98
|
+
const depositCents = clampCents(computeDepositCents(total, effectivePolicy.deposit), 0, total);
|
|
72
99
|
const balanceCents = total - depositCents;
|
|
73
100
|
if (depositCents <= 0 || balanceCents <= 0) {
|
|
74
101
|
// Edge: a policy that resolves to 0% deposit or 100% deposit
|
|
@@ -78,8 +105,8 @@ export function computePaymentSchedule(input, policy) {
|
|
|
78
105
|
{ scheduleType: "full", amountCents: total, currency: input.currency, dueDate: todayIso },
|
|
79
106
|
];
|
|
80
107
|
}
|
|
81
|
-
const rawBalanceDue = addDays(departure, -
|
|
82
|
-
const earliestBalanceDue = addDays(today,
|
|
108
|
+
const rawBalanceDue = addDays(departure, -effectivePolicy.balanceDueDaysBeforeDeparture);
|
|
109
|
+
const earliestBalanceDue = addDays(today, effectivePolicy.balanceDueMinDaysFromNow);
|
|
83
110
|
const balanceDue = rawBalanceDue.getTime() > earliestBalanceDue.getTime() ? rawBalanceDue : earliestBalanceDue;
|
|
84
111
|
return [
|
|
85
112
|
{
|
|
@@ -108,7 +135,7 @@ function computeDepositCents(total, rule) {
|
|
|
108
135
|
}
|
|
109
136
|
/** True when this policy is empty / "inherit from parent". */
|
|
110
137
|
export function isPaymentPolicyEmpty(policy) {
|
|
111
|
-
if (!policy)
|
|
138
|
+
if (!isPaymentPolicy(policy))
|
|
112
139
|
return true;
|
|
113
140
|
if (policy.deposit.kind === "none")
|
|
114
141
|
return true;
|
|
@@ -139,15 +166,20 @@ export function isPaymentPolicyEmpty(policy) {
|
|
|
139
166
|
* proves useful.
|
|
140
167
|
*/
|
|
141
168
|
export function resolveEffectivePaymentPolicy(layers) {
|
|
142
|
-
if (layers.bookingPolicy)
|
|
169
|
+
if (isPaymentPolicy(layers.bookingPolicy))
|
|
143
170
|
return { policy: layers.bookingPolicy, source: "booking" };
|
|
144
|
-
if (layers.listingPolicy)
|
|
171
|
+
if (isPaymentPolicy(layers.listingPolicy))
|
|
145
172
|
return { policy: layers.listingPolicy, source: "listing" };
|
|
146
|
-
if (layers.categoryPolicy)
|
|
173
|
+
if (isPaymentPolicy(layers.categoryPolicy)) {
|
|
147
174
|
return { policy: layers.categoryPolicy, source: "category" };
|
|
148
|
-
|
|
175
|
+
}
|
|
176
|
+
if (isPaymentPolicy(layers.supplierPolicy)) {
|
|
149
177
|
return { policy: layers.supplierPolicy, source: "supplier" };
|
|
150
|
-
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
policy: isPaymentPolicy(layers.operatorDefault) ? layers.operatorDefault : noDepositPolicy,
|
|
181
|
+
source: "operator_default",
|
|
182
|
+
};
|
|
151
183
|
}
|
|
152
184
|
/**
|
|
153
185
|
* Predicate the storefront UI uses to decide whether to surface the
|
|
@@ -155,12 +187,13 @@ export function resolveEffectivePaymentPolicy(layers) {
|
|
|
155
187
|
* the policy + departure date resolve to a single full-payment row.
|
|
156
188
|
*/
|
|
157
189
|
export function policyShouldRequireFullPayment(policy, departureDate, today = new Date()) {
|
|
158
|
-
|
|
190
|
+
const effectivePolicy = isPaymentPolicy(policy) ? policy : noDepositPolicy;
|
|
191
|
+
if (effectivePolicy.deposit.kind === "none")
|
|
159
192
|
return true;
|
|
160
193
|
const departure = parseIsoDate(departureDate);
|
|
161
194
|
if (!departure)
|
|
162
195
|
return true;
|
|
163
|
-
return wholeDaysBetween(today, departure) <
|
|
196
|
+
return wholeDaysBetween(today, departure) < effectivePolicy.minDaysBeforeDepartureForDeposit;
|
|
164
197
|
}
|
|
165
198
|
// ─────────────────────────────────────────────────────────────────
|
|
166
199
|
// Helpers
|