@voyantjs/legal 0.8.0 → 0.10.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/contracts/routes.d.ts +8 -8
- package/dist/contracts/service-contracts.d.ts +2 -2
- package/dist/contracts/service-templates.d.ts +1 -1
- package/dist/contracts/service.d.ts +3 -3
- package/dist/policies/index.d.ts +2 -2
- package/dist/policies/index.d.ts.map +1 -1
- package/dist/policies/index.js +1 -1
- package/dist/policies/routes.d.ts +2 -2
- package/dist/policies/service-core.d.ts +23 -2
- package/dist/policies/service-core.d.ts.map +1 -1
- package/dist/policies/service-core.js +50 -1
- package/dist/policies/service-shared.d.ts +57 -0
- package/dist/policies/service-shared.d.ts.map +1 -1
- package/dist/policies/service-shared.js +51 -0
- package/dist/policies/service.d.ts +12 -3
- package/dist/policies/service.d.ts.map +1 -1
- package/dist/policies/service.js +2 -2
- package/package.json +9 -9
|
@@ -88,9 +88,9 @@ export declare function createContractsAdminRoutes(options?: ContractsRouteOptio
|
|
|
88
88
|
scope: "customer" | "partner" | "supplier" | "other" | "channel";
|
|
89
89
|
slug: string;
|
|
90
90
|
description: string | null;
|
|
91
|
-
language: string;
|
|
92
91
|
active: boolean;
|
|
93
92
|
body: string;
|
|
93
|
+
language: string;
|
|
94
94
|
variableSchema: import("hono/utils/types").JSONValue;
|
|
95
95
|
currentVersionId: string | null;
|
|
96
96
|
} | null;
|
|
@@ -531,11 +531,11 @@ export declare function createContractsAdminRoutes(options?: ContractsRouteOptio
|
|
|
531
531
|
scope: "customer" | "partner" | "supplier" | "other" | "channel";
|
|
532
532
|
organizationId: string | null;
|
|
533
533
|
status: "executed" | "void" | "draft" | "issued" | "sent" | "signed" | "expired";
|
|
534
|
+
bookingId: string | null;
|
|
534
535
|
language: string;
|
|
535
536
|
variables: import("hono/utils/types").JSONValue;
|
|
536
537
|
personId: string | null;
|
|
537
538
|
supplierId: string | null;
|
|
538
|
-
bookingId: string | null;
|
|
539
539
|
orderId: string | null;
|
|
540
540
|
title: string;
|
|
541
541
|
templateVersionId: string | null;
|
|
@@ -886,12 +886,12 @@ export declare function createContractsAdminRoutes(options?: ContractsRouteOptio
|
|
|
886
886
|
createdAt: string;
|
|
887
887
|
ipAddress: string | null;
|
|
888
888
|
userAgent: string | null;
|
|
889
|
+
provider: string | null;
|
|
889
890
|
personId: string | null;
|
|
890
891
|
signerName: string;
|
|
891
892
|
signerEmail: string | null;
|
|
892
893
|
signerRole: string | null;
|
|
893
894
|
method: "other" | "manual" | "electronic" | "docusign";
|
|
894
|
-
provider: string | null;
|
|
895
895
|
externalReference: string | null;
|
|
896
896
|
signatureData: string | null;
|
|
897
897
|
contractId: string;
|
|
@@ -1479,9 +1479,9 @@ export declare const contractsAdminRoutes: import("hono/hono-base").HonoBase<Env
|
|
|
1479
1479
|
scope: "customer" | "partner" | "supplier" | "other" | "channel";
|
|
1480
1480
|
slug: string;
|
|
1481
1481
|
description: string | null;
|
|
1482
|
-
language: string;
|
|
1483
1482
|
active: boolean;
|
|
1484
1483
|
body: string;
|
|
1484
|
+
language: string;
|
|
1485
1485
|
variableSchema: import("hono/utils/types").JSONValue;
|
|
1486
1486
|
currentVersionId: string | null;
|
|
1487
1487
|
} | null;
|
|
@@ -1922,11 +1922,11 @@ export declare const contractsAdminRoutes: import("hono/hono-base").HonoBase<Env
|
|
|
1922
1922
|
scope: "customer" | "partner" | "supplier" | "other" | "channel";
|
|
1923
1923
|
organizationId: string | null;
|
|
1924
1924
|
status: "executed" | "void" | "draft" | "issued" | "sent" | "signed" | "expired";
|
|
1925
|
+
bookingId: string | null;
|
|
1925
1926
|
language: string;
|
|
1926
1927
|
variables: import("hono/utils/types").JSONValue;
|
|
1927
1928
|
personId: string | null;
|
|
1928
1929
|
supplierId: string | null;
|
|
1929
|
-
bookingId: string | null;
|
|
1930
1930
|
orderId: string | null;
|
|
1931
1931
|
title: string;
|
|
1932
1932
|
templateVersionId: string | null;
|
|
@@ -2277,12 +2277,12 @@ export declare const contractsAdminRoutes: import("hono/hono-base").HonoBase<Env
|
|
|
2277
2277
|
createdAt: string;
|
|
2278
2278
|
ipAddress: string | null;
|
|
2279
2279
|
userAgent: string | null;
|
|
2280
|
+
provider: string | null;
|
|
2280
2281
|
personId: string | null;
|
|
2281
2282
|
signerName: string;
|
|
2282
2283
|
signerEmail: string | null;
|
|
2283
2284
|
signerRole: string | null;
|
|
2284
2285
|
method: "other" | "manual" | "electronic" | "docusign";
|
|
2285
|
-
provider: string | null;
|
|
2286
2286
|
externalReference: string | null;
|
|
2287
2287
|
signatureData: string | null;
|
|
2288
2288
|
contractId: string;
|
|
@@ -2947,12 +2947,12 @@ export declare function createContractsPublicRoutes(): import("hono/hono-base").
|
|
|
2947
2947
|
createdAt: string;
|
|
2948
2948
|
ipAddress: string | null;
|
|
2949
2949
|
userAgent: string | null;
|
|
2950
|
+
provider: string | null;
|
|
2950
2951
|
personId: string | null;
|
|
2951
2952
|
signerName: string;
|
|
2952
2953
|
signerEmail: string | null;
|
|
2953
2954
|
signerRole: string | null;
|
|
2954
2955
|
method: "other" | "manual" | "electronic" | "docusign";
|
|
2955
|
-
provider: string | null;
|
|
2956
2956
|
externalReference: string | null;
|
|
2957
2957
|
signatureData: string | null;
|
|
2958
2958
|
contractId: string;
|
|
@@ -3113,12 +3113,12 @@ export declare const contractsPublicRoutes: import("hono/hono-base").HonoBase<En
|
|
|
3113
3113
|
createdAt: string;
|
|
3114
3114
|
ipAddress: string | null;
|
|
3115
3115
|
userAgent: string | null;
|
|
3116
|
+
provider: string | null;
|
|
3116
3117
|
personId: string | null;
|
|
3117
3118
|
signerName: string;
|
|
3118
3119
|
signerEmail: string | null;
|
|
3119
3120
|
signerRole: string | null;
|
|
3120
3121
|
method: "other" | "manual" | "electronic" | "docusign";
|
|
3121
|
-
provider: string | null;
|
|
3122
3122
|
externalReference: string | null;
|
|
3123
3123
|
signatureData: string | null;
|
|
3124
3124
|
contractId: string;
|
|
@@ -69,11 +69,11 @@ export declare const contractRecordsService: {
|
|
|
69
69
|
scope: "customer" | "partner" | "supplier" | "other" | "channel";
|
|
70
70
|
organizationId: string | null;
|
|
71
71
|
status: "executed" | "void" | "draft" | "issued" | "sent" | "signed" | "expired";
|
|
72
|
+
bookingId: string | null;
|
|
72
73
|
language: string;
|
|
73
74
|
variables: unknown;
|
|
74
75
|
personId: string | null;
|
|
75
76
|
supplierId: string | null;
|
|
76
|
-
bookingId: string | null;
|
|
77
77
|
orderId: string | null;
|
|
78
78
|
title: string;
|
|
79
79
|
templateVersionId: string | null;
|
|
@@ -801,12 +801,12 @@ export declare const contractRecordsService: {
|
|
|
801
801
|
createdAt: Date;
|
|
802
802
|
ipAddress: string | null;
|
|
803
803
|
userAgent: string | null;
|
|
804
|
+
provider: string | null;
|
|
804
805
|
personId: string | null;
|
|
805
806
|
signerName: string;
|
|
806
807
|
signerEmail: string | null;
|
|
807
808
|
signerRole: string | null;
|
|
808
809
|
method: "other" | "manual" | "electronic" | "docusign";
|
|
809
|
-
provider: string | null;
|
|
810
810
|
externalReference: string | null;
|
|
811
811
|
signatureData: string | null;
|
|
812
812
|
contractId: string;
|
|
@@ -78,9 +78,9 @@ export declare const contractTemplatesService: {
|
|
|
78
78
|
scope: "customer" | "partner" | "supplier" | "other" | "channel";
|
|
79
79
|
slug: string;
|
|
80
80
|
description: string | null;
|
|
81
|
-
language: string;
|
|
82
81
|
active: boolean;
|
|
83
82
|
body: string;
|
|
83
|
+
language: string;
|
|
84
84
|
variableSchema: unknown;
|
|
85
85
|
currentVersionId: string | null;
|
|
86
86
|
} | null>;
|
|
@@ -81,11 +81,11 @@ export declare const contractsService: {
|
|
|
81
81
|
scope: "customer" | "partner" | "supplier" | "other" | "channel";
|
|
82
82
|
organizationId: string | null;
|
|
83
83
|
status: "executed" | "void" | "draft" | "issued" | "sent" | "signed" | "expired";
|
|
84
|
+
bookingId: string | null;
|
|
84
85
|
language: string;
|
|
85
86
|
variables: unknown;
|
|
86
87
|
personId: string | null;
|
|
87
88
|
supplierId: string | null;
|
|
88
|
-
bookingId: string | null;
|
|
89
89
|
orderId: string | null;
|
|
90
90
|
title: string;
|
|
91
91
|
templateVersionId: string | null;
|
|
@@ -813,12 +813,12 @@ export declare const contractsService: {
|
|
|
813
813
|
createdAt: Date;
|
|
814
814
|
ipAddress: string | null;
|
|
815
815
|
userAgent: string | null;
|
|
816
|
+
provider: string | null;
|
|
816
817
|
personId: string | null;
|
|
817
818
|
signerName: string;
|
|
818
819
|
signerEmail: string | null;
|
|
819
820
|
signerRole: string | null;
|
|
820
821
|
method: "other" | "manual" | "electronic" | "docusign";
|
|
821
|
-
provider: string | null;
|
|
822
822
|
externalReference: string | null;
|
|
823
823
|
signatureData: string | null;
|
|
824
824
|
contractId: string;
|
|
@@ -1400,9 +1400,9 @@ export declare const contractsService: {
|
|
|
1400
1400
|
scope: "customer" | "partner" | "supplier" | "other" | "channel";
|
|
1401
1401
|
slug: string;
|
|
1402
1402
|
description: string | null;
|
|
1403
|
-
language: string;
|
|
1404
1403
|
active: boolean;
|
|
1405
1404
|
body: string;
|
|
1405
|
+
language: string;
|
|
1406
1406
|
variableSchema: unknown;
|
|
1407
1407
|
currentVersionId: string | null;
|
|
1408
1408
|
} | null>;
|
package/dist/policies/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export declare const policiesLinkable: {
|
|
|
10
10
|
};
|
|
11
11
|
export type { NewPolicy, NewPolicyAcceptance, NewPolicyAssignment, NewPolicyRule, NewPolicyVersion, Policy, PolicyAcceptance, PolicyAssignment, PolicyRule, PolicyVersion, } from "./schema.js";
|
|
12
12
|
export { policies, policyAcceptances, policyAssignments, policyRules, policyVersions, } from "./schema.js";
|
|
13
|
-
export type { CancellationResult, CancellationRule } from "./service.js";
|
|
14
|
-
export { evaluateCancellationPolicy, policiesService } from "./service.js";
|
|
13
|
+
export type { CancellationResult, CancellationRule, CancellationSegment, SegmentedCancellationInput, SegmentedCancellationResult, } from "./service.js";
|
|
14
|
+
export { evaluateCancellationPolicy, evaluateSegmentedCancellation, policiesService, } from "./service.js";
|
|
15
15
|
export { evaluateCancellationInputSchema, insertPolicyAcceptanceSchema, insertPolicyAssignmentSchema, insertPolicyRuleSchema, insertPolicySchema, insertPolicyVersionSchema, policyAcceptanceListQuerySchema, policyAcceptanceMethodSchema, policyAssignmentListQuerySchema, policyAssignmentScopeSchema, policyKindSchema, policyListQuerySchema, policyRefundTypeSchema, policyRuleTypeSchema, policyVersionStatusSchema, resolvePolicyInputSchema, updatePolicyAssignmentSchema, updatePolicyRuleSchema, updatePolicySchema, updatePolicyVersionSchema, } from "./validation.js";
|
|
16
16
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/policies/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAExD,YAAY,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAE5E,eAAO,MAAM,cAAc,EAAE,kBAK5B,CAAA;AAED,eAAO,MAAM,qBAAqB,EAAE,kBAKnC,CAAA;AAED,eAAO,MAAM,wBAAwB,EAAE,kBAKtC,CAAA;AAED,eAAO,MAAM,gBAAgB;;;;CAI5B,CAAA;AAED,YAAY,EACV,SAAS,EACT,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EAChB,MAAM,EACN,gBAAgB,EAChB,gBAAgB,EAChB,UAAU,EACV,aAAa,GACd,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,QAAQ,EACR,iBAAiB,EACjB,iBAAiB,EACjB,WAAW,EACX,cAAc,GACf,MAAM,aAAa,CAAA;AACpB,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/policies/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAExD,YAAY,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAE5E,eAAO,MAAM,cAAc,EAAE,kBAK5B,CAAA;AAED,eAAO,MAAM,qBAAqB,EAAE,kBAKnC,CAAA;AAED,eAAO,MAAM,wBAAwB,EAAE,kBAKtC,CAAA;AAED,eAAO,MAAM,gBAAgB;;;;CAI5B,CAAA;AAED,YAAY,EACV,SAAS,EACT,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EAChB,MAAM,EACN,gBAAgB,EAChB,gBAAgB,EAChB,UAAU,EACV,aAAa,GACd,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,QAAQ,EACR,iBAAiB,EACjB,iBAAiB,EACjB,WAAW,EACX,cAAc,GACf,MAAM,aAAa,CAAA;AACpB,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,0BAA0B,EAC1B,6BAA6B,EAC7B,eAAe,GAChB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,+BAA+B,EAC/B,4BAA4B,EAC5B,4BAA4B,EAC5B,sBAAsB,EACtB,kBAAkB,EAClB,yBAAyB,EACzB,+BAA+B,EAC/B,4BAA4B,EAC5B,+BAA+B,EAC/B,2BAA2B,EAC3B,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,EACtB,oBAAoB,EACpB,yBAAyB,EACzB,wBAAwB,EACxB,4BAA4B,EAC5B,sBAAsB,EACtB,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,iBAAiB,CAAA"}
|
package/dist/policies/index.js
CHANGED
|
@@ -22,5 +22,5 @@ export const policiesLinkable = {
|
|
|
22
22
|
policyAcceptance: policyAcceptanceLinkable,
|
|
23
23
|
};
|
|
24
24
|
export { policies, policyAcceptances, policyAssignments, policyRules, policyVersions, } from "./schema.js";
|
|
25
|
-
export { evaluateCancellationPolicy, policiesService } from "./service.js";
|
|
25
|
+
export { evaluateCancellationPolicy, evaluateSegmentedCancellation, policiesService, } from "./service.js";
|
|
26
26
|
export { evaluateCancellationInputSchema, insertPolicyAcceptanceSchema, insertPolicyAssignmentSchema, insertPolicyRuleSchema, insertPolicySchema, insertPolicyVersionSchema, policyAcceptanceListQuerySchema, policyAcceptanceMethodSchema, policyAssignmentListQuerySchema, policyAssignmentScopeSchema, policyKindSchema, policyListQuerySchema, policyRefundTypeSchema, policyRuleTypeSchema, policyVersionStatusSchema, resolvePolicyInputSchema, updatePolicyAssignmentSchema, updatePolicyRuleSchema, updatePolicySchema, updatePolicyVersionSchema, } from "./validation.js";
|
|
@@ -666,8 +666,8 @@ export declare const policiesAdminRoutes: import("hono/hono-base").HonoBase<Env,
|
|
|
666
666
|
createdAt: string;
|
|
667
667
|
ipAddress: string | null;
|
|
668
668
|
userAgent: string | null;
|
|
669
|
-
personId: string | null;
|
|
670
669
|
bookingId: string | null;
|
|
670
|
+
personId: string | null;
|
|
671
671
|
orderId: string | null;
|
|
672
672
|
method: "signature" | "implicit" | "explicit_checkbox";
|
|
673
673
|
acceptedAt: string;
|
|
@@ -888,8 +888,8 @@ export declare const policiesPublicRoutes: import("hono/hono-base").HonoBase<Env
|
|
|
888
888
|
createdAt: string;
|
|
889
889
|
ipAddress: string | null;
|
|
890
890
|
userAgent: string | null;
|
|
891
|
-
personId: string | null;
|
|
892
891
|
bookingId: string | null;
|
|
892
|
+
personId: string | null;
|
|
893
893
|
orderId: string | null;
|
|
894
894
|
method: "signature" | "implicit" | "explicit_checkbox";
|
|
895
895
|
acceptedAt: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
|
|
2
|
-
import { type CreatePolicyAcceptanceInput, type CreatePolicyAssignmentInput, type CreatePolicyInput, type CreatePolicyRuleInput, type CreatePolicyVersionInput, type EvaluateCancellationInput, type PolicyAcceptanceListQuery, type PolicyAssignmentListQuery, type PolicyListQuery, type ResolvePolicyInput, type UpdatePolicyAssignmentInput, type UpdatePolicyInput, type UpdatePolicyRuleInput, type UpdatePolicyVersionInput } from "./service-shared.js";
|
|
2
|
+
import { type CreatePolicyAcceptanceInput, type CreatePolicyAssignmentInput, type CreatePolicyInput, type CreatePolicyRuleInput, type CreatePolicyVersionInput, type EvaluateCancellationInput, type PolicyAcceptanceListQuery, type PolicyAssignmentListQuery, type PolicyListQuery, type ResolvePolicyInput, type SegmentedCancellationResult, type UpdatePolicyAssignmentInput, type UpdatePolicyInput, type UpdatePolicyRuleInput, type UpdatePolicyVersionInput } from "./service-shared.js";
|
|
3
3
|
export declare const policiesCoreService: {
|
|
4
4
|
listPolicies(db: PostgresJsDatabase, query: PolicyListQuery): Promise<{
|
|
5
5
|
data: {
|
|
@@ -1256,6 +1256,27 @@ export declare const policiesCoreService: {
|
|
|
1256
1256
|
}[];
|
|
1257
1257
|
} | null>;
|
|
1258
1258
|
evaluateCancellation(db: PostgresJsDatabase, policyId: string, input: EvaluateCancellationInput): Promise<import("./service-shared.js").CancellationResult | null>;
|
|
1259
|
+
/**
|
|
1260
|
+
* DB variant of {@link evaluateSegmentedCancellation} that resolves
|
|
1261
|
+
* each segment's rules from a `policyId`. Use this for multi-segment
|
|
1262
|
+
* cancellations where each line item may carry a different
|
|
1263
|
+
* cancellation policy (e.g. mid-stay room change with mixed
|
|
1264
|
+
* flexible/non-refundable rate plans).
|
|
1265
|
+
*
|
|
1266
|
+
* Segments referencing a missing or version-less policy are passed
|
|
1267
|
+
* through with empty `rules`, which produces a zero refund — surfaces
|
|
1268
|
+
* as a per-segment `appliedRule: null` for ops triage rather than
|
|
1269
|
+
* throwing on the whole cancellation.
|
|
1270
|
+
*/
|
|
1271
|
+
evaluateMultiPolicyCancellation(db: PostgresJsDatabase, segments: Array<{
|
|
1272
|
+
id?: string;
|
|
1273
|
+
label?: string;
|
|
1274
|
+
policyId: string;
|
|
1275
|
+
totalCents: number;
|
|
1276
|
+
}>, input: {
|
|
1277
|
+
daysBeforeDeparture: number;
|
|
1278
|
+
currency?: string;
|
|
1279
|
+
}): Promise<SegmentedCancellationResult>;
|
|
1259
1280
|
listPolicyAcceptances(db: PostgresJsDatabase, query: PolicyAcceptanceListQuery): Promise<{
|
|
1260
1281
|
data: {
|
|
1261
1282
|
id: string;
|
|
@@ -1282,8 +1303,8 @@ export declare const policiesCoreService: {
|
|
|
1282
1303
|
createdAt: Date;
|
|
1283
1304
|
ipAddress: string | null;
|
|
1284
1305
|
userAgent: string | null;
|
|
1285
|
-
personId: string | null;
|
|
1286
1306
|
bookingId: string | null;
|
|
1307
|
+
personId: string | null;
|
|
1287
1308
|
orderId: string | null;
|
|
1288
1309
|
method: "signature" | "implicit" | "explicit_checkbox";
|
|
1289
1310
|
acceptedAt: Date;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-core.d.ts","sourceRoot":"","sources":["../../src/policies/service-core.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AASjE,OAAO,EAEL,KAAK,2BAA2B,EAChC,KAAK,2BAA2B,EAChC,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,
|
|
1
|
+
{"version":3,"file":"service-core.d.ts","sourceRoot":"","sources":["../../src/policies/service-core.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AASjE,OAAO,EAEL,KAAK,2BAA2B,EAChC,KAAK,2BAA2B,EAChC,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAG9B,KAAK,yBAAyB,EAC9B,KAAK,yBAAyB,EAC9B,KAAK,eAAe,EAEpB,KAAK,kBAAkB,EACvB,KAAK,2BAA2B,EAEhC,KAAK,2BAA2B,EAChC,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,wBAAwB,EAC9B,MAAM,qBAAqB,CAAA;AAE5B,eAAO,MAAM,mBAAmB;qBACP,kBAAkB,SAAS,eAAe;;;;;;;;;;;;;;;;;sBA4BzC,kBAAkB,MAAM,MAAM;;;;;;;;;;;;wBAI5B,kBAAkB,QAAQ,MAAM;;;;;;;;;;;;qBAInC,kBAAkB,QAAQ,iBAAiB;;;;;;;;;;;;qBAI3C,kBAAkB,MAAM,MAAM,QAAQ,iBAAiB;;;;;;;;;;;;qBAQvD,kBAAkB,MAAM,MAAM;;;2BAO9B,kBAAkB,YAAY,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6BAO5B,kBAAkB,MAAM,MAAM;;;;;;;;;;;;;;4BAKvD,kBAAkB,YACZ,MAAM,QACV,wBAAwB;;;;;;;;;;;;;;4BA8B1B,kBAAkB,aACX,MAAM,QACX,wBAAwB;;;;;;;;;;;;;;6BASD,kBAAkB,aAAa,MAAM;;;;;;;;;;;;;;;;;;;;;;;4BA+BtC,kBAAkB,aAAa,MAAM;;;;;;;;;;;;;;wBAQ/C,kBAAkB,aAAa,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAO9B,kBAAkB,aAAa,MAAM,QAAQ,qBAAqB;;;;;;;;;;;;;;;;;yBA0BlE,kBAAkB,UAAU,MAAM,QAAQ,qBAAqB;;;;;;;;;;;;;;;;;yBAQ/D,kBAAkB,UAAU,MAAM;;;8BAO7B,kBAAkB,SAAS,yBAAyB;;;;;;;;;;;;;;;;;;;;;+BAwBnD,kBAAkB,QAAQ,2BAA2B;;;;;;;;;;;;;;;;+BAoBhF,kBAAkB,MAClB,MAAM,QACJ,2BAA2B;;;;;;;;;;;;;;;;+BASF,kBAAkB,MAAM,MAAM;;;sBAOvC,kBAAkB,SAAS,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6BA4F/D,kBAAkB,YACZ,MAAM,SACT,yBAAyB;IAmBlC;;;;;;;;;;;OAWG;wCAEG,kBAAkB,YACZ,KAAK,CAAC;QACd,EAAE,CAAC,EAAE,MAAM,CAAA;QACX,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,QAAQ,EAAE,MAAM,CAAA;QAChB,UAAU,EAAE,MAAM,CAAA;KACnB,CAAC,SACK;QAAE,mBAAmB,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GACxD,OAAO,CAAC,2BAA2B,CAAC;8BA0CP,kBAAkB,SAAS,yBAAyB;;;;;;;;;;;;;;;;;;;;+BAqBnD,kBAAkB,QAAQ,2BAA2B;;;;;;;;;;;;;;;CAkBvF,CAAA"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { and, desc, eq, gte, ilike, lte, or, sql } from "drizzle-orm";
|
|
2
2
|
import { policies, policyAcceptances, policyAssignments, policyRules, policyVersions, } from "./schema.js";
|
|
3
|
-
import { evaluateCancellationPolicy, paginate, toDateString, } from "./service-shared.js";
|
|
3
|
+
import { evaluateCancellationPolicy, evaluateSegmentedCancellation, paginate, toDateString, } from "./service-shared.js";
|
|
4
4
|
export const policiesCoreService = {
|
|
5
5
|
async listPolicies(db, query) {
|
|
6
6
|
const conditions = [];
|
|
@@ -316,6 +316,55 @@ export const policiesCoreService = {
|
|
|
316
316
|
}));
|
|
317
317
|
return evaluateCancellationPolicy(mapped, input);
|
|
318
318
|
},
|
|
319
|
+
/**
|
|
320
|
+
* DB variant of {@link evaluateSegmentedCancellation} that resolves
|
|
321
|
+
* each segment's rules from a `policyId`. Use this for multi-segment
|
|
322
|
+
* cancellations where each line item may carry a different
|
|
323
|
+
* cancellation policy (e.g. mid-stay room change with mixed
|
|
324
|
+
* flexible/non-refundable rate plans).
|
|
325
|
+
*
|
|
326
|
+
* Segments referencing a missing or version-less policy are passed
|
|
327
|
+
* through with empty `rules`, which produces a zero refund — surfaces
|
|
328
|
+
* as a per-segment `appliedRule: null` for ops triage rather than
|
|
329
|
+
* throwing on the whole cancellation.
|
|
330
|
+
*/
|
|
331
|
+
async evaluateMultiPolicyCancellation(db, segments, input) {
|
|
332
|
+
const policyIds = [...new Set(segments.map((segment) => segment.policyId))];
|
|
333
|
+
const rulesByPolicyId = new Map();
|
|
334
|
+
for (const policyId of policyIds) {
|
|
335
|
+
const [policy] = await db
|
|
336
|
+
.select({ id: policies.id, currentVersionId: policies.currentVersionId })
|
|
337
|
+
.from(policies)
|
|
338
|
+
.where(eq(policies.id, policyId))
|
|
339
|
+
.limit(1);
|
|
340
|
+
if (!policy?.currentVersionId) {
|
|
341
|
+
rulesByPolicyId.set(policyId, []);
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
const rules = await db
|
|
345
|
+
.select()
|
|
346
|
+
.from(policyRules)
|
|
347
|
+
.where(eq(policyRules.policyVersionId, policy.currentVersionId));
|
|
348
|
+
rulesByPolicyId.set(policyId, rules.map((r) => ({
|
|
349
|
+
id: r.id,
|
|
350
|
+
daysBeforeDeparture: r.daysBeforeDeparture,
|
|
351
|
+
refundPercent: r.refundPercent,
|
|
352
|
+
refundType: r.refundType,
|
|
353
|
+
flatAmountCents: r.flatAmountCents,
|
|
354
|
+
label: r.label,
|
|
355
|
+
})));
|
|
356
|
+
}
|
|
357
|
+
return evaluateSegmentedCancellation({
|
|
358
|
+
daysBeforeDeparture: input.daysBeforeDeparture,
|
|
359
|
+
currency: input.currency,
|
|
360
|
+
segments: segments.map((segment) => ({
|
|
361
|
+
id: segment.id,
|
|
362
|
+
label: segment.label,
|
|
363
|
+
totalCents: segment.totalCents,
|
|
364
|
+
rules: rulesByPolicyId.get(segment.policyId) ?? [],
|
|
365
|
+
})),
|
|
366
|
+
});
|
|
367
|
+
},
|
|
319
368
|
async listPolicyAcceptances(db, query) {
|
|
320
369
|
const conditions = [];
|
|
321
370
|
if (query.policyVersionId)
|
|
@@ -39,5 +39,62 @@ export type CancellationResult = {
|
|
|
39
39
|
appliedRule: CancellationRule | null;
|
|
40
40
|
};
|
|
41
41
|
export declare function evaluateCancellationPolicy(rules: CancellationRule[], input: EvaluateCancellationInput): CancellationResult;
|
|
42
|
+
/**
|
|
43
|
+
* One revenue line in a multi-segment cancellation. Each segment carries
|
|
44
|
+
* its own rule set + own amount; segments that share a policy still need
|
|
45
|
+
* to be passed in separately so the per-segment refund tracks the
|
|
46
|
+
* specific line item.
|
|
47
|
+
*/
|
|
48
|
+
export type CancellationSegment = {
|
|
49
|
+
/** Optional caller-supplied id — typically the booking_item id. */
|
|
50
|
+
id?: string;
|
|
51
|
+
/** Optional human-readable label (e.g. "Deluxe room, 3 nights"). */
|
|
52
|
+
label?: string;
|
|
53
|
+
rules: CancellationRule[];
|
|
54
|
+
totalCents: number;
|
|
55
|
+
};
|
|
56
|
+
export type SegmentedCancellationInput = {
|
|
57
|
+
daysBeforeDeparture: number;
|
|
58
|
+
currency?: string;
|
|
59
|
+
segments: CancellationSegment[];
|
|
60
|
+
};
|
|
61
|
+
export type SegmentedCancellationResult = {
|
|
62
|
+
/** Σ(segments.totalCents). */
|
|
63
|
+
totalCents: number;
|
|
64
|
+
/** Σ(per-segment refundCents). */
|
|
65
|
+
refundCents: number;
|
|
66
|
+
/** Aggregate refund as basis points: refundCents / totalCents × 10000. */
|
|
67
|
+
refundPercent: number;
|
|
68
|
+
/**
|
|
69
|
+
* "mixed" when the segments resolve to different refundTypes (e.g. one
|
|
70
|
+
* segment is `cash` and another is `none`). When all non-zero
|
|
71
|
+
* segments resolve to the same refundType, that value is preserved.
|
|
72
|
+
* "none" when every segment resolves to 0 refund.
|
|
73
|
+
*/
|
|
74
|
+
refundType: "cash" | "credit" | "cash_or_credit" | "none" | "mixed";
|
|
75
|
+
segments: Array<{
|
|
76
|
+
id?: string;
|
|
77
|
+
label?: string;
|
|
78
|
+
totalCents: number;
|
|
79
|
+
result: CancellationResult;
|
|
80
|
+
}>;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Evaluate a multi-segment cancellation. Each segment runs through
|
|
84
|
+
* {@link evaluateCancellationPolicy} with the shared
|
|
85
|
+
* `daysBeforeDeparture`; per-segment refunds are summed and a coarse
|
|
86
|
+
* `refundType` is computed for the aggregate.
|
|
87
|
+
*
|
|
88
|
+
* Use case: hotel bookings with mid-stay room changes where each
|
|
89
|
+
* `stay_booking_items.ratePlanId` carries a different
|
|
90
|
+
* `cancellationPolicyId` (e.g. flexible Deluxe + non-refundable Suite).
|
|
91
|
+
* The customer cancels and we owe a partial refund — the flexible
|
|
92
|
+
* portion's refundCents + 0 from the non-refundable portion.
|
|
93
|
+
*
|
|
94
|
+
* Pure: no I/O. Caller resolves rules from policy IDs first (see
|
|
95
|
+
* {@link policiesService.evaluateMultiPolicyCancellation} for the DB
|
|
96
|
+
* variant).
|
|
97
|
+
*/
|
|
98
|
+
export declare function evaluateSegmentedCancellation(input: SegmentedCancellationInput): SegmentedCancellationResult;
|
|
42
99
|
export declare const _unused: typeof inArray;
|
|
43
100
|
//# sourceMappingURL=service-shared.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-shared.d.ts","sourceRoot":"","sources":["../../src/policies/service-shared.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"service-shared.d.ts","sourceRoot":"","sources":["../../src/policies/service-shared.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AACrC,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAE5B,OAAO,KAAK,EACV,+BAA+B,EAC/B,4BAA4B,EAC5B,4BAA4B,EAC5B,sBAAsB,EACtB,kBAAkB,EAClB,yBAAyB,EACzB,+BAA+B,EAC/B,+BAA+B,EAC/B,qBAAqB,EACrB,wBAAwB,EACxB,4BAA4B,EAC5B,sBAAsB,EACtB,kBAAkB,EAClB,yBAAyB,EAC1B,MAAM,iBAAiB,CAAA;AAExB,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAA;AACnE,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAClE,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAClE,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAA;AAChF,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAA;AAChF,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAA;AAC1E,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAA;AAC1E,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAA;AACtF,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAA;AACtF,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAA;AACvF,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAA;AACtF,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAA;AACvF,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAA;AACvF,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAA;AAEzE,wBAAsB,QAAQ,CAAC,CAAC,SAAS,MAAM,EAC7C,SAAS,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,EACvB,UAAU,EAAE,OAAO,CAAC,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,EAC7C,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM;;;;;GAIf;AAED,wBAAgB,YAAY,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAEjE;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,gBAAgB,GAAG,MAAM,GAAG,IAAI,CAAA;IAChE,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,gBAAgB,GAAG,MAAM,CAAA;IACzD,WAAW,EAAE,gBAAgB,GAAG,IAAI,CAAA;CACrC,CAAA;AAED,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,gBAAgB,EAAE,EACzB,KAAK,EAAE,yBAAyB,GAC/B,kBAAkB,CA6BpB;AAED;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,mEAAmE;IACnE,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,gBAAgB,EAAE,CAAA;IACzB,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,0BAA0B,GAAG;IACvC,mBAAmB,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,mBAAmB,EAAE,CAAA;CAChC,CAAA;AAED,MAAM,MAAM,2BAA2B,GAAG;IACxC,8BAA8B;IAC9B,UAAU,EAAE,MAAM,CAAA;IAClB,kCAAkC;IAClC,WAAW,EAAE,MAAM,CAAA;IACnB,0EAA0E;IAC1E,aAAa,EAAE,MAAM,CAAA;IACrB;;;;;OAKG;IACH,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,gBAAgB,GAAG,MAAM,GAAG,OAAO,CAAA;IACnE,QAAQ,EAAE,KAAK,CAAC;QACd,EAAE,CAAC,EAAE,MAAM,CAAA;QACX,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,UAAU,EAAE,MAAM,CAAA;QAClB,MAAM,EAAE,kBAAkB,CAAA;KAC3B,CAAC,CAAA;CACH,CAAA;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,0BAA0B,GAChC,2BAA2B,CAuC7B;AAED,eAAO,MAAM,OAAO,gBAAU,CAAA"}
|
|
@@ -27,4 +27,55 @@ export function evaluateCancellationPolicy(rules, input) {
|
|
|
27
27
|
const refundCents = applied.flatAmountCents ?? percentageRefundCents;
|
|
28
28
|
return { refundPercent, refundCents, refundType, appliedRule: applied };
|
|
29
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Evaluate a multi-segment cancellation. Each segment runs through
|
|
32
|
+
* {@link evaluateCancellationPolicy} with the shared
|
|
33
|
+
* `daysBeforeDeparture`; per-segment refunds are summed and a coarse
|
|
34
|
+
* `refundType` is computed for the aggregate.
|
|
35
|
+
*
|
|
36
|
+
* Use case: hotel bookings with mid-stay room changes where each
|
|
37
|
+
* `stay_booking_items.ratePlanId` carries a different
|
|
38
|
+
* `cancellationPolicyId` (e.g. flexible Deluxe + non-refundable Suite).
|
|
39
|
+
* The customer cancels and we owe a partial refund — the flexible
|
|
40
|
+
* portion's refundCents + 0 from the non-refundable portion.
|
|
41
|
+
*
|
|
42
|
+
* Pure: no I/O. Caller resolves rules from policy IDs first (see
|
|
43
|
+
* {@link policiesService.evaluateMultiPolicyCancellation} for the DB
|
|
44
|
+
* variant).
|
|
45
|
+
*/
|
|
46
|
+
export function evaluateSegmentedCancellation(input) {
|
|
47
|
+
const totalCents = input.segments.reduce((sum, segment) => sum + segment.totalCents, 0);
|
|
48
|
+
const segmentResults = input.segments.map((segment) => ({
|
|
49
|
+
id: segment.id,
|
|
50
|
+
label: segment.label,
|
|
51
|
+
totalCents: segment.totalCents,
|
|
52
|
+
result: evaluateCancellationPolicy(segment.rules, {
|
|
53
|
+
daysBeforeDeparture: input.daysBeforeDeparture,
|
|
54
|
+
totalCents: segment.totalCents,
|
|
55
|
+
currency: input.currency,
|
|
56
|
+
}),
|
|
57
|
+
}));
|
|
58
|
+
const refundCents = segmentResults.reduce((sum, segment) => sum + segment.result.refundCents, 0);
|
|
59
|
+
const refundPercent = totalCents > 0 ? Math.floor((refundCents * 10000) / totalCents) : 0;
|
|
60
|
+
const nonZeroTypes = new Set(segmentResults
|
|
61
|
+
.filter((segment) => segment.result.refundCents > 0)
|
|
62
|
+
.map((segment) => segment.result.refundType));
|
|
63
|
+
let refundType;
|
|
64
|
+
if (nonZeroTypes.size === 0) {
|
|
65
|
+
refundType = "none";
|
|
66
|
+
}
|
|
67
|
+
else if (nonZeroTypes.size === 1) {
|
|
68
|
+
refundType = [...nonZeroTypes][0];
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
refundType = "mixed";
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
totalCents,
|
|
75
|
+
refundCents,
|
|
76
|
+
refundPercent,
|
|
77
|
+
refundType,
|
|
78
|
+
segments: segmentResults,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
30
81
|
export const _unused = inArray;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { _unused, type CancellationResult, type CancellationRule, evaluateCancellationPolicy } from "./service-shared.js";
|
|
2
|
-
export { _unused, type CancellationResult, type CancellationRule, evaluateCancellationPolicy };
|
|
1
|
+
import { _unused, type CancellationResult, type CancellationRule, type CancellationSegment, evaluateCancellationPolicy, evaluateSegmentedCancellation, type SegmentedCancellationInput, type SegmentedCancellationResult } from "./service-shared.js";
|
|
2
|
+
export { _unused, type CancellationResult, type CancellationRule, type CancellationSegment, evaluateCancellationPolicy, evaluateSegmentedCancellation, type SegmentedCancellationInput, type SegmentedCancellationResult, };
|
|
3
3
|
export declare const policiesService: {
|
|
4
4
|
listPolicies(db: import("drizzle-orm/postgres-js").PostgresJsDatabase, query: import("./service-shared.js").PolicyListQuery): Promise<{
|
|
5
5
|
data: {
|
|
@@ -1256,6 +1256,15 @@ export declare const policiesService: {
|
|
|
1256
1256
|
}[];
|
|
1257
1257
|
} | null>;
|
|
1258
1258
|
evaluateCancellation(db: import("drizzle-orm/postgres-js").PostgresJsDatabase, policyId: string, input: import("./service-shared.js").EvaluateCancellationInput): Promise<CancellationResult | null>;
|
|
1259
|
+
evaluateMultiPolicyCancellation(db: import("drizzle-orm/postgres-js").PostgresJsDatabase, segments: Array<{
|
|
1260
|
+
id?: string;
|
|
1261
|
+
label?: string;
|
|
1262
|
+
policyId: string;
|
|
1263
|
+
totalCents: number;
|
|
1264
|
+
}>, input: {
|
|
1265
|
+
daysBeforeDeparture: number;
|
|
1266
|
+
currency?: string;
|
|
1267
|
+
}): Promise<SegmentedCancellationResult>;
|
|
1259
1268
|
listPolicyAcceptances(db: import("drizzle-orm/postgres-js").PostgresJsDatabase, query: import("./service-shared.js").PolicyAcceptanceListQuery): Promise<{
|
|
1260
1269
|
data: {
|
|
1261
1270
|
id: string;
|
|
@@ -1282,8 +1291,8 @@ export declare const policiesService: {
|
|
|
1282
1291
|
createdAt: Date;
|
|
1283
1292
|
ipAddress: string | null;
|
|
1284
1293
|
userAgent: string | null;
|
|
1285
|
-
personId: string | null;
|
|
1286
1294
|
bookingId: string | null;
|
|
1295
|
+
personId: string | null;
|
|
1287
1296
|
orderId: string | null;
|
|
1288
1297
|
method: "signature" | "implicit" | "explicit_checkbox";
|
|
1289
1298
|
acceptedAt: Date;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/policies/service.ts"],"names":[],"mappings":"AACA,OAAO,EACL,OAAO,EACP,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,0BAA0B,
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/policies/service.ts"],"names":[],"mappings":"AACA,OAAO,EACL,OAAO,EACP,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,0BAA0B,EAC1B,6BAA6B,EAC7B,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,EACjC,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EACL,OAAO,EACP,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,0BAA0B,EAC1B,6BAA6B,EAC7B,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,GACjC,CAAA;AAED,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAGo8b,CAAC;aAAoB,CAAC;;;;;gBAAmH,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CADzmc,CAAA"}
|
package/dist/policies/service.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { policiesCoreService } from "./service-core.js";
|
|
2
|
-
import { _unused, evaluateCancellationPolicy, } from "./service-shared.js";
|
|
3
|
-
export { _unused, evaluateCancellationPolicy };
|
|
2
|
+
import { _unused, evaluateCancellationPolicy, evaluateSegmentedCancellation, } from "./service-shared.js";
|
|
3
|
+
export { _unused, evaluateCancellationPolicy, evaluateSegmentedCancellation, };
|
|
4
4
|
export const policiesService = {
|
|
5
5
|
...policiesCoreService,
|
|
6
6
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voyantjs/legal",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"license": "FSL-1.1-Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -53,14 +53,14 @@
|
|
|
53
53
|
"drizzle-orm": "^0.45.2",
|
|
54
54
|
"hono": "^4.12.10",
|
|
55
55
|
"zod": "^4.3.6",
|
|
56
|
-
"@voyantjs/
|
|
57
|
-
"@voyantjs/
|
|
58
|
-
"@voyantjs/
|
|
59
|
-
"@voyantjs/
|
|
60
|
-
"@voyantjs/
|
|
61
|
-
"@voyantjs/
|
|
62
|
-
"@voyantjs/
|
|
63
|
-
"@voyantjs/
|
|
56
|
+
"@voyantjs/core": "0.10.0",
|
|
57
|
+
"@voyantjs/crm": "0.10.0",
|
|
58
|
+
"@voyantjs/db": "0.10.0",
|
|
59
|
+
"@voyantjs/hono": "0.10.0",
|
|
60
|
+
"@voyantjs/suppliers": "0.10.0",
|
|
61
|
+
"@voyantjs/utils": "0.10.0",
|
|
62
|
+
"@voyantjs/voyant-storage": "0.10.0",
|
|
63
|
+
"@voyantjs/bookings": "0.10.0"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
66
|
"typescript": "^6.0.2",
|