@voyantjs/pricing 0.26.8 → 0.27.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.
Files changed (37) hide show
  1. package/dist/index.d.ts +3 -3
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +2 -2
  4. package/dist/routes-rules.d.ts +172 -9
  5. package/dist/routes-rules.d.ts.map +1 -1
  6. package/dist/routes-rules.js +17 -1
  7. package/dist/schema-departure-overrides.d.ts +228 -0
  8. package/dist/schema-departure-overrides.d.ts.map +1 -0
  9. package/dist/schema-departure-overrides.js +36 -0
  10. package/dist/schema-relations.d.ts +4 -0
  11. package/dist/schema-relations.d.ts.map +1 -1
  12. package/dist/schema-relations.js +8 -0
  13. package/dist/schema.d.ts +1 -0
  14. package/dist/schema.d.ts.map +1 -1
  15. package/dist/schema.js +1 -0
  16. package/dist/service-departure-overrides.d.ts +67 -0
  17. package/dist/service-departure-overrides.d.ts.map +1 -0
  18. package/dist/service-departure-overrides.js +54 -0
  19. package/dist/service-option-rules.d.ts +2 -2
  20. package/dist/service-public.d.ts.map +1 -1
  21. package/dist/service-public.js +78 -3
  22. package/dist/service-rule-resolver.d.ts +67 -0
  23. package/dist/service-rule-resolver.d.ts.map +1 -0
  24. package/dist/service-rule-resolver.js +200 -0
  25. package/dist/service-shared.d.ts +4 -1
  26. package/dist/service-shared.d.ts.map +1 -1
  27. package/dist/service-transfer-rules.d.ts +6 -6
  28. package/dist/service.d.ts +6 -0
  29. package/dist/service.d.ts.map +1 -1
  30. package/dist/service.js +6 -0
  31. package/dist/validation-public.d.ts +2 -0
  32. package/dist/validation-public.d.ts.map +1 -1
  33. package/dist/validation-public.js +2 -0
  34. package/dist/validation.d.ts +47 -0
  35. package/dist/validation.d.ts.map +1 -1
  36. package/dist/validation.js +20 -0
  37. package/package.json +9 -8
@@ -0,0 +1,67 @@
1
+ import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
2
+ import { type CreateDeparturePriceOverrideInput, type DeparturePriceOverrideListQuery, type UpdateDeparturePriceOverrideInput } from "./service-shared.js";
3
+ export declare function listDeparturePriceOverrides(db: PostgresJsDatabase, query: DeparturePriceOverrideListQuery): Promise<{
4
+ data: {
5
+ id: string;
6
+ departureId: string;
7
+ optionId: string;
8
+ optionUnitId: string;
9
+ priceCatalogId: string;
10
+ sellAmountCents: number;
11
+ costAmountCents: number | null;
12
+ notes: string | null;
13
+ active: boolean;
14
+ metadata: Record<string, unknown> | null;
15
+ createdAt: Date;
16
+ updatedAt: Date;
17
+ }[];
18
+ total: number;
19
+ limit: number;
20
+ offset: number;
21
+ }>;
22
+ export declare function getDeparturePriceOverrideById(db: PostgresJsDatabase, id: string): Promise<{
23
+ id: string;
24
+ departureId: string;
25
+ optionId: string;
26
+ optionUnitId: string;
27
+ priceCatalogId: string;
28
+ sellAmountCents: number;
29
+ costAmountCents: number | null;
30
+ notes: string | null;
31
+ active: boolean;
32
+ metadata: Record<string, unknown> | null;
33
+ createdAt: Date;
34
+ updatedAt: Date;
35
+ } | null>;
36
+ export declare function createDeparturePriceOverride(db: PostgresJsDatabase, data: CreateDeparturePriceOverrideInput): Promise<{
37
+ metadata: Record<string, unknown> | null;
38
+ id: string;
39
+ createdAt: Date;
40
+ updatedAt: Date;
41
+ notes: string | null;
42
+ active: boolean;
43
+ priceCatalogId: string;
44
+ optionId: string;
45
+ departureId: string;
46
+ optionUnitId: string;
47
+ sellAmountCents: number;
48
+ costAmountCents: number | null;
49
+ } | null>;
50
+ export declare function updateDeparturePriceOverride(db: PostgresJsDatabase, id: string, data: UpdateDeparturePriceOverrideInput): Promise<{
51
+ id: string;
52
+ departureId: string;
53
+ optionId: string;
54
+ optionUnitId: string;
55
+ priceCatalogId: string;
56
+ sellAmountCents: number;
57
+ costAmountCents: number | null;
58
+ notes: string | null;
59
+ active: boolean;
60
+ metadata: Record<string, unknown> | null;
61
+ createdAt: Date;
62
+ updatedAt: Date;
63
+ } | null>;
64
+ export declare function deleteDeparturePriceOverride(db: PostgresJsDatabase, id: string): Promise<{
65
+ id: string;
66
+ } | null>;
67
+ //# sourceMappingURL=service-departure-overrides.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-departure-overrides.d.ts","sourceRoot":"","sources":["../src/service-departure-overrides.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAGjE,OAAO,EACL,KAAK,iCAAiC,EACtC,KAAK,+BAA+B,EAEpC,KAAK,iCAAiC,EACvC,MAAM,qBAAqB,CAAA;AAE5B,wBAAsB,2BAA2B,CAC/C,EAAE,EAAE,kBAAkB,EACtB,KAAK,EAAE,+BAA+B;;;;;;;;;;;;;;;;;;GA4BvC;AAED,wBAAsB,6BAA6B,CAAC,EAAE,EAAE,kBAAkB,EAAE,EAAE,EAAE,MAAM;;;;;;;;;;;;;UAOrF;AAED,wBAAsB,4BAA4B,CAChD,EAAE,EAAE,kBAAkB,EACtB,IAAI,EAAE,iCAAiC;;;;;;;;;;;;;UAIxC;AAED,wBAAsB,4BAA4B,CAChD,EAAE,EAAE,kBAAkB,EACtB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,iCAAiC;;;;;;;;;;;;;UAQxC;AAED,wBAAsB,4BAA4B,CAAC,EAAE,EAAE,kBAAkB,EAAE,EAAE,EAAE,MAAM;;UAMpF"}
@@ -0,0 +1,54 @@
1
+ import { and, desc, eq, sql } from "drizzle-orm";
2
+ import { departurePriceOverrides } from "./schema.js";
3
+ import { paginate, } from "./service-shared.js";
4
+ export async function listDeparturePriceOverrides(db, query) {
5
+ const conditions = [];
6
+ if (query.departureId)
7
+ conditions.push(eq(departurePriceOverrides.departureId, query.departureId));
8
+ if (query.optionId)
9
+ conditions.push(eq(departurePriceOverrides.optionId, query.optionId));
10
+ if (query.optionUnitId) {
11
+ conditions.push(eq(departurePriceOverrides.optionUnitId, query.optionUnitId));
12
+ }
13
+ if (query.priceCatalogId) {
14
+ conditions.push(eq(departurePriceOverrides.priceCatalogId, query.priceCatalogId));
15
+ }
16
+ if (query.active !== undefined) {
17
+ conditions.push(eq(departurePriceOverrides.active, query.active));
18
+ }
19
+ const where = conditions.length ? and(...conditions) : undefined;
20
+ return paginate(db
21
+ .select()
22
+ .from(departurePriceOverrides)
23
+ .where(where)
24
+ .limit(query.limit)
25
+ .offset(query.offset)
26
+ .orderBy(desc(departurePriceOverrides.updatedAt)), db.select({ count: sql `count(*)::int` }).from(departurePriceOverrides).where(where), query.limit, query.offset);
27
+ }
28
+ export async function getDeparturePriceOverrideById(db, id) {
29
+ const [row] = await db
30
+ .select()
31
+ .from(departurePriceOverrides)
32
+ .where(eq(departurePriceOverrides.id, id))
33
+ .limit(1);
34
+ return row ?? null;
35
+ }
36
+ export async function createDeparturePriceOverride(db, data) {
37
+ const [row] = await db.insert(departurePriceOverrides).values(data).returning();
38
+ return row ?? null;
39
+ }
40
+ export async function updateDeparturePriceOverride(db, id, data) {
41
+ const [row] = await db
42
+ .update(departurePriceOverrides)
43
+ .set({ ...data, updatedAt: new Date() })
44
+ .where(eq(departurePriceOverrides.id, id))
45
+ .returning();
46
+ return row ?? null;
47
+ }
48
+ export async function deleteDeparturePriceOverride(db, id) {
49
+ const [row] = await db
50
+ .delete(departurePriceOverrides)
51
+ .where(eq(departurePriceOverrides.id, id))
52
+ .returning({ id: departurePriceOverrides.id });
53
+ return row ?? null;
54
+ }
@@ -152,10 +152,10 @@ export declare function createOptionUnitPriceRule(db: PostgresJsDatabase, data:
152
152
  unitId: string;
153
153
  sortOrder: number;
154
154
  pricingCategoryId: string | null;
155
- pricingMode: "per_person" | "per_booking" | "free" | "on_request" | "per_unit" | "included";
156
- optionPriceRuleId: string;
157
155
  sellAmountCents: number | null;
158
156
  costAmountCents: number | null;
157
+ pricingMode: "per_person" | "per_booking" | "free" | "on_request" | "per_unit" | "included";
158
+ optionPriceRuleId: string;
159
159
  minQuantity: number | null;
160
160
  maxQuantity: number | null;
161
161
  } | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"service-public.d.ts","sourceRoot":"","sources":["../src/service-public.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AASjE,OAAO,KAAK,EACV,+BAA+B,EAC/B,yBAAyB,EAC1B,MAAM,wBAAwB,CAAA;AAwE/B,eAAO,MAAM,oBAAoB;kCAEzB,kBAAkB,aACX,MAAM,SACV,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCA0R5B,kBAAkB,aACX,MAAM,SACV,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;CAgGzC,CAAA"}
1
+ {"version":3,"file":"service-public.d.ts","sourceRoot":"","sources":["../src/service-public.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAgBjE,OAAO,KAAK,EACV,+BAA+B,EAC/B,yBAAyB,EAC1B,MAAM,wBAAwB,CAAA;AA+J/B,eAAO,MAAM,oBAAoB;kCAEzB,kBAAkB,aACX,MAAM,SACV,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAyS5B,kBAAkB,aACX,MAAM,SACV,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;CAgGzC,CAAA"}
@@ -1,7 +1,8 @@
1
1
  import { availabilitySlots, availabilityStartTimes } from "@voyantjs/availability/schema";
2
2
  import { optionUnits, productOptions, products } from "@voyantjs/products/schema";
3
3
  import { and, asc, desc, eq, gte, inArray, lte, ne, or, sql } from "drizzle-orm";
4
- import { optionPriceRules, optionStartTimeRules, optionUnitPriceRules, optionUnitTiers, priceCatalogs, } from "./schema.js";
4
+ import { optionPriceRules, optionStartTimeRules, optionUnitPriceRules, optionUnitTiers, priceCatalogs, priceSchedules, } from "./schema.js";
5
+ import { loadDeparturePriceOverrides, pickRulesForDate, } from "./service-rule-resolver.js";
5
6
  function normalizeDate(value) {
6
7
  if (!value) {
7
8
  return null;
@@ -48,6 +49,68 @@ async function resolvePublicCatalog(db, input) {
48
49
  .limit(1);
49
50
  return catalog ?? null;
50
51
  }
52
+ async function resolveQueryDate(db, query) {
53
+ if (query.date)
54
+ return query.date;
55
+ if (!query.departureId)
56
+ return null;
57
+ const [slot] = await db
58
+ .select({ dateLocal: availabilitySlots.dateLocal })
59
+ .from(availabilitySlots)
60
+ .where(eq(availabilitySlots.id, query.departureId))
61
+ .limit(1);
62
+ return slot?.dateLocal ?? null;
63
+ }
64
+ async function narrowRulesByDate(db, rules, isoDate) {
65
+ if (rules.length === 0)
66
+ return rules;
67
+ const scheduleIds = Array.from(new Set(rules.map((r) => r.priceScheduleId).filter((id) => id !== null)));
68
+ const schedules = scheduleIds.length > 0
69
+ ? await db
70
+ .select({
71
+ id: priceSchedules.id,
72
+ active: priceSchedules.active,
73
+ priority: priceSchedules.priority,
74
+ recurrenceRule: priceSchedules.recurrenceRule,
75
+ validFrom: priceSchedules.validFrom,
76
+ validTo: priceSchedules.validTo,
77
+ weekdays: priceSchedules.weekdays,
78
+ timezone: priceSchedules.timezone,
79
+ })
80
+ .from(priceSchedules)
81
+ .where(inArray(priceSchedules.id, scheduleIds))
82
+ : [];
83
+ const scheduleMap = new Map(schedules.map((s) => [
84
+ s.id,
85
+ {
86
+ id: s.id,
87
+ active: s.active,
88
+ priority: s.priority,
89
+ recurrenceRule: s.recurrenceRule,
90
+ validFrom: s.validFrom,
91
+ validTo: s.validTo,
92
+ weekdays: s.weekdays ?? null,
93
+ timezone: s.timezone,
94
+ },
95
+ ]));
96
+ const rulesByOption = new Map();
97
+ for (const r of rules) {
98
+ const existing = rulesByOption.get(r.optionId) ?? [];
99
+ existing.push(r);
100
+ rulesByOption.set(r.optionId, existing);
101
+ }
102
+ const winners = [];
103
+ for (const [, candidateRules] of rulesByOption) {
104
+ const picked = pickRulesForDate(candidateRules, scheduleMap, isoDate);
105
+ const winnerId = picked[0]?.id;
106
+ if (!winnerId)
107
+ continue;
108
+ const winner = candidateRules.find((r) => r.id === winnerId);
109
+ if (winner)
110
+ winners.push(winner);
111
+ }
112
+ return winners;
113
+ }
51
114
  export const publicPricingService = {
52
115
  async getProductPricingSnapshot(db, productId, query) {
53
116
  const product = await ensurePublicProduct(db, productId);
@@ -87,7 +150,14 @@ export const publicPricingService = {
87
150
  };
88
151
  }
89
152
  const optionIds = options.map((option) => option.id);
90
- const [units, rules] = await Promise.all([
153
+ const resolvedDate = await resolveQueryDate(db, query);
154
+ const overridesByUnit = query.departureId
155
+ ? await loadDeparturePriceOverrides(db, {
156
+ departureId: query.departureId,
157
+ catalogId: catalog.id,
158
+ })
159
+ : new Map();
160
+ const [units, allRules] = await Promise.all([
91
161
  db
92
162
  .select({
93
163
  id: optionUnits.id,
@@ -112,11 +182,13 @@ export const publicPricingService = {
112
182
  maxPerBooking: optionPriceRules.maxPerBooking,
113
183
  isDefault: optionPriceRules.isDefault,
114
184
  cancellationPolicyId: optionPriceRules.cancellationPolicyId,
185
+ priceScheduleId: optionPriceRules.priceScheduleId,
115
186
  })
116
187
  .from(optionPriceRules)
117
188
  .where(and(eq(optionPriceRules.productId, productId), inArray(optionPriceRules.optionId, optionIds), eq(optionPriceRules.priceCatalogId, catalog.id), eq(optionPriceRules.active, true)))
118
189
  .orderBy(desc(optionPriceRules.isDefault), asc(optionPriceRules.name)),
119
190
  ]);
191
+ const rules = resolvedDate ? await narrowRulesByDate(db, allRules, resolvedDate) : allRules;
120
192
  const ruleIds = rules.map((rule) => rule.id);
121
193
  const [unitPrices, startTimeAdjustments] = await Promise.all([
122
194
  ruleIds.length > 0
@@ -235,13 +307,16 @@ export const publicPricingService = {
235
307
  if (!unit) {
236
308
  return null;
237
309
  }
310
+ const override = overridesByUnit.get(unit.unitId);
238
311
  return {
239
312
  id: unitPrice.id,
240
313
  unitId: unit.unitId,
241
314
  unitName: unit.unitName,
242
315
  unitType: unit.unitType,
243
316
  pricingMode: unitPrice.pricingMode,
244
- sellAmountCents: unitPrice.sellAmountCents ?? null,
317
+ sellAmountCents: override
318
+ ? override.sellAmountCents
319
+ : (unitPrice.sellAmountCents ?? null),
245
320
  minQuantity: unitPrice.minQuantity ?? null,
246
321
  maxQuantity: unitPrice.maxQuantity ?? null,
247
322
  pricingCategoryId: unitPrice.pricingCategoryId ?? null,
@@ -0,0 +1,67 @@
1
+ import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
2
+ export interface ResolverRuleInput {
3
+ id: string;
4
+ name: string;
5
+ isDefault: boolean;
6
+ priceScheduleId: string | null;
7
+ }
8
+ export interface ResolverScheduleInput {
9
+ id: string;
10
+ active: boolean;
11
+ priority: number;
12
+ recurrenceRule: string;
13
+ validFrom: string | null;
14
+ validTo: string | null;
15
+ weekdays: string[] | null;
16
+ timezone: string | null;
17
+ }
18
+ /**
19
+ * Pick the option price rule that applies to a given date, given a set of
20
+ * candidate rules and their schedules.
21
+ *
22
+ * - Rules with a matching schedule beat rules without one.
23
+ * - Among scheduled matches, highest `priority` wins. Ties: `isDefault` first,
24
+ * then alphabetic by `name`.
25
+ * - When no schedule matches, a rule with `isDefault=true` and no schedule acts
26
+ * as the fallback. Without one, returns an empty array.
27
+ */
28
+ export declare function pickRulesForDate(rules: ResolverRuleInput[], schedules: Map<string, ResolverScheduleInput>, isoDate: string): ResolverRuleInput[];
29
+ export interface ResolveOptionPriceRulesParams {
30
+ productId: string;
31
+ optionIds: string[];
32
+ catalogId: string;
33
+ date: string;
34
+ }
35
+ /**
36
+ * DB-backed wrapper around `pickRulesForDate`. Fetches active rules for the
37
+ * product/option/catalog plus their schedules, then picks the winning rule
38
+ * per option for the given date.
39
+ *
40
+ * Returns a Map keyed by optionId. Options whose rules don't match the date
41
+ * (and have no default) are absent from the map.
42
+ */
43
+ export declare function resolveOptionPriceRulesForDate(db: PostgresJsDatabase, params: ResolveOptionPriceRulesParams): Promise<Map<string, ResolverRuleInput>>;
44
+ /**
45
+ * Per-departure price override applied to a specific unit, keyed by unitId.
46
+ * Resolved AFTER rule selection: the rule's per-unit price gets replaced with
47
+ * the override's amount for any matching unit. Units without an override fall
48
+ * through to the rule's normal price.
49
+ */
50
+ export interface UnitPriceOverride {
51
+ id: string;
52
+ unitId: string;
53
+ sellAmountCents: number;
54
+ costAmountCents: number | null;
55
+ }
56
+ /**
57
+ * Fetch active per-unit price overrides for a given departure + catalog.
58
+ *
59
+ * Returns a Map keyed by `optionUnitId` so callers can apply overrides while
60
+ * iterating per-unit prices in a snapshot. Inactive overrides are excluded at
61
+ * query time.
62
+ */
63
+ export declare function loadDeparturePriceOverrides(db: PostgresJsDatabase, params: {
64
+ departureId: string;
65
+ catalogId: string;
66
+ }): Promise<Map<string, UnitPriceOverride>>;
67
+ //# sourceMappingURL=service-rule-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-rule-resolver.d.ts","sourceRoot":"","sources":["../src/service-rule-resolver.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAOjE,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,OAAO,CAAA;IAClB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;CAC/B;AAED,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,OAAO,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,cAAc,EAAE,MAAM,CAAA;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB;AAoED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,iBAAiB,EAAE,EAC1B,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC,EAC7C,OAAO,EAAE,MAAM,GACd,iBAAiB,EAAE,CAgCrB;AAED,MAAM,WAAW,6BAA6B;IAC5C,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACb;AAED;;;;;;;GAOG;AACH,wBAAsB,8BAA8B,CAClD,EAAE,EAAE,kBAAkB,EACtB,MAAM,EAAE,6BAA6B,GACpC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CA8EzC;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,eAAe,EAAE,MAAM,CAAA;IACvB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;CAC/B;AAED;;;;;;GAMG;AACH,wBAAsB,2BAA2B,CAC/C,EAAE,EAAE,kBAAkB,EACtB,MAAM,EAAE;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACjD,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CA4BzC"}
@@ -0,0 +1,200 @@
1
+ import { and, eq, inArray } from "drizzle-orm";
2
+ import { rrulestr } from "rrule";
3
+ import { priceSchedules } from "./schema-catalogs.js";
4
+ import { departurePriceOverrides } from "./schema-departure-overrides.js";
5
+ import { optionPriceRules } from "./schema-option-rules.js";
6
+ const ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
7
+ const WEEKDAY_CODES = ["SU", "MO", "TU", "WE", "TH", "FR", "SA"];
8
+ function weekdayCode(isoDate) {
9
+ const d = new Date(`${isoDate}T00:00:00Z`);
10
+ return WEEKDAY_CODES[d.getUTCDay()] ?? "MO";
11
+ }
12
+ function dateInWindow(isoDate, from, to) {
13
+ if (from && isoDate < from)
14
+ return false;
15
+ if (to && isoDate > to)
16
+ return false;
17
+ return true;
18
+ }
19
+ function rruleMatchesDate(ruleString, isoDate, anchor) {
20
+ const trimmed = ruleString.trim();
21
+ if (trimmed === "")
22
+ return true;
23
+ const dtstart = `${anchor.replace(/-/g, "")}T000000Z`;
24
+ const hasDtstart = /(?:^|\n)DTSTART[:;]/.test(trimmed);
25
+ const hasRrule = /(?:^|\n)RRULE[:;]/.test(trimmed);
26
+ const body = hasRrule ? trimmed : `RRULE:${trimmed}`;
27
+ const fullRule = hasDtstart ? body : `DTSTART:${dtstart}\n${body}`;
28
+ let parsed;
29
+ try {
30
+ parsed = rrulestr(fullRule);
31
+ }
32
+ catch {
33
+ return false;
34
+ }
35
+ const start = new Date(`${isoDate}T00:00:00Z`);
36
+ const end = new Date(start.getTime() + 24 * 60 * 60 * 1000);
37
+ const occurrences = parsed.between(start, end, true);
38
+ return occurrences.some((occ) => occ.toISOString().slice(0, 10) === isoDate);
39
+ }
40
+ function scheduleMatchesDate(s, isoDate) {
41
+ if (!s.active)
42
+ return false;
43
+ if (!dateInWindow(isoDate, s.validFrom, s.validTo))
44
+ return false;
45
+ if (s.weekdays && s.weekdays.length > 0) {
46
+ if (!s.weekdays.includes(weekdayCode(isoDate)))
47
+ return false;
48
+ }
49
+ const anchor = s.validFrom ?? "2000-01-01";
50
+ if (!rruleMatchesDate(s.recurrenceRule, isoDate, anchor))
51
+ return false;
52
+ return true;
53
+ }
54
+ function compareMatches(a, b) {
55
+ if (b.priority !== a.priority)
56
+ return b.priority - a.priority;
57
+ const aDef = a.rule.isDefault ? 1 : 0;
58
+ const bDef = b.rule.isDefault ? 1 : 0;
59
+ if (aDef !== bDef)
60
+ return bDef - aDef;
61
+ return a.rule.name.localeCompare(b.rule.name);
62
+ }
63
+ /**
64
+ * Pick the option price rule that applies to a given date, given a set of
65
+ * candidate rules and their schedules.
66
+ *
67
+ * - Rules with a matching schedule beat rules without one.
68
+ * - Among scheduled matches, highest `priority` wins. Ties: `isDefault` first,
69
+ * then alphabetic by `name`.
70
+ * - When no schedule matches, a rule with `isDefault=true` and no schedule acts
71
+ * as the fallback. Without one, returns an empty array.
72
+ */
73
+ export function pickRulesForDate(rules, schedules, isoDate) {
74
+ if (!ISO_DATE_RE.test(isoDate)) {
75
+ throw new Error(`pickRulesForDate: expected ISO yyyy-mm-dd, got "${isoDate}"`);
76
+ }
77
+ const matches = [];
78
+ for (const rule of rules) {
79
+ if (rule.priceScheduleId === null) {
80
+ if (rule.isDefault) {
81
+ matches.push({ rule, priority: Number.NEGATIVE_INFINITY, scheduled: false });
82
+ }
83
+ continue;
84
+ }
85
+ const schedule = schedules.get(rule.priceScheduleId);
86
+ if (!schedule)
87
+ continue;
88
+ if (!scheduleMatchesDate(schedule, isoDate))
89
+ continue;
90
+ matches.push({ rule, priority: schedule.priority, scheduled: true });
91
+ }
92
+ if (matches.length === 0)
93
+ return [];
94
+ const scheduled = matches.filter((m) => m.scheduled);
95
+ if (scheduled.length > 0) {
96
+ scheduled.sort(compareMatches);
97
+ const winner = scheduled[0];
98
+ return winner ? [winner.rule] : [];
99
+ }
100
+ matches.sort(compareMatches);
101
+ const winner = matches[0];
102
+ return winner ? [winner.rule] : [];
103
+ }
104
+ /**
105
+ * DB-backed wrapper around `pickRulesForDate`. Fetches active rules for the
106
+ * product/option/catalog plus their schedules, then picks the winning rule
107
+ * per option for the given date.
108
+ *
109
+ * Returns a Map keyed by optionId. Options whose rules don't match the date
110
+ * (and have no default) are absent from the map.
111
+ */
112
+ export async function resolveOptionPriceRulesForDate(db, params) {
113
+ if (params.optionIds.length === 0)
114
+ return new Map();
115
+ const rules = await db
116
+ .select({
117
+ id: optionPriceRules.id,
118
+ optionId: optionPriceRules.optionId,
119
+ name: optionPriceRules.name,
120
+ isDefault: optionPriceRules.isDefault,
121
+ priceScheduleId: optionPriceRules.priceScheduleId,
122
+ })
123
+ .from(optionPriceRules)
124
+ .where(and(eq(optionPriceRules.productId, params.productId), inArray(optionPriceRules.optionId, params.optionIds), eq(optionPriceRules.priceCatalogId, params.catalogId), eq(optionPriceRules.active, true)));
125
+ const scheduleIds = Array.from(new Set(rules.map((r) => r.priceScheduleId).filter((id) => id !== null)));
126
+ const schedules = scheduleIds.length > 0
127
+ ? await db
128
+ .select({
129
+ id: priceSchedules.id,
130
+ active: priceSchedules.active,
131
+ priority: priceSchedules.priority,
132
+ recurrenceRule: priceSchedules.recurrenceRule,
133
+ validFrom: priceSchedules.validFrom,
134
+ validTo: priceSchedules.validTo,
135
+ weekdays: priceSchedules.weekdays,
136
+ timezone: priceSchedules.timezone,
137
+ })
138
+ .from(priceSchedules)
139
+ .where(inArray(priceSchedules.id, scheduleIds))
140
+ : [];
141
+ const scheduleMap = new Map(schedules.map((s) => [
142
+ s.id,
143
+ {
144
+ id: s.id,
145
+ active: s.active,
146
+ priority: s.priority,
147
+ recurrenceRule: s.recurrenceRule,
148
+ validFrom: s.validFrom,
149
+ validTo: s.validTo,
150
+ weekdays: s.weekdays ?? null,
151
+ timezone: s.timezone,
152
+ },
153
+ ]));
154
+ const rulesByOption = new Map();
155
+ for (const r of rules) {
156
+ const existing = rulesByOption.get(r.optionId) ?? [];
157
+ existing.push({
158
+ id: r.id,
159
+ name: r.name,
160
+ isDefault: r.isDefault,
161
+ priceScheduleId: r.priceScheduleId,
162
+ });
163
+ rulesByOption.set(r.optionId, existing);
164
+ }
165
+ const result = new Map();
166
+ for (const [optionId, candidateRules] of rulesByOption) {
167
+ const picked = pickRulesForDate(candidateRules, scheduleMap, params.date);
168
+ const first = picked[0];
169
+ if (first)
170
+ result.set(optionId, first);
171
+ }
172
+ return result;
173
+ }
174
+ /**
175
+ * Fetch active per-unit price overrides for a given departure + catalog.
176
+ *
177
+ * Returns a Map keyed by `optionUnitId` so callers can apply overrides while
178
+ * iterating per-unit prices in a snapshot. Inactive overrides are excluded at
179
+ * query time.
180
+ */
181
+ export async function loadDeparturePriceOverrides(db, params) {
182
+ const rows = await db
183
+ .select({
184
+ id: departurePriceOverrides.id,
185
+ optionUnitId: departurePriceOverrides.optionUnitId,
186
+ sellAmountCents: departurePriceOverrides.sellAmountCents,
187
+ costAmountCents: departurePriceOverrides.costAmountCents,
188
+ })
189
+ .from(departurePriceOverrides)
190
+ .where(and(eq(departurePriceOverrides.departureId, params.departureId), eq(departurePriceOverrides.priceCatalogId, params.catalogId), eq(departurePriceOverrides.active, true)));
191
+ return new Map(rows.map((r) => [
192
+ r.optionUnitId,
193
+ {
194
+ id: r.id,
195
+ unitId: r.optionUnitId,
196
+ sellAmountCents: r.sellAmountCents,
197
+ costAmountCents: r.costAmountCents,
198
+ },
199
+ ]));
200
+ }
@@ -1,5 +1,5 @@
1
1
  import type { z } from "zod";
2
- import type { cancellationPolicyListQuerySchema, cancellationPolicyRuleListQuerySchema, dropoffPriceRuleListQuerySchema, extraPriceRuleListQuerySchema, insertCancellationPolicyRuleSchema, insertCancellationPolicySchema, insertDropoffPriceRuleSchema, insertExtraPriceRuleSchema, insertOptionPriceRuleSchema, insertOptionStartTimeRuleSchema, insertOptionUnitPriceRuleSchema, insertOptionUnitTierSchema, insertPickupPriceRuleSchema, insertPriceCatalogSchema, insertPriceScheduleSchema, insertPricingCategoryDependencySchema, insertPricingCategorySchema, optionPriceRuleListQuerySchema, optionStartTimeRuleListQuerySchema, optionUnitPriceRuleListQuerySchema, optionUnitTierListQuerySchema, pickupPriceRuleListQuerySchema, priceCatalogListQuerySchema, priceScheduleListQuerySchema, pricingCategoryDependencyListQuerySchema, pricingCategoryListQuerySchema, updateCancellationPolicyRuleSchema, updateCancellationPolicySchema, updateDropoffPriceRuleSchema, updateExtraPriceRuleSchema, updateOptionPriceRuleSchema, updateOptionStartTimeRuleSchema, updateOptionUnitPriceRuleSchema, updateOptionUnitTierSchema, updatePickupPriceRuleSchema, updatePriceCatalogSchema, updatePriceScheduleSchema, updatePricingCategoryDependencySchema, updatePricingCategorySchema } from "./validation.js";
2
+ import type { cancellationPolicyListQuerySchema, cancellationPolicyRuleListQuerySchema, departurePriceOverrideListQuerySchema, dropoffPriceRuleListQuerySchema, extraPriceRuleListQuerySchema, insertCancellationPolicyRuleSchema, insertCancellationPolicySchema, insertDeparturePriceOverrideSchema, insertDropoffPriceRuleSchema, insertExtraPriceRuleSchema, insertOptionPriceRuleSchema, insertOptionStartTimeRuleSchema, insertOptionUnitPriceRuleSchema, insertOptionUnitTierSchema, insertPickupPriceRuleSchema, insertPriceCatalogSchema, insertPriceScheduleSchema, insertPricingCategoryDependencySchema, insertPricingCategorySchema, optionPriceRuleListQuerySchema, optionStartTimeRuleListQuerySchema, optionUnitPriceRuleListQuerySchema, optionUnitTierListQuerySchema, pickupPriceRuleListQuerySchema, priceCatalogListQuerySchema, priceScheduleListQuerySchema, pricingCategoryDependencyListQuerySchema, pricingCategoryListQuerySchema, updateCancellationPolicyRuleSchema, updateCancellationPolicySchema, updateDeparturePriceOverrideSchema, updateDropoffPriceRuleSchema, updateExtraPriceRuleSchema, updateOptionPriceRuleSchema, updateOptionStartTimeRuleSchema, updateOptionUnitPriceRuleSchema, updateOptionUnitTierSchema, updatePickupPriceRuleSchema, updatePriceCatalogSchema, updatePriceScheduleSchema, updatePricingCategoryDependencySchema, updatePricingCategorySchema } from "./validation.js";
3
3
  export type PricingCategoryListQuery = z.infer<typeof pricingCategoryListQuerySchema>;
4
4
  export type PricingCategoryDependencyListQuery = z.infer<typeof pricingCategoryDependencyListQuerySchema>;
5
5
  export type CancellationPolicyListQuery = z.infer<typeof cancellationPolicyListQuerySchema>;
@@ -13,6 +13,7 @@ export type OptionUnitTierListQuery = z.infer<typeof optionUnitTierListQuerySche
13
13
  export type PickupPriceRuleListQuery = z.infer<typeof pickupPriceRuleListQuerySchema>;
14
14
  export type DropoffPriceRuleListQuery = z.infer<typeof dropoffPriceRuleListQuerySchema>;
15
15
  export type ExtraPriceRuleListQuery = z.infer<typeof extraPriceRuleListQuerySchema>;
16
+ export type DeparturePriceOverrideListQuery = z.infer<typeof departurePriceOverrideListQuerySchema>;
16
17
  export type CreatePricingCategoryInput = z.infer<typeof insertPricingCategorySchema>;
17
18
  export type UpdatePricingCategoryInput = z.infer<typeof updatePricingCategorySchema>;
18
19
  export type CreatePricingCategoryDependencyInput = z.infer<typeof insertPricingCategoryDependencySchema>;
@@ -39,6 +40,8 @@ export type CreateDropoffPriceRuleInput = z.infer<typeof insertDropoffPriceRuleS
39
40
  export type UpdateDropoffPriceRuleInput = z.infer<typeof updateDropoffPriceRuleSchema>;
40
41
  export type CreateExtraPriceRuleInput = z.infer<typeof insertExtraPriceRuleSchema>;
41
42
  export type UpdateExtraPriceRuleInput = z.infer<typeof updateExtraPriceRuleSchema>;
43
+ export type CreateDeparturePriceOverrideInput = z.infer<typeof insertDeparturePriceOverrideSchema>;
44
+ export type UpdateDeparturePriceOverrideInput = z.infer<typeof updateDeparturePriceOverrideSchema>;
42
45
  export declare function paginate<T extends object>(rowsQuery: Promise<T[]>, countQuery: Promise<Array<{
43
46
  count: number;
44
47
  }>>, limit: number, offset: number): Promise<{
@@ -1 +1 @@
1
- {"version":3,"file":"service-shared.d.ts","sourceRoot":"","sources":["../src/service-shared.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"service-shared.d.ts","sourceRoot":"","sources":["../src/service-shared.ts"],"names":[],"mappings":"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"}
@@ -41,10 +41,10 @@ export declare function createPickupPriceRule(db: PostgresJsDatabase, data: Crea
41
41
  active: boolean;
42
42
  optionId: string;
43
43
  sortOrder: number;
44
- pricingMode: "per_person" | "per_booking" | "on_request" | "included" | "unavailable";
45
- optionPriceRuleId: string;
46
44
  sellAmountCents: number | null;
47
45
  costAmountCents: number | null;
46
+ pricingMode: "per_person" | "per_booking" | "on_request" | "included" | "unavailable";
47
+ optionPriceRuleId: string;
48
48
  pickupPointId: string;
49
49
  } | null>;
50
50
  export declare function updatePickupPriceRule(db: PostgresJsDatabase, id: string, data: UpdatePickupPriceRuleInput): Promise<{
@@ -109,10 +109,10 @@ export declare function createDropoffPriceRule(db: PostgresJsDatabase, data: Cre
109
109
  active: boolean;
110
110
  optionId: string;
111
111
  sortOrder: number;
112
- pricingMode: "per_person" | "per_booking" | "on_request" | "included" | "unavailable";
113
- optionPriceRuleId: string;
114
112
  sellAmountCents: number | null;
115
113
  costAmountCents: number | null;
114
+ pricingMode: "per_person" | "per_booking" | "on_request" | "included" | "unavailable";
115
+ optionPriceRuleId: string;
116
116
  facilityId: string | null;
117
117
  dropoffCode: string | null;
118
118
  dropoffName: string;
@@ -182,10 +182,10 @@ export declare function createExtraPriceRule(db: PostgresJsDatabase, data: Creat
182
182
  active: boolean;
183
183
  optionId: string;
184
184
  sortOrder: number;
185
- pricingMode: "per_person" | "per_booking" | "on_request" | "included" | "unavailable";
186
- optionPriceRuleId: string;
187
185
  sellAmountCents: number | null;
188
186
  costAmountCents: number | null;
187
+ pricingMode: "per_person" | "per_booking" | "on_request" | "included" | "unavailable";
188
+ optionPriceRuleId: string;
189
189
  productExtraId: string | null;
190
190
  optionExtraConfigId: string | null;
191
191
  } | null>;
package/dist/service.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { createPriceCatalog, createPriceSchedule, deletePriceCatalog, deletePriceSchedule, getPriceCatalogById, getPriceScheduleById, listPriceCatalogs, listPriceSchedules, updatePriceCatalog, updatePriceSchedule } from "./service-catalogs.js";
2
2
  import { createPricingCategory, createPricingCategoryDependency, deletePricingCategory, deletePricingCategoryDependency, getPricingCategoryById, getPricingCategoryDependencyById, listPricingCategories, listPricingCategoryDependencies, updatePricingCategory, updatePricingCategoryDependency } from "./service-categories.js";
3
+ import { createDeparturePriceOverride, deleteDeparturePriceOverride, getDeparturePriceOverrideById, listDeparturePriceOverrides, updateDeparturePriceOverride } from "./service-departure-overrides.js";
3
4
  import { createOptionPriceRule, createOptionStartTimeRule, createOptionUnitPriceRule, createOptionUnitTier, deleteOptionPriceRule, deleteOptionStartTimeRule, deleteOptionUnitPriceRule, deleteOptionUnitTier, getOptionPriceRuleById, getOptionStartTimeRuleById, getOptionUnitPriceRuleById, getOptionUnitTierById, listOptionPriceRules, listOptionStartTimeRules, listOptionUnitPriceRules, listOptionUnitTiers, updateOptionPriceRule, updateOptionStartTimeRule, updateOptionUnitPriceRule, updateOptionUnitTier } from "./service-option-rules.js";
4
5
  import { createCancellationPolicy, createCancellationPolicyRule, deleteCancellationPolicy, deleteCancellationPolicyRule, getCancellationPolicyById, getCancellationPolicyRuleById, listCancellationPolicies, listCancellationPolicyRules, updateCancellationPolicy, updateCancellationPolicyRule } from "./service-policies.js";
5
6
  import { createDropoffPriceRule, createExtraPriceRule, createPickupPriceRule, deleteDropoffPriceRule, deleteExtraPriceRule, deletePickupPriceRule, getDropoffPriceRuleById, getExtraPriceRuleById, getPickupPriceRuleById, listDropoffPriceRules, listExtraPriceRules, listPickupPriceRules, updateDropoffPriceRule, updateExtraPriceRule, updatePickupPriceRule } from "./service-transfer-rules.js";
@@ -69,5 +70,10 @@ export declare const pricingService: {
69
70
  createExtraPriceRule: typeof createExtraPriceRule;
70
71
  updateExtraPriceRule: typeof updateExtraPriceRule;
71
72
  deleteExtraPriceRule: typeof deleteExtraPriceRule;
73
+ listDeparturePriceOverrides: typeof listDeparturePriceOverrides;
74
+ getDeparturePriceOverrideById: typeof getDeparturePriceOverrideById;
75
+ createDeparturePriceOverride: typeof createDeparturePriceOverride;
76
+ updateDeparturePriceOverride: typeof updateDeparturePriceOverride;
77
+ deleteDeparturePriceOverride: typeof deleteDeparturePriceOverride;
72
78
  };
73
79
  //# sourceMappingURL=service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,qBAAqB,EACrB,+BAA+B,EAC/B,qBAAqB,EACrB,+BAA+B,EAC/B,sBAAsB,EACtB,gCAAgC,EAChC,qBAAqB,EACrB,+BAA+B,EAC/B,qBAAqB,EACrB,+BAA+B,EAChC,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,yBAAyB,EACzB,oBAAoB,EACpB,qBAAqB,EACrB,yBAAyB,EACzB,yBAAyB,EACzB,oBAAoB,EACpB,sBAAsB,EACtB,0BAA0B,EAC1B,0BAA0B,EAC1B,qBAAqB,EACrB,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,EACxB,mBAAmB,EACnB,qBAAqB,EACrB,yBAAyB,EACzB,yBAAyB,EACzB,oBAAoB,EACrB,MAAM,2BAA2B,CAAA;AAClC,OAAO,EACL,wBAAwB,EACxB,4BAA4B,EAC5B,wBAAwB,EACxB,4BAA4B,EAC5B,yBAAyB,EACzB,6BAA6B,EAC7B,wBAAwB,EACxB,2BAA2B,EAC3B,wBAAwB,EACxB,4BAA4B,EAC7B,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,EACtB,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,sBAAsB,EACtB,oBAAoB,EACpB,qBAAqB,EACtB,MAAM,6BAA6B,CAAA;AAEpC,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkE1B,CAAA"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,qBAAqB,EACrB,+BAA+B,EAC/B,qBAAqB,EACrB,+BAA+B,EAC/B,sBAAsB,EACtB,gCAAgC,EAChC,qBAAqB,EACrB,+BAA+B,EAC/B,qBAAqB,EACrB,+BAA+B,EAChC,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,4BAA4B,EAC5B,4BAA4B,EAC5B,6BAA6B,EAC7B,2BAA2B,EAC3B,4BAA4B,EAC7B,MAAM,kCAAkC,CAAA;AACzC,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,yBAAyB,EACzB,oBAAoB,EACpB,qBAAqB,EACrB,yBAAyB,EACzB,yBAAyB,EACzB,oBAAoB,EACpB,sBAAsB,EACtB,0BAA0B,EAC1B,0BAA0B,EAC1B,qBAAqB,EACrB,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,EACxB,mBAAmB,EACnB,qBAAqB,EACrB,yBAAyB,EACzB,yBAAyB,EACzB,oBAAoB,EACrB,MAAM,2BAA2B,CAAA;AAClC,OAAO,EACL,wBAAwB,EACxB,4BAA4B,EAC5B,wBAAwB,EACxB,4BAA4B,EAC5B,yBAAyB,EACzB,6BAA6B,EAC7B,wBAAwB,EACxB,2BAA2B,EAC3B,wBAAwB,EACxB,4BAA4B,EAC7B,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,EACtB,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,sBAAsB,EACtB,oBAAoB,EACpB,qBAAqB,EACtB,MAAM,6BAA6B,CAAA;AAEpC,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuE1B,CAAA"}