@bash-app/bash-common 30.236.0 → 30.237.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/__tests__/statusEnums.test.js +88 -7
- package/dist/__tests__/statusEnums.test.js.map +1 -1
- package/dist/definitions.d.ts +39 -8
- package/dist/definitions.d.ts.map +1 -1
- package/dist/definitions.js +31 -10
- package/dist/definitions.js.map +1 -1
- package/dist/extendedSchemas.d.ts +6 -0
- package/dist/extendedSchemas.d.ts.map +1 -1
- package/dist/extendedSchemas.js.map +1 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -4
- package/dist/index.js.map +1 -1
- package/dist/mirroredPrismaEnums.d.ts +145 -0
- package/dist/mirroredPrismaEnums.d.ts.map +1 -0
- package/dist/mirroredPrismaEnums.js +136 -0
- package/dist/mirroredPrismaEnums.js.map +1 -0
- package/dist/utils/__tests__/nonprofitUtils.test.d.ts +2 -0
- package/dist/utils/__tests__/nonprofitUtils.test.d.ts.map +1 -0
- package/dist/utils/__tests__/nonprofitUtils.test.js +84 -0
- package/dist/utils/__tests__/nonprofitUtils.test.js.map +1 -0
- package/dist/utils/__tests__/paymentUtils.test.js +87 -0
- package/dist/utils/__tests__/paymentUtils.test.js.map +1 -1
- package/dist/utils/nonprofitUtils.d.ts +21 -0
- package/dist/utils/nonprofitUtils.d.ts.map +1 -0
- package/dist/utils/nonprofitUtils.js +29 -0
- package/dist/utils/nonprofitUtils.js.map +1 -0
- package/dist/utils/paymentUtils.d.ts +23 -0
- package/dist/utils/paymentUtils.d.ts.map +1 -1
- package/dist/utils/paymentUtils.js +24 -7
- package/dist/utils/paymentUtils.js.map +1 -1
- package/dist/utils/service/__tests__/billingCapUtils.test.d.ts +2 -0
- package/dist/utils/service/__tests__/billingCapUtils.test.d.ts.map +1 -0
- package/dist/utils/service/__tests__/billingCapUtils.test.js +120 -0
- package/dist/utils/service/__tests__/billingCapUtils.test.js.map +1 -0
- package/dist/utils/service/__tests__/cancellationPolicyRefundResolver.test.js +1 -1
- package/dist/utils/service/__tests__/cancellationPolicyRefundResolver.test.js.map +1 -1
- package/dist/utils/service/__tests__/eventPromoterPhase3.test.d.ts +2 -0
- package/dist/utils/service/__tests__/eventPromoterPhase3.test.d.ts.map +1 -0
- package/dist/utils/service/__tests__/eventPromoterPhase3.test.js +243 -0
- package/dist/utils/service/__tests__/eventPromoterPhase3.test.js.map +1 -0
- package/dist/utils/service/__tests__/eventPromoterUtils.test.d.ts +2 -0
- package/dist/utils/service/__tests__/eventPromoterUtils.test.d.ts.map +1 -0
- package/dist/utils/service/__tests__/eventPromoterUtils.test.js +333 -0
- package/dist/utils/service/__tests__/eventPromoterUtils.test.js.map +1 -0
- package/dist/utils/service/__tests__/offerAllowListUtils.test.d.ts +2 -0
- package/dist/utils/service/__tests__/offerAllowListUtils.test.d.ts.map +1 -0
- package/dist/utils/service/__tests__/offerAllowListUtils.test.js +52 -0
- package/dist/utils/service/__tests__/offerAllowListUtils.test.js.map +1 -0
- package/dist/utils/service/__tests__/offerComparisonUtils.test.d.ts +2 -0
- package/dist/utils/service/__tests__/offerComparisonUtils.test.d.ts.map +1 -0
- package/dist/utils/service/__tests__/offerComparisonUtils.test.js +111 -0
- package/dist/utils/service/__tests__/offerComparisonUtils.test.js.map +1 -0
- package/dist/utils/service/__tests__/serviceBookingExposureUtils.test.d.ts +2 -0
- package/dist/utils/service/__tests__/serviceBookingExposureUtils.test.d.ts.map +1 -0
- package/dist/utils/service/__tests__/serviceBookingExposureUtils.test.js +155 -0
- package/dist/utils/service/__tests__/serviceBookingExposureUtils.test.js.map +1 -0
- package/dist/utils/service/__tests__/unifiedPricingResolver.test.d.ts +2 -0
- package/dist/utils/service/__tests__/unifiedPricingResolver.test.d.ts.map +1 -0
- package/dist/utils/service/__tests__/unifiedPricingResolver.test.js +77 -0
- package/dist/utils/service/__tests__/unifiedPricingResolver.test.js.map +1 -0
- package/dist/utils/service/__tests__/venueFBSettlementUtils.test.d.ts +2 -0
- package/dist/utils/service/__tests__/venueFBSettlementUtils.test.d.ts.map +1 -0
- package/dist/utils/service/__tests__/venueFBSettlementUtils.test.js +157 -0
- package/dist/utils/service/__tests__/venueFBSettlementUtils.test.js.map +1 -0
- package/dist/utils/service/__tests__/venueSettlementUtils.test.d.ts +2 -0
- package/dist/utils/service/__tests__/venueSettlementUtils.test.d.ts.map +1 -0
- package/dist/utils/service/__tests__/venueSettlementUtils.test.js +175 -0
- package/dist/utils/service/__tests__/venueSettlementUtils.test.js.map +1 -0
- package/dist/utils/service/__tests__/volunteerCompensationUtils.test.d.ts +2 -0
- package/dist/utils/service/__tests__/volunteerCompensationUtils.test.d.ts.map +1 -0
- package/dist/utils/service/__tests__/volunteerCompensationUtils.test.js +118 -0
- package/dist/utils/service/__tests__/volunteerCompensationUtils.test.js.map +1 -0
- package/dist/utils/service/apiServiceBookingApiUtils.d.ts.map +1 -1
- package/dist/utils/service/apiServiceBookingApiUtils.js +4 -0
- package/dist/utils/service/apiServiceBookingApiUtils.js.map +1 -1
- package/dist/utils/service/billingCapUtils.d.ts +86 -0
- package/dist/utils/service/billingCapUtils.d.ts.map +1 -0
- package/dist/utils/service/billingCapUtils.js +96 -0
- package/dist/utils/service/billingCapUtils.js.map +1 -0
- package/dist/utils/service/cancellationPolicyRefundResolver.d.ts +1 -1
- package/dist/utils/service/cancellationPolicyRefundResolver.d.ts.map +1 -1
- package/dist/utils/service/cancellationPolicyRefundResolver.js +1 -1
- package/dist/utils/service/cancellationPolicyRefundResolver.js.map +1 -1
- package/dist/utils/service/eventPromoterUtils.d.ts +319 -0
- package/dist/utils/service/eventPromoterUtils.d.ts.map +1 -0
- package/dist/utils/service/eventPromoterUtils.js +372 -0
- package/dist/utils/service/eventPromoterUtils.js.map +1 -0
- package/dist/utils/service/offerAllowListUtils.d.ts +42 -0
- package/dist/utils/service/offerAllowListUtils.d.ts.map +1 -0
- package/dist/utils/service/offerAllowListUtils.js +49 -0
- package/dist/utils/service/offerAllowListUtils.js.map +1 -0
- package/dist/utils/service/offerComparisonUtils.d.ts +69 -0
- package/dist/utils/service/offerComparisonUtils.d.ts.map +1 -0
- package/dist/utils/service/offerComparisonUtils.js +110 -0
- package/dist/utils/service/offerComparisonUtils.js.map +1 -0
- package/dist/utils/service/serviceBookingExposureUtils.d.ts +111 -0
- package/dist/utils/service/serviceBookingExposureUtils.d.ts.map +1 -0
- package/dist/utils/service/serviceBookingExposureUtils.js +133 -0
- package/dist/utils/service/serviceBookingExposureUtils.js.map +1 -0
- package/dist/utils/service/serviceBookingTypes.d.ts +1 -1
- package/dist/utils/service/serviceBookingTypes.d.ts.map +1 -1
- package/dist/utils/service/serviceUtils.d.ts +2 -1
- package/dist/utils/service/serviceUtils.d.ts.map +1 -1
- package/dist/utils/service/serviceUtils.js +17 -16
- package/dist/utils/service/serviceUtils.js.map +1 -1
- package/dist/utils/service/unifiedPricingResolver.d.ts +67 -0
- package/dist/utils/service/unifiedPricingResolver.d.ts.map +1 -0
- package/dist/utils/service/unifiedPricingResolver.js +75 -0
- package/dist/utils/service/unifiedPricingResolver.js.map +1 -0
- package/dist/utils/service/venueFBSettlementUtils.d.ts +122 -0
- package/dist/utils/service/venueFBSettlementUtils.d.ts.map +1 -0
- package/dist/utils/service/venueFBSettlementUtils.js +106 -0
- package/dist/utils/service/venueFBSettlementUtils.js.map +1 -0
- package/dist/utils/service/venueSettlementUtils.d.ts +107 -0
- package/dist/utils/service/venueSettlementUtils.d.ts.map +1 -0
- package/dist/utils/service/venueSettlementUtils.js +117 -0
- package/dist/utils/service/venueSettlementUtils.js.map +1 -0
- package/dist/utils/service/volunteerCompensationUtils.d.ts +75 -0
- package/dist/utils/service/volunteerCompensationUtils.d.ts.map +1 -0
- package/dist/utils/service/volunteerCompensationUtils.js +88 -0
- package/dist/utils/service/volunteerCompensationUtils.js.map +1 -0
- package/dist/utils/venueLoyalty/__tests__/eligibilityUtils.test.d.ts +2 -0
- package/dist/utils/venueLoyalty/__tests__/eligibilityUtils.test.d.ts.map +1 -0
- package/dist/utils/venueLoyalty/__tests__/eligibilityUtils.test.js +67 -0
- package/dist/utils/venueLoyalty/__tests__/eligibilityUtils.test.js.map +1 -0
- package/dist/utils/venueLoyalty/__tests__/redemptionCodeUtils.test.d.ts +2 -0
- package/dist/utils/venueLoyalty/__tests__/redemptionCodeUtils.test.d.ts.map +1 -0
- package/dist/utils/venueLoyalty/__tests__/redemptionCodeUtils.test.js +71 -0
- package/dist/utils/venueLoyalty/__tests__/redemptionCodeUtils.test.js.map +1 -0
- package/dist/utils/venueLoyalty/eligibilityUtils.d.ts +33 -0
- package/dist/utils/venueLoyalty/eligibilityUtils.d.ts.map +1 -0
- package/dist/utils/venueLoyalty/eligibilityUtils.js +49 -0
- package/dist/utils/venueLoyalty/eligibilityUtils.js.map +1 -0
- package/dist/utils/venueLoyalty/redemptionCodeUtils.d.ts +35 -0
- package/dist/utils/venueLoyalty/redemptionCodeUtils.d.ts.map +1 -0
- package/dist/utils/venueLoyalty/redemptionCodeUtils.js +74 -0
- package/dist/utils/venueLoyalty/redemptionCodeUtils.js.map +1 -0
- package/dist/venueLoyaltyRedemption.d.ts +146 -1
- package/dist/venueLoyaltyRedemption.d.ts.map +1 -1
- package/dist/venueLoyaltyRedemption.js +18 -2
- package/dist/venueLoyaltyRedemption.js.map +1 -1
- package/package.json +1 -1
- package/prisma/schema.prisma +609 -214
- package/src/__tests__/statusEnums.test.ts +119 -11
- package/src/definitions.ts +57 -14
- package/src/extendedSchemas.ts +6 -0
- package/src/index.ts +16 -6
- package/src/mirroredPrismaEnums.ts +181 -0
- package/src/utils/__tests__/nonprofitUtils.test.ts +117 -0
- package/src/utils/__tests__/paymentUtils.test.ts +93 -0
- package/src/utils/nonprofitUtils.ts +44 -0
- package/src/utils/paymentUtils.ts +33 -7
- package/src/utils/service/__tests__/billingCapUtils.test.ts +175 -0
- package/src/utils/service/__tests__/cancellationPolicyRefundResolver.test.ts +1 -1
- package/src/utils/service/__tests__/eventPromoterPhase3.test.ts +296 -0
- package/src/utils/service/__tests__/eventPromoterUtils.test.ts +396 -0
- package/src/utils/service/__tests__/offerAllowListUtils.test.ts +76 -0
- package/src/utils/service/__tests__/offerComparisonUtils.test.ts +124 -0
- package/src/utils/service/__tests__/serviceBookingExposureUtils.test.ts +171 -0
- package/src/utils/service/__tests__/unifiedPricingResolver.test.ts +83 -0
- package/src/utils/service/__tests__/venueSettlementUtils.test.ts +219 -0
- package/src/utils/service/__tests__/volunteerCompensationUtils.test.ts +172 -0
- package/src/utils/service/apiServiceBookingApiUtils.ts +4 -0
- package/src/utils/service/billingCapUtils.ts +145 -0
- package/src/utils/service/cancellationPolicyRefundResolver.ts +1 -1
- package/src/utils/service/eventPromoterUtils.ts +644 -0
- package/src/utils/service/offerAllowListUtils.ts +81 -0
- package/src/utils/service/offerComparisonUtils.ts +197 -0
- package/src/utils/service/serviceBookingExposureUtils.ts +218 -0
- package/src/utils/service/serviceBookingTypes.ts +4 -0
- package/src/utils/service/serviceUtils.ts +18 -21
- package/src/utils/service/unifiedPricingResolver.ts +149 -0
- package/src/utils/service/venueSettlementUtils.ts +198 -0
- package/src/utils/service/volunteerCompensationUtils.ts +145 -0
- package/src/utils/venueLoyalty/__tests__/eligibilityUtils.test.ts +103 -0
- package/src/utils/venueLoyalty/__tests__/redemptionCodeUtils.test.ts +92 -0
- package/src/utils/venueLoyalty/eligibilityUtils.ts +84 -0
- package/src/utils/venueLoyalty/redemptionCodeUtils.ts +94 -0
- package/src/venueLoyaltyRedemption.ts +177 -2
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const EMPTY = {
|
|
2
|
+
pricingModel: null,
|
|
3
|
+
baseRateCents: null,
|
|
4
|
+
baseRateBashPoints: null,
|
|
5
|
+
rateUnit: null,
|
|
6
|
+
minimumChargeCents: null,
|
|
7
|
+
minimumQuantity: null,
|
|
8
|
+
tierPricing: null,
|
|
9
|
+
pricingNotes: null,
|
|
10
|
+
fromUnifiedBlock: false,
|
|
11
|
+
noRateConfigured: true,
|
|
12
|
+
};
|
|
13
|
+
function hasUnifiedSignal(b) {
|
|
14
|
+
if (!b)
|
|
15
|
+
return false;
|
|
16
|
+
return (b.pricingModel != null ||
|
|
17
|
+
b.baseRateCents != null ||
|
|
18
|
+
b.baseRateBashPoints != null ||
|
|
19
|
+
b.minimumChargeCents != null ||
|
|
20
|
+
b.minimumQuantity != null);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Walk the candidate subtypes in order, returning the first one that has
|
|
24
|
+
* unified pricing populated. Falls back to legacy `ServiceRate` if nothing
|
|
25
|
+
* has been migrated yet.
|
|
26
|
+
*/
|
|
27
|
+
export function resolveUnifiedPricingBlock(c) {
|
|
28
|
+
const candidates = [
|
|
29
|
+
c.eventService,
|
|
30
|
+
c.vendor,
|
|
31
|
+
c.exhibitor,
|
|
32
|
+
c.sponsor,
|
|
33
|
+
c.venue,
|
|
34
|
+
c.entertainmentService,
|
|
35
|
+
c.volunteerService,
|
|
36
|
+
];
|
|
37
|
+
for (const cand of candidates) {
|
|
38
|
+
if (hasUnifiedSignal(cand)) {
|
|
39
|
+
const b = cand;
|
|
40
|
+
const baseRateCents = b.baseRateCents ?? null;
|
|
41
|
+
return {
|
|
42
|
+
pricingModel: b.pricingModel ?? null,
|
|
43
|
+
baseRateCents,
|
|
44
|
+
baseRateBashPoints: b.baseRateBashPoints ?? null,
|
|
45
|
+
rateUnit: b.rateUnit ?? null,
|
|
46
|
+
minimumChargeCents: b.minimumChargeCents ?? null,
|
|
47
|
+
minimumQuantity: b.minimumQuantity ?? null,
|
|
48
|
+
tierPricing: b.tierPricing ?? null,
|
|
49
|
+
pricingNotes: b.pricingNotes ?? null,
|
|
50
|
+
fromUnifiedBlock: true,
|
|
51
|
+
noRateConfigured: baseRateCents == null && (b.baseRateBashPoints ?? null) == null,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const legacy = c.legacyRate;
|
|
56
|
+
if (legacy &&
|
|
57
|
+
(legacy.ratePerUnitCents != null ||
|
|
58
|
+
legacy.minimumQuantity != null ||
|
|
59
|
+
legacy.minimumChargeCents != null)) {
|
|
60
|
+
return {
|
|
61
|
+
pricingModel: "FLAT_FEE",
|
|
62
|
+
baseRateCents: legacy.ratePerUnitCents ?? null,
|
|
63
|
+
baseRateBashPoints: null,
|
|
64
|
+
rateUnit: legacy.rateUnit ?? null,
|
|
65
|
+
minimumChargeCents: legacy.minimumChargeCents ?? null,
|
|
66
|
+
minimumQuantity: legacy.minimumQuantity ?? null,
|
|
67
|
+
tierPricing: null,
|
|
68
|
+
pricingNotes: null,
|
|
69
|
+
fromUnifiedBlock: false,
|
|
70
|
+
noRateConfigured: legacy.ratePerUnitCents == null,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return EMPTY;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=unifiedPricingResolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unifiedPricingResolver.js","sourceRoot":"","sources":["../../../src/utils/service/unifiedPricingResolver.ts"],"names":[],"mappings":"AAgEA,MAAM,KAAK,GAAwB;IACjC,YAAY,EAAE,IAAI;IAClB,aAAa,EAAE,IAAI;IACnB,kBAAkB,EAAE,IAAI;IACxB,QAAQ,EAAE,IAAI;IACd,kBAAkB,EAAE,IAAI;IACxB,eAAe,EAAE,IAAI;IACrB,WAAW,EAAE,IAAI;IACjB,YAAY,EAAE,IAAI;IAClB,gBAAgB,EAAE,KAAK;IACvB,gBAAgB,EAAE,IAAI;CACvB,CAAC;AAEF,SAAS,gBAAgB,CAAC,CAAyC;IACjE,IAAI,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACrB,OAAO,CACL,CAAC,CAAC,YAAY,IAAI,IAAI;QACtB,CAAC,CAAC,aAAa,IAAI,IAAI;QACvB,CAAC,CAAC,kBAAkB,IAAI,IAAI;QAC5B,CAAC,CAAC,kBAAkB,IAAI,IAAI;QAC5B,CAAC,CAAC,eAAe,IAAI,IAAI,CAC1B,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,CACxC,CAAiC;IAEjC,MAAM,UAAU,GAAkD;QAChE,CAAC,CAAC,YAAY;QACd,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,OAAO;QACT,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,oBAAoB;QACtB,CAAC,CAAC,gBAAgB;KACnB,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,IAAI,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,MAAM,CAAC,GAAG,IAAK,CAAC;YAChB,MAAM,aAAa,GAAG,CAAC,CAAC,aAAa,IAAI,IAAI,CAAC;YAC9C,OAAO;gBACL,YAAY,EAAE,CAAC,CAAC,YAAY,IAAI,IAAI;gBACpC,aAAa;gBACb,kBAAkB,EAAE,CAAC,CAAC,kBAAkB,IAAI,IAAI;gBAChD,QAAQ,EAAE,CAAC,CAAC,QAAQ,IAAI,IAAI;gBAC5B,kBAAkB,EAAE,CAAC,CAAC,kBAAkB,IAAI,IAAI;gBAChD,eAAe,EAAE,CAAC,CAAC,eAAe,IAAI,IAAI;gBAC1C,WAAW,EAAE,CAAC,CAAC,WAAW,IAAI,IAAI;gBAClC,YAAY,EAAE,CAAC,CAAC,YAAY,IAAI,IAAI;gBACpC,gBAAgB,EAAE,IAAI;gBACtB,gBAAgB,EACd,aAAa,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,kBAAkB,IAAI,IAAI,CAAC,IAAI,IAAI;aAClE,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,CAAC,UAAU,CAAC;IAC5B,IACE,MAAM;QACN,CAAC,MAAM,CAAC,gBAAgB,IAAI,IAAI;YAC9B,MAAM,CAAC,eAAe,IAAI,IAAI;YAC9B,MAAM,CAAC,kBAAkB,IAAI,IAAI,CAAC,EACpC,CAAC;QACD,OAAO;YACL,YAAY,EAAE,UAA0B;YACxC,aAAa,EAAE,MAAM,CAAC,gBAAgB,IAAI,IAAI;YAC9C,kBAAkB,EAAE,IAAI;YACxB,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,IAAI;YACjC,kBAAkB,EAAE,MAAM,CAAC,kBAAkB,IAAI,IAAI;YACrD,eAAe,EAAE,MAAM,CAAC,eAAe,IAAI,IAAI;YAC/C,WAAW,EAAE,IAAI;YACjB,YAAY,EAAE,IAAI;YAClB,gBAAgB,EAAE,KAAK;YACvB,gBAAgB,EAAE,MAAM,CAAC,gBAAgB,IAAI,IAAI;SAClD,CAAC;IACJ,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase 2 of the unified-pricing roadmap — Venue F&B minimum + revenue-share math.
|
|
3
|
+
*
|
|
4
|
+
* Pure functions only (no Prisma / no fetches) so the wizard, api validators,
|
|
5
|
+
* settlement worker, and offer-suggestion AI can all share one source of truth.
|
|
6
|
+
*
|
|
7
|
+
* Concepts:
|
|
8
|
+
* - F&B MINIMUM: A venue can require the host's bash to generate at least
|
|
9
|
+
* $X in food + beverage spend. If actual spend < minimum, the host owes
|
|
10
|
+
* the gap (the "shortfall"). Service charge + tax may or may not count
|
|
11
|
+
* toward the minimum, depending on venue config.
|
|
12
|
+
* - CARRYOVER CREDIT: If `fbCarryoverEnabled`, excess spend over the minimum
|
|
13
|
+
* converts to a credit the host can apply to their next bash at the same
|
|
14
|
+
* venue (expires after `fbCarryoverExpiryDays`).
|
|
15
|
+
* - REVENUE SHARE: Venue takes a % of ticket revenue. Optional `revenueShareMinimumCents`
|
|
16
|
+
* is a floor so the venue is guaranteed at least that much even on slow nights.
|
|
17
|
+
*
|
|
18
|
+
* All amounts are integer cents.
|
|
19
|
+
*/
|
|
20
|
+
export interface VenueFBPolicySnapshot {
|
|
21
|
+
/** Effective minimum in cents (already weekday/weekend/override-resolved). */
|
|
22
|
+
fbMinimumCents: number;
|
|
23
|
+
/** True if the stated minimum already bakes in service charge. */
|
|
24
|
+
fbMinimumIncludesServiceCharge: boolean;
|
|
25
|
+
/** True if the stated minimum already bakes in tax. */
|
|
26
|
+
fbMinimumIncludesTax: boolean;
|
|
27
|
+
/** 0..1 service charge rate (e.g. 0.20 for 20%). Optional. */
|
|
28
|
+
fbServiceChargeRate?: number | null;
|
|
29
|
+
/** 0..1 tax rate. Optional. */
|
|
30
|
+
fbTaxRate?: number | null;
|
|
31
|
+
}
|
|
32
|
+
export interface FBSettlementInput extends VenueFBPolicySnapshot {
|
|
33
|
+
/**
|
|
34
|
+
* Raw F&B spend the venue invoiced (pre-service-charge, pre-tax) in cents.
|
|
35
|
+
* Use the same dollar basis as the minimum's "includes" flags below.
|
|
36
|
+
*/
|
|
37
|
+
actualFbSpendCents: number;
|
|
38
|
+
/**
|
|
39
|
+
* Any existing carryover credits the host has at this venue (sum of
|
|
40
|
+
* `remainingCents`, expiry-filtered upstream). Optional.
|
|
41
|
+
*/
|
|
42
|
+
availableCarryoverCents?: number;
|
|
43
|
+
/**
|
|
44
|
+
* Whether the venue has carryover credits enabled at all (so excess spend
|
|
45
|
+
* becomes a credit instead of evaporating).
|
|
46
|
+
*/
|
|
47
|
+
carryoverEnabled?: boolean;
|
|
48
|
+
}
|
|
49
|
+
export interface FBSettlementResult {
|
|
50
|
+
/** What the minimum normalizes to on the *actual* spend basis. */
|
|
51
|
+
normalizedMinimumCents: number;
|
|
52
|
+
/** Normalized actual spend (after applying svc-charge + tax if missing). */
|
|
53
|
+
normalizedActualCents: number;
|
|
54
|
+
/** Raw shortfall before carryover (>=0). */
|
|
55
|
+
rawShortfallCents: number;
|
|
56
|
+
/** Carryover credits redeemed against shortfall this settlement. */
|
|
57
|
+
carryoverAppliedCents: number;
|
|
58
|
+
/** Final amount the host owes for the F&B gap (after carryover). */
|
|
59
|
+
shortfallChargedCents: number;
|
|
60
|
+
/** Excess F&B spend over the minimum, available as new carryover. */
|
|
61
|
+
carryoverEarnedCents: number;
|
|
62
|
+
/** True if no shortfall + no excess. */
|
|
63
|
+
metExactly: boolean;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Settle an F&B minimum.
|
|
67
|
+
*
|
|
68
|
+
* Algorithm:
|
|
69
|
+
* 1. Normalize both the minimum and the actual spend to the same basis.
|
|
70
|
+
* - If the minimum INCLUDES service charge but actual does not, gross up
|
|
71
|
+
* the actual by (1 + serviceChargeRate). Same logic for tax.
|
|
72
|
+
* - If the minimum EXCLUDES service charge but actual does, strip the
|
|
73
|
+
* service charge from the actual figure. Same for tax.
|
|
74
|
+
* 2. Shortfall = max(0, normalizedMinimum - normalizedActual).
|
|
75
|
+
* 3. If carryover credits are available, apply them against shortfall.
|
|
76
|
+
* 4. Excess = max(0, normalizedActual - normalizedMinimum). Becomes new
|
|
77
|
+
* carryover credit if `carryoverEnabled`.
|
|
78
|
+
*/
|
|
79
|
+
export declare function settleVenueFBMinimum(input: FBSettlementInput): FBSettlementResult;
|
|
80
|
+
export interface RevenueShareInput {
|
|
81
|
+
/** Held ticket revenue at settlement, in cents. */
|
|
82
|
+
heldTicketRevenueCents: number;
|
|
83
|
+
/** 0..100 percentage the venue gets. */
|
|
84
|
+
revenueSharePercentage: number;
|
|
85
|
+
/** Optional floor — venue gets at least this even if the % is lower. */
|
|
86
|
+
revenueShareMinimumCents?: number | null;
|
|
87
|
+
}
|
|
88
|
+
export interface RevenueShareResult {
|
|
89
|
+
/** Venue's cut after applying %. */
|
|
90
|
+
venueCutPctCents: number;
|
|
91
|
+
/** Final venue cut after applying the floor. */
|
|
92
|
+
venuePayoutCents: number;
|
|
93
|
+
/** True if the floor topped up the %. */
|
|
94
|
+
flooredUp: boolean;
|
|
95
|
+
}
|
|
96
|
+
export declare function settleVenueRevenueShare(input: RevenueShareInput): RevenueShareResult;
|
|
97
|
+
/**
|
|
98
|
+
* Returns the effective weekday-vs-weekend F&B minimum for a given bash date.
|
|
99
|
+
* Override windows take precedence; otherwise picks weekday/weekend based on
|
|
100
|
+
* day-of-week of the bash *start* (Mon=1..Sun=0, in local TZ at the caller's
|
|
101
|
+
* level — pass `bashStartDay` 0..6 in whatever convention you've already
|
|
102
|
+
* resolved).
|
|
103
|
+
*/
|
|
104
|
+
export interface ResolveFBMinimumInput {
|
|
105
|
+
bashStartDay: number;
|
|
106
|
+
/** Optional date windows that override the weekday/weekend values. */
|
|
107
|
+
overrides?: ReadonlyArray<{
|
|
108
|
+
startsAt: Date;
|
|
109
|
+
endsAt: Date;
|
|
110
|
+
minimumCents: number;
|
|
111
|
+
}>;
|
|
112
|
+
bashStartDate?: Date;
|
|
113
|
+
fbMinimumWeekdayCents?: number | null;
|
|
114
|
+
fbMinimumWeekendCents?: number | null;
|
|
115
|
+
}
|
|
116
|
+
export declare function resolveFBMinimumCents(input: ResolveFBMinimumInput): number | null;
|
|
117
|
+
/**
|
|
118
|
+
* Cancellation-policy copy snippet to surface on offer sheets + booking
|
|
119
|
+
* detail when a venue booking has an F&B minimum attached.
|
|
120
|
+
*/
|
|
121
|
+
export declare const FB_MINIMUM_CANCELLATION_COPY = "If the bash is canceled within the venue's cancellation window, the host may still owe the F&B minimum shortfall. See the venue's cancellation policy for the exact timing.";
|
|
122
|
+
//# sourceMappingURL=venueFBSettlementUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"venueFBSettlementUtils.d.ts","sourceRoot":"","sources":["../../../src/utils/service/venueFBSettlementUtils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAQH,MAAM,WAAW,qBAAqB;IACpC,8EAA8E;IAC9E,cAAc,EAAE,MAAM,CAAC;IACvB,kEAAkE;IAClE,8BAA8B,EAAE,OAAO,CAAC;IACxC,uDAAuD;IACvD,oBAAoB,EAAE,OAAO,CAAC;IAC9B,8DAA8D;IAC9D,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,+BAA+B;IAC/B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAkB,SAAQ,qBAAqB;IAC9D;;;OAGG;IACH,kBAAkB,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,kEAAkE;IAClE,sBAAsB,EAAE,MAAM,CAAC;IAC/B,4EAA4E;IAC5E,qBAAqB,EAAE,MAAM,CAAC;IAC9B,4CAA4C;IAC5C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oEAAoE;IACpE,qBAAqB,EAAE,MAAM,CAAC;IAC9B,oEAAoE;IACpE,qBAAqB,EAAE,MAAM,CAAC;IAC9B,qEAAqE;IACrE,oBAAoB,EAAE,MAAM,CAAC;IAC7B,wCAAwC;IACxC,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,iBAAiB,GACvB,kBAAkB,CA4CpB;AAED,MAAM,WAAW,iBAAiB;IAChC,mDAAmD;IACnD,sBAAsB,EAAE,MAAM,CAAC;IAC/B,wCAAwC;IACxC,sBAAsB,EAAE,MAAM,CAAC;IAC/B,wEAAwE;IACxE,wBAAwB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1C;AAED,MAAM,WAAW,kBAAkB;IACjC,oCAAoC;IACpC,gBAAgB,EAAE,MAAM,CAAC;IACzB,gDAAgD;IAChD,gBAAgB,EAAE,MAAM,CAAC;IACzB,yCAAyC;IACzC,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,iBAAiB,GACvB,kBAAkB,CAWpB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,sEAAsE;IACtE,SAAS,CAAC,EAAE,aAAa,CAAC;QACxB,QAAQ,EAAE,IAAI,CAAC;QACf,MAAM,EAAE,IAAI,CAAC;QACb,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;IACH,aAAa,CAAC,EAAE,IAAI,CAAC;IACrB,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvC;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,qBAAqB,GAC3B,MAAM,GAAG,IAAI,CAkBf;AAED;;;GAGG;AACH,eAAO,MAAM,4BAA4B,gLACsI,CAAC"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase 2 of the unified-pricing roadmap — Venue F&B minimum + revenue-share math.
|
|
3
|
+
*
|
|
4
|
+
* Pure functions only (no Prisma / no fetches) so the wizard, api validators,
|
|
5
|
+
* settlement worker, and offer-suggestion AI can all share one source of truth.
|
|
6
|
+
*
|
|
7
|
+
* Concepts:
|
|
8
|
+
* - F&B MINIMUM: A venue can require the host's bash to generate at least
|
|
9
|
+
* $X in food + beverage spend. If actual spend < minimum, the host owes
|
|
10
|
+
* the gap (the "shortfall"). Service charge + tax may or may not count
|
|
11
|
+
* toward the minimum, depending on venue config.
|
|
12
|
+
* - CARRYOVER CREDIT: If `fbCarryoverEnabled`, excess spend over the minimum
|
|
13
|
+
* converts to a credit the host can apply to their next bash at the same
|
|
14
|
+
* venue (expires after `fbCarryoverExpiryDays`).
|
|
15
|
+
* - REVENUE SHARE: Venue takes a % of ticket revenue. Optional `revenueShareMinimumCents`
|
|
16
|
+
* is a floor so the venue is guaranteed at least that much even on slow nights.
|
|
17
|
+
*
|
|
18
|
+
* All amounts are integer cents.
|
|
19
|
+
*/
|
|
20
|
+
/** Cents → cents helper that always returns a non-negative integer. */
|
|
21
|
+
function nonNegInt(value) {
|
|
22
|
+
if (!Number.isFinite(value) || value <= 0)
|
|
23
|
+
return 0;
|
|
24
|
+
return Math.round(value);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Settle an F&B minimum.
|
|
28
|
+
*
|
|
29
|
+
* Algorithm:
|
|
30
|
+
* 1. Normalize both the minimum and the actual spend to the same basis.
|
|
31
|
+
* - If the minimum INCLUDES service charge but actual does not, gross up
|
|
32
|
+
* the actual by (1 + serviceChargeRate). Same logic for tax.
|
|
33
|
+
* - If the minimum EXCLUDES service charge but actual does, strip the
|
|
34
|
+
* service charge from the actual figure. Same for tax.
|
|
35
|
+
* 2. Shortfall = max(0, normalizedMinimum - normalizedActual).
|
|
36
|
+
* 3. If carryover credits are available, apply them against shortfall.
|
|
37
|
+
* 4. Excess = max(0, normalizedActual - normalizedMinimum). Becomes new
|
|
38
|
+
* carryover credit if `carryoverEnabled`.
|
|
39
|
+
*/
|
|
40
|
+
export function settleVenueFBMinimum(input) {
|
|
41
|
+
const svcRate = Math.max(0, input.fbServiceChargeRate ?? 0);
|
|
42
|
+
const taxRate = Math.max(0, input.fbTaxRate ?? 0);
|
|
43
|
+
// Both the minimum and the actual need to live on the same basis. We
|
|
44
|
+
// normalize to "pre-service-charge, pre-tax" (the food+bev sticker price).
|
|
45
|
+
let normalizedMinimumCents = input.fbMinimumCents;
|
|
46
|
+
if (input.fbMinimumIncludesServiceCharge && svcRate > 0) {
|
|
47
|
+
normalizedMinimumCents = normalizedMinimumCents / (1 + svcRate);
|
|
48
|
+
}
|
|
49
|
+
if (input.fbMinimumIncludesTax && taxRate > 0) {
|
|
50
|
+
normalizedMinimumCents = normalizedMinimumCents / (1 + taxRate);
|
|
51
|
+
}
|
|
52
|
+
normalizedMinimumCents = nonNegInt(normalizedMinimumCents);
|
|
53
|
+
const normalizedActualCents = nonNegInt(input.actualFbSpendCents);
|
|
54
|
+
const rawShortfallCents = Math.max(0, normalizedMinimumCents - normalizedActualCents);
|
|
55
|
+
const availableCarryover = nonNegInt(input.availableCarryoverCents ?? 0);
|
|
56
|
+
const carryoverAppliedCents = Math.min(rawShortfallCents, availableCarryover);
|
|
57
|
+
const shortfallChargedCents = rawShortfallCents - carryoverAppliedCents;
|
|
58
|
+
const excessCents = Math.max(0, normalizedActualCents - normalizedMinimumCents);
|
|
59
|
+
const carryoverEarnedCents = input.carryoverEnabled ? excessCents : 0;
|
|
60
|
+
return {
|
|
61
|
+
normalizedMinimumCents,
|
|
62
|
+
normalizedActualCents,
|
|
63
|
+
rawShortfallCents,
|
|
64
|
+
carryoverAppliedCents,
|
|
65
|
+
shortfallChargedCents,
|
|
66
|
+
carryoverEarnedCents,
|
|
67
|
+
metExactly: rawShortfallCents === 0 &&
|
|
68
|
+
excessCents === 0 &&
|
|
69
|
+
normalizedActualCents === normalizedMinimumCents,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
export function settleVenueRevenueShare(input) {
|
|
73
|
+
const heldCents = nonNegInt(input.heldTicketRevenueCents);
|
|
74
|
+
const pct = Math.max(0, Math.min(100, input.revenueSharePercentage));
|
|
75
|
+
const venueCutPctCents = nonNegInt((heldCents * pct) / 100);
|
|
76
|
+
const floor = nonNegInt(input.revenueShareMinimumCents ?? 0);
|
|
77
|
+
const venuePayoutCents = Math.max(venueCutPctCents, floor);
|
|
78
|
+
return {
|
|
79
|
+
venueCutPctCents,
|
|
80
|
+
venuePayoutCents,
|
|
81
|
+
flooredUp: venuePayoutCents > venueCutPctCents,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
export function resolveFBMinimumCents(input) {
|
|
85
|
+
if (input.overrides && input.bashStartDate) {
|
|
86
|
+
for (const o of input.overrides) {
|
|
87
|
+
if (o.startsAt <= input.bashStartDate &&
|
|
88
|
+
input.bashStartDate <= o.endsAt) {
|
|
89
|
+
return o.minimumCents;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const day = input.bashStartDay;
|
|
94
|
+
// Fri (5), Sat (6), Sun (0) treated as weekend.
|
|
95
|
+
const isWeekend = day === 0 || day === 5 || day === 6;
|
|
96
|
+
const result = isWeekend
|
|
97
|
+
? input.fbMinimumWeekendCents
|
|
98
|
+
: input.fbMinimumWeekdayCents;
|
|
99
|
+
return result == null ? null : Math.max(0, Math.floor(result));
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Cancellation-policy copy snippet to surface on offer sheets + booking
|
|
103
|
+
* detail when a venue booking has an F&B minimum attached.
|
|
104
|
+
*/
|
|
105
|
+
export const FB_MINIMUM_CANCELLATION_COPY = "If the bash is canceled within the venue's cancellation window, the host may still owe the F&B minimum shortfall. See the venue's cancellation policy for the exact timing.";
|
|
106
|
+
//# sourceMappingURL=venueFBSettlementUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"venueFBSettlementUtils.js","sourceRoot":"","sources":["../../../src/utils/service/venueFBSettlementUtils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase 2 of the unified-pricing roadmap — pure math for Venue F&B minimums
|
|
3
|
+
* and revenue share. Pure functions only (no Prisma / no fetches) so the
|
|
4
|
+
* wizard, api validators, settlement worker, and offer-suggestion AI can all
|
|
5
|
+
* share one source of truth.
|
|
6
|
+
*
|
|
7
|
+
* See `docs/help-center/pricing-models/` and the plan at
|
|
8
|
+
* `unified-pricing-roadmap_21d456c6.plan.md` for the policy story.
|
|
9
|
+
*
|
|
10
|
+
* Amounts are always integer cents.
|
|
11
|
+
*/
|
|
12
|
+
/** Days of week used in `Venue.fbMinimumSchedule`. Locale-agnostic short keys. */
|
|
13
|
+
export declare const FB_MINIMUM_SCHEDULE_DAYS: readonly ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
14
|
+
export type FBMinimumScheduleDay = (typeof FB_MINIMUM_SCHEDULE_DAYS)[number];
|
|
15
|
+
/** Shape of the JSON stored at `Venue.fbMinimumSchedule`. */
|
|
16
|
+
export type FBMinimumSchedule = Partial<Record<FBMinimumScheduleDay, number>>;
|
|
17
|
+
/** Allowed values for `Venue.revenueShareBasis` (kept as plain strings since
|
|
18
|
+
* the column is `String?` rather than an enum). */
|
|
19
|
+
export declare const REVENUE_SHARE_BASES: readonly ["FB_SALES", "TICKET_REVENUE", "TOTAL_GROSS"];
|
|
20
|
+
export type RevenueShareBasis = (typeof REVENUE_SHARE_BASES)[number];
|
|
21
|
+
export interface ResolveFBMinimumInput {
|
|
22
|
+
/** Per-day-of-week schedule from `Venue.fbMinimumSchedule`. */
|
|
23
|
+
schedule: FBMinimumSchedule | null | undefined;
|
|
24
|
+
/** Optional date-windowed overrides from `VenueFBMinimumOverride`. */
|
|
25
|
+
overrides?: ReadonlyArray<{
|
|
26
|
+
startDate: Date;
|
|
27
|
+
endDate: Date;
|
|
28
|
+
minimumCents: number;
|
|
29
|
+
}>;
|
|
30
|
+
/** Bash start as it should be evaluated for day-of-week / override match. */
|
|
31
|
+
eventStartDateTime: Date;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Resolve the effective F&B minimum (in cents) for a given bash date.
|
|
35
|
+
*
|
|
36
|
+
* Override precedence: any matching window in `overrides` (inclusive endpoints)
|
|
37
|
+
* wins; otherwise the schedule entry for the day-of-week of `eventStartDateTime`
|
|
38
|
+
* is used. Returns `null` if neither produces a value.
|
|
39
|
+
*
|
|
40
|
+
* Callers that need timezone-aware day-of-week selection should pre-shift the
|
|
41
|
+
* Date before passing it in — this function uses `Date.getDay()` directly.
|
|
42
|
+
*/
|
|
43
|
+
export declare function resolveFBMinimumForDate(input: ResolveFBMinimumInput): number | null;
|
|
44
|
+
export interface FBShortfallInput {
|
|
45
|
+
/** Effective minimum (resolved via `resolveFBMinimumForDate`). */
|
|
46
|
+
fbMinimumCents: number;
|
|
47
|
+
/** Final food+bev sticker price from the venue invoice. */
|
|
48
|
+
fbActualSpendCents: number;
|
|
49
|
+
/** Service-charge cents the venue charged on top of the F&B subtotal. */
|
|
50
|
+
serviceChargeCents?: number | null;
|
|
51
|
+
/** Tax cents the venue charged on top of subtotal+service. */
|
|
52
|
+
taxCents?: number | null;
|
|
53
|
+
/** Snapshot of `Venue.fbServiceChargeCountsTowardMinimum`. */
|
|
54
|
+
serviceChargeCountsTowardMinimum: boolean;
|
|
55
|
+
/** Snapshot of `Venue.fbMinimumIncludesTax`. */
|
|
56
|
+
includesTax: boolean;
|
|
57
|
+
}
|
|
58
|
+
export interface FBShortfallResult {
|
|
59
|
+
/** Spend credited toward the minimum after svc-charge/tax flags. */
|
|
60
|
+
coveredSpendCents: number;
|
|
61
|
+
/** max(0, minimum - covered). */
|
|
62
|
+
shortfallCents: number;
|
|
63
|
+
/** max(0, covered - minimum). Useful for carryover-credit issuance. */
|
|
64
|
+
excessCents: number;
|
|
65
|
+
/** True if `shortfallCents === 0 && excessCents === 0`. */
|
|
66
|
+
metExactly: boolean;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Compute how much of the bash's F&B invoice counts toward the venue's
|
|
70
|
+
* minimum and the resulting shortfall (or excess) at settlement.
|
|
71
|
+
*
|
|
72
|
+
* Rules:
|
|
73
|
+
* - Subtotal (`fbActualSpendCents`) ALWAYS counts toward the minimum.
|
|
74
|
+
* - Service charge counts iff `serviceChargeCountsTowardMinimum`.
|
|
75
|
+
* - Tax counts iff `includesTax`.
|
|
76
|
+
*
|
|
77
|
+
* All cents are integers and always non-negative.
|
|
78
|
+
*/
|
|
79
|
+
export declare function computeFBMinimumShortfallCents(input: FBShortfallInput): FBShortfallResult;
|
|
80
|
+
export interface RevenueShareInput {
|
|
81
|
+
/** The basis amount in cents (ticket revenue, F&B sales, etc.). */
|
|
82
|
+
basisCents: number;
|
|
83
|
+
/** Host percentage (0..100). Venue cut = basisCents * (100 - hostPct) / 100. */
|
|
84
|
+
hostPct: number;
|
|
85
|
+
}
|
|
86
|
+
export interface RevenueShareResult {
|
|
87
|
+
/** Host's share in cents. */
|
|
88
|
+
hostCents: number;
|
|
89
|
+
/** Venue's share in cents. Equals basis - host. */
|
|
90
|
+
venueCents: number;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Compute the revenue-share split given a basis and host percentage.
|
|
94
|
+
* Returns integer cents. Out-of-range hostPct is clamped to [0, 100].
|
|
95
|
+
*/
|
|
96
|
+
export declare function computeRevenueShareCents(input: RevenueShareInput): RevenueShareResult;
|
|
97
|
+
/** Surfaced on offer sheets + booking detail when an F&B minimum is attached. */
|
|
98
|
+
export declare const FB_MINIMUM_CANCELLATION_COPY = "If the bash is canceled within the venue's cancellation window, the host may still owe the F&B minimum shortfall. See the venue's cancellation policy for the exact timing.";
|
|
99
|
+
/** Surfaced when a venue booking has revenue share configured. */
|
|
100
|
+
export declare const REVENUE_SHARE_CANCELLATION_COPY = "If the bash is canceled before tickets sell, no revenue-share payment is owed. See the venue's cancellation policy for late-cancel rules.";
|
|
101
|
+
/** Default lifetime for a `VenueFBCarryoverCredit`, in days (12 months). */
|
|
102
|
+
export declare const DEFAULT_FB_CARRYOVER_EXPIRY_DAYS = 365;
|
|
103
|
+
/**
|
|
104
|
+
* Compute the default expiry timestamp for a newly-issued carryover credit.
|
|
105
|
+
*/
|
|
106
|
+
export declare function defaultFBCarryoverExpiresAt(issuedAt?: Date, days?: number): Date;
|
|
107
|
+
//# sourceMappingURL=venueSettlementUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"venueSettlementUtils.d.ts","sourceRoot":"","sources":["../../../src/utils/service/venueSettlementUtils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,kFAAkF;AAClF,eAAO,MAAM,wBAAwB,4DAQ3B,CAAC;AACX,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7E,6DAA6D;AAC7D,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC,CAAC;AAE9E;oDACoD;AACpD,eAAO,MAAM,mBAAmB,wDAItB,CAAC;AACX,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAUrE,MAAM,WAAW,qBAAqB;IACpC,+DAA+D;IAC/D,QAAQ,EAAE,iBAAiB,GAAG,IAAI,GAAG,SAAS,CAAC;IAC/C,sEAAsE;IACtE,SAAS,CAAC,EAAE,aAAa,CAAC;QACxB,SAAS,EAAE,IAAI,CAAC;QAChB,OAAO,EAAE,IAAI,CAAC;QACd,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;IACH,6EAA6E;IAC7E,kBAAkB,EAAE,IAAI,CAAC;CAC1B;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,qBAAqB,GAC3B,MAAM,GAAG,IAAI,CAgBf;AAED,MAAM,WAAW,gBAAgB;IAC/B,kEAAkE;IAClE,cAAc,EAAE,MAAM,CAAC;IACvB,2DAA2D;IAC3D,kBAAkB,EAAE,MAAM,CAAC;IAC3B,yEAAyE;IACzE,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,8DAA8D;IAC9D,gCAAgC,EAAE,OAAO,CAAC;IAC1C,gDAAgD;IAChD,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,oEAAoE;IACpE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iCAAiC;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,uEAAuE;IACvE,WAAW,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,gBAAgB,GACtB,iBAAiB,CAiBnB;AAID,MAAM,WAAW,iBAAiB;IAChC,mEAAmE;IACnE,UAAU,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,6BAA6B;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,iBAAiB,GACvB,kBAAkB,CAMpB;AAID,iFAAiF;AACjF,eAAO,MAAM,4BAA4B,gLACsI,CAAC;AAEhL,kEAAkE;AAClE,eAAO,MAAM,+BAA+B,8IACiG,CAAC;AAE9I,4EAA4E;AAC5E,eAAO,MAAM,gCAAgC,MAAM,CAAC;AAEpD;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,GAAE,IAAiB,EAC3B,IAAI,GAAE,MAAyC,GAC9C,IAAI,CAGN"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase 2 of the unified-pricing roadmap — pure math for Venue F&B minimums
|
|
3
|
+
* and revenue share. Pure functions only (no Prisma / no fetches) so the
|
|
4
|
+
* wizard, api validators, settlement worker, and offer-suggestion AI can all
|
|
5
|
+
* share one source of truth.
|
|
6
|
+
*
|
|
7
|
+
* See `docs/help-center/pricing-models/` and the plan at
|
|
8
|
+
* `unified-pricing-roadmap_21d456c6.plan.md` for the policy story.
|
|
9
|
+
*
|
|
10
|
+
* Amounts are always integer cents.
|
|
11
|
+
*/
|
|
12
|
+
/** Days of week used in `Venue.fbMinimumSchedule`. Locale-agnostic short keys. */
|
|
13
|
+
export const FB_MINIMUM_SCHEDULE_DAYS = [
|
|
14
|
+
"Sun",
|
|
15
|
+
"Mon",
|
|
16
|
+
"Tue",
|
|
17
|
+
"Wed",
|
|
18
|
+
"Thu",
|
|
19
|
+
"Fri",
|
|
20
|
+
"Sat",
|
|
21
|
+
];
|
|
22
|
+
/** Allowed values for `Venue.revenueShareBasis` (kept as plain strings since
|
|
23
|
+
* the column is `String?` rather than an enum). */
|
|
24
|
+
export const REVENUE_SHARE_BASES = [
|
|
25
|
+
"FB_SALES",
|
|
26
|
+
"TICKET_REVENUE",
|
|
27
|
+
"TOTAL_GROSS",
|
|
28
|
+
];
|
|
29
|
+
/** Internal helper — cents → non-negative rounded integer. */
|
|
30
|
+
function nonNegInt(value) {
|
|
31
|
+
if (!Number.isFinite(value) || value <= 0)
|
|
32
|
+
return 0;
|
|
33
|
+
return Math.round(value);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Resolve the effective F&B minimum (in cents) for a given bash date.
|
|
37
|
+
*
|
|
38
|
+
* Override precedence: any matching window in `overrides` (inclusive endpoints)
|
|
39
|
+
* wins; otherwise the schedule entry for the day-of-week of `eventStartDateTime`
|
|
40
|
+
* is used. Returns `null` if neither produces a value.
|
|
41
|
+
*
|
|
42
|
+
* Callers that need timezone-aware day-of-week selection should pre-shift the
|
|
43
|
+
* Date before passing it in — this function uses `Date.getDay()` directly.
|
|
44
|
+
*/
|
|
45
|
+
export function resolveFBMinimumForDate(input) {
|
|
46
|
+
if (input.overrides && input.overrides.length > 0) {
|
|
47
|
+
const ms = input.eventStartDateTime.getTime();
|
|
48
|
+
for (const o of input.overrides) {
|
|
49
|
+
if (o.startDate.getTime() <= ms && ms <= o.endDate.getTime()) {
|
|
50
|
+
return Math.max(0, Math.floor(o.minimumCents));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const schedule = input.schedule ?? null;
|
|
55
|
+
if (!schedule)
|
|
56
|
+
return null;
|
|
57
|
+
const dayIdx = input.eventStartDateTime.getDay();
|
|
58
|
+
const dayKey = FB_MINIMUM_SCHEDULE_DAYS[dayIdx];
|
|
59
|
+
const value = schedule[dayKey];
|
|
60
|
+
if (value == null || !Number.isFinite(value))
|
|
61
|
+
return null;
|
|
62
|
+
return Math.max(0, Math.floor(value));
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Compute how much of the bash's F&B invoice counts toward the venue's
|
|
66
|
+
* minimum and the resulting shortfall (or excess) at settlement.
|
|
67
|
+
*
|
|
68
|
+
* Rules:
|
|
69
|
+
* - Subtotal (`fbActualSpendCents`) ALWAYS counts toward the minimum.
|
|
70
|
+
* - Service charge counts iff `serviceChargeCountsTowardMinimum`.
|
|
71
|
+
* - Tax counts iff `includesTax`.
|
|
72
|
+
*
|
|
73
|
+
* All cents are integers and always non-negative.
|
|
74
|
+
*/
|
|
75
|
+
export function computeFBMinimumShortfallCents(input) {
|
|
76
|
+
const subtotal = nonNegInt(input.fbActualSpendCents);
|
|
77
|
+
const svc = nonNegInt(input.serviceChargeCents ?? 0);
|
|
78
|
+
const tax = nonNegInt(input.taxCents ?? 0);
|
|
79
|
+
const coveredSpendCents = subtotal +
|
|
80
|
+
(input.serviceChargeCountsTowardMinimum ? svc : 0) +
|
|
81
|
+
(input.includesTax ? tax : 0);
|
|
82
|
+
const minimum = nonNegInt(input.fbMinimumCents);
|
|
83
|
+
const shortfallCents = Math.max(0, minimum - coveredSpendCents);
|
|
84
|
+
const excessCents = Math.max(0, coveredSpendCents - minimum);
|
|
85
|
+
return {
|
|
86
|
+
coveredSpendCents,
|
|
87
|
+
shortfallCents,
|
|
88
|
+
excessCents,
|
|
89
|
+
metExactly: shortfallCents === 0 && excessCents === 0,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Compute the revenue-share split given a basis and host percentage.
|
|
94
|
+
* Returns integer cents. Out-of-range hostPct is clamped to [0, 100].
|
|
95
|
+
*/
|
|
96
|
+
export function computeRevenueShareCents(input) {
|
|
97
|
+
const basis = nonNegInt(input.basisCents);
|
|
98
|
+
const hostPct = Math.max(0, Math.min(100, input.hostPct));
|
|
99
|
+
const hostCents = nonNegInt((basis * hostPct) / 100);
|
|
100
|
+
const venueCents = Math.max(0, basis - hostCents);
|
|
101
|
+
return { hostCents, venueCents };
|
|
102
|
+
}
|
|
103
|
+
// ---------- Cancellation copy ----------
|
|
104
|
+
/** Surfaced on offer sheets + booking detail when an F&B minimum is attached. */
|
|
105
|
+
export const FB_MINIMUM_CANCELLATION_COPY = "If the bash is canceled within the venue's cancellation window, the host may still owe the F&B minimum shortfall. See the venue's cancellation policy for the exact timing.";
|
|
106
|
+
/** Surfaced when a venue booking has revenue share configured. */
|
|
107
|
+
export const REVENUE_SHARE_CANCELLATION_COPY = "If the bash is canceled before tickets sell, no revenue-share payment is owed. See the venue's cancellation policy for late-cancel rules.";
|
|
108
|
+
/** Default lifetime for a `VenueFBCarryoverCredit`, in days (12 months). */
|
|
109
|
+
export const DEFAULT_FB_CARRYOVER_EXPIRY_DAYS = 365;
|
|
110
|
+
/**
|
|
111
|
+
* Compute the default expiry timestamp for a newly-issued carryover credit.
|
|
112
|
+
*/
|
|
113
|
+
export function defaultFBCarryoverExpiresAt(issuedAt = new Date(), days = DEFAULT_FB_CARRYOVER_EXPIRY_DAYS) {
|
|
114
|
+
const ms = issuedAt.getTime() + Math.max(1, Math.floor(days)) * 86_400_000;
|
|
115
|
+
return new Date(ms);
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=venueSettlementUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"venueSettlementUtils.js","sourceRoot":"","sources":["../../../src/utils/service/venueSettlementUtils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Volunteer compensation — closed-loop BashPoints stipends + on-site perks.
|
|
3
|
+
*
|
|
4
|
+
* Volunteers are NOT employees or contractors. This util intentionally avoids
|
|
5
|
+
* any USD rate / wage / per-attendee math, because crossing that line would
|
|
6
|
+
* trigger worker-classification, minimum-wage, and 1099 reporting concerns.
|
|
7
|
+
*
|
|
8
|
+
* BashPoints stipends are safe because BP is closed-loop platform credit:
|
|
9
|
+
* - never cashed out,
|
|
10
|
+
* - never used to settle third-party USD invoices,
|
|
11
|
+
* - only redeemable against Bash-issued goods (tickets, BashPass upgrades,
|
|
12
|
+
* premium features) — see the closed-loop BP plan.
|
|
13
|
+
*
|
|
14
|
+
* Pure functions only so the wizard, api validators, and help-center page
|
|
15
|
+
* share one source of truth.
|
|
16
|
+
*/
|
|
17
|
+
import { VolunteerCompensationType } from "../../mirroredPrismaEnums.js";
|
|
18
|
+
/** Suggested starter BP stipend per shift. Hosts can override in the wizard. */
|
|
19
|
+
export declare const DEFAULT_VOLUNTEER_STIPEND_BP_PER_SHIFT = 100;
|
|
20
|
+
/** Suggested starter BP stipend per hour. */
|
|
21
|
+
export declare const DEFAULT_VOLUNTEER_STIPEND_BP_PER_HOUR = 25;
|
|
22
|
+
/** Allowed values for `VolunteerService.rateUnit`. */
|
|
23
|
+
export declare const VOLUNTEER_RATE_UNITS: readonly ["shift", "hour"];
|
|
24
|
+
export type VolunteerRateUnit = (typeof VOLUNTEER_RATE_UNITS)[number];
|
|
25
|
+
/**
|
|
26
|
+
* Returns the suggested starter BP stipend for a volunteer profile based on
|
|
27
|
+
* how the host wants to denominate it. Wizard pre-fills `bashPointsStipend`
|
|
28
|
+
* with this; host can override.
|
|
29
|
+
*/
|
|
30
|
+
export declare function defaultStipendBpFor(args: {
|
|
31
|
+
rateUnit: VolunteerRateUnit | string | null | undefined;
|
|
32
|
+
}): number;
|
|
33
|
+
/**
|
|
34
|
+
* Returns true if the given compensation type pays any BashPoints. Used by
|
|
35
|
+
* the booking detail page + settlement worker to decide whether to surface
|
|
36
|
+
* BP-stipend fields.
|
|
37
|
+
*/
|
|
38
|
+
export declare function compensationTypePaysBashPoints(t: VolunteerCompensationType | string | null | undefined): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Returns true if the given compensation type includes on-site perks.
|
|
41
|
+
*/
|
|
42
|
+
export declare function compensationTypeIncludesPerks(t: VolunteerCompensationType | string | null | undefined): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Validates a saved volunteer compensation block. Returns a friendly error
|
|
45
|
+
* when the host's choices contradict (e.g. `PerksOnly` with a BP stipend
|
|
46
|
+
* filled in, or `BashPointsStipend` with no BP amount).
|
|
47
|
+
*/
|
|
48
|
+
export type VolunteerCompensationValidation = {
|
|
49
|
+
ok: true;
|
|
50
|
+
} | {
|
|
51
|
+
ok: false;
|
|
52
|
+
reason: string;
|
|
53
|
+
};
|
|
54
|
+
export declare function validateVolunteerCompensation(args: {
|
|
55
|
+
compensationType: VolunteerCompensationType | string;
|
|
56
|
+
bashPointsStipend?: number | null;
|
|
57
|
+
rateUnit?: string | null;
|
|
58
|
+
perksDescription?: string | null;
|
|
59
|
+
}): VolunteerCompensationValidation;
|
|
60
|
+
/**
|
|
61
|
+
* Plain-English label for the booking detail page + booking thread system
|
|
62
|
+
* messages. Stable across renders.
|
|
63
|
+
*/
|
|
64
|
+
export declare function volunteerCompensationSummary(args: {
|
|
65
|
+
compensationType: VolunteerCompensationType | string;
|
|
66
|
+
bashPointsStipend?: number | null;
|
|
67
|
+
rateUnit?: string | null;
|
|
68
|
+
perksDescription?: string | null;
|
|
69
|
+
}): string;
|
|
70
|
+
/**
|
|
71
|
+
* Disclaimer copy for the volunteer wizard step + help-center page + booking
|
|
72
|
+
* detail. Kept here so wizard, api, and docs cite the exact same wording.
|
|
73
|
+
*/
|
|
74
|
+
export declare const VOLUNTEER_COMPENSATION_DISCLAIMER = "Volunteers are not employees or contractors. BashPoints stipends are platform credit redeemable on Bash, not wages, and don't count toward employment or 1099 reporting.";
|
|
75
|
+
//# sourceMappingURL=volunteerCompensationUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"volunteerCompensationUtils.d.ts","sourceRoot":"","sources":["../../../src/utils/service/volunteerCompensationUtils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AAEzE,gFAAgF;AAChF,eAAO,MAAM,sCAAsC,MAAM,CAAC;AAE1D,6CAA6C;AAC7C,eAAO,MAAM,qCAAqC,KAAK,CAAC;AAExD,sDAAsD;AACtD,eAAO,MAAM,oBAAoB,4BAA6B,CAAC;AAC/D,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IACxC,QAAQ,EAAE,iBAAiB,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CACzD,GAAG,MAAM,CAKT;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAC5C,CAAC,EAAE,yBAAyB,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GACvD,OAAO,CAET;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAC3C,CAAC,EAAE,yBAAyB,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GACvD,OAAO,CAET;AAED;;;;GAIG;AACH,MAAM,MAAM,+BAA+B,GACvC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC,wBAAgB,6BAA6B,CAAC,IAAI,EAAE;IAClD,gBAAgB,EAAE,yBAAyB,GAAG,MAAM,CAAC;IACrD,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC,GAAG,+BAA+B,CA+BlC;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE;IACjD,gBAAgB,EAAE,yBAAyB,GAAG,MAAM,CAAC;IACrD,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC,GAAG,MAAM,CAmBT;AAED;;;GAGG;AACH,eAAO,MAAM,iCAAiC,6KAC8H,CAAC"}
|