@bash-app/bash-common 30.171.0 → 30.172.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/definitions.d.ts +19 -2
- package/dist/definitions.d.ts.map +1 -1
- package/dist/definitions.js.map +1 -1
- package/dist/extendedSchemas.d.ts +96 -0
- package/dist/extendedSchemas.d.ts.map +1 -1
- package/dist/extendedSchemas.js +2 -0
- package/dist/extendedSchemas.js.map +1 -1
- package/dist/membershipDefinitions.d.ts +2 -0
- package/dist/membershipDefinitions.d.ts.map +1 -1
- package/dist/membershipDefinitions.js +3 -1
- package/dist/membershipDefinitions.js.map +1 -1
- package/dist/utils/__tests__/paymentUtils.test.js +13 -16
- package/dist/utils/__tests__/paymentUtils.test.js.map +1 -1
- package/dist/utils/apiUtils.d.ts.map +1 -1
- package/dist/utils/apiUtils.js +16 -6
- package/dist/utils/apiUtils.js.map +1 -1
- package/dist/utils/discountEngine/__tests__/bestPriceResolver.test.js +4 -3
- package/dist/utils/discountEngine/__tests__/bestPriceResolver.test.js.map +1 -1
- package/dist/utils/discountEngine/discountCalculator.d.ts +7 -1
- package/dist/utils/discountEngine/discountCalculator.d.ts.map +1 -1
- package/dist/utils/discountEngine/discountCalculator.js +6 -4
- package/dist/utils/discountEngine/discountCalculator.js.map +1 -1
- package/dist/utils/paymentUtils.d.ts +9 -4
- package/dist/utils/paymentUtils.d.ts.map +1 -1
- package/dist/utils/paymentUtils.js +18 -7
- package/dist/utils/paymentUtils.js.map +1 -1
- package/package.json +2 -1
- package/prisma/schema.prisma +35 -2
- package/src/definitions.ts +19 -2
- package/src/extendedSchemas.ts +6 -0
- package/src/membershipDefinitions.ts +3 -1
- package/src/utils/__tests__/paymentUtils.test.ts +14 -16
- package/src/utils/apiUtils.ts +21 -9
- package/src/utils/discountEngine/__tests__/bestPriceResolver.test.ts +6 -5
- package/src/utils/discountEngine/discountCalculator.ts +16 -9
- package/src/utils/paymentUtils.ts +19 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discountCalculator.js","sourceRoot":"","sources":["../../../src/utils/discountEngine/discountCalculator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACvG,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"discountCalculator.js","sourceRoot":"","sources":["../../../src/utils/discountEngine/discountCalculator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACvG,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAuB3D;;GAEG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CACxC,SAAyC,EACzC,WAAmB,EAAE,WAAW;AAChC,QAAgB,EACA,EAAE;IAClB,MAAM,aAAa,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC7C,IAAI,gBAAgB,GAAG,CAAC,CAAC;IACzB,IAAI,YAAY,GAAkC,YAAY,CAAC;IAC/D,IAAI,aAAa,GAAG,CAAC,CAAC;IAEtB,IAAI,SAAS,CAAC,wBAAwB,EAAE,CAAC;QACvC,sBAAsB;QACtB,YAAY,GAAG,YAAY,CAAC;QAC5B,aAAa,GAAG,SAAS,CAAC,wBAAwB,CAAC;QACnD,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,aAAa,GAAG,SAAS,CAAC,wBAAwB,CAAC,GAAG,GAAG,CAAC,CAAC;IAC5F,CAAC;SAAM,IAAI,SAAS,CAAC,qBAAqB,EAAE,CAAC;QAC3C,oDAAoD;QACpD,YAAY,GAAG,cAAc,CAAC;QAC9B,aAAa,GAAG,SAAS,CAAC,qBAAqB,CAAC;QAChD,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,qBAAqB,EAAE,aAAa,CAAC,CAAC;IAC9E,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,aAAa,GAAG,gBAAgB,CAAC,CAAC;IAEjE,OAAO;QACL,UAAU,EAAE,YAAY;QACxB,QAAQ,EAAE,SAAS,CAAC,EAAE;QACtB,UAAU,EAAE,SAAS,CAAC,IAAI;QAC1B,YAAY;QACZ,aAAa;QACb,gBAAgB;QAChB,aAAa,EAAE,aAAa;QAC5B,UAAU;QACV,qFAAqF;QACrF,0EAA0E;QAC1E,GAAG,CAAC,SAAS,CAAC,UAAU;YACtB,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI;YAC5B,WAAW,EAAE;gBACX,MAAM,EAAE,SAAS,CAAC,QAAQ,CAAC,MAAM;gBACjC,cAAc,EAAE,GAAG,EAAE,sEAAsE;gBAC3F,gBAAgB,EAAE,IAAI,CAAC,KAAK,CAAC,gBAAgB,GAAG,IAAI,CAAC;aACtD;SACF,CAAC;KACL,CAAC;AACJ,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAC3C,KAAmB,EACnB,WAAmB,EAAE,WAAW;AAChC,QAAgB,EAChB,MAAe,EACC,EAAE;IAClB,MAAM,aAAa,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC7C,IAAI,gBAAgB,GAAG,CAAC,CAAC;IACzB,IAAI,YAAY,GAAiD,YAAY,CAAC;IAC9E,IAAI,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC;IAExC,gCAAgC;IAChC,QAAQ,KAAK,CAAC,SAAS,EAAE,CAAC;QACxB,KAAK,gBAAgB,CAAC,IAAI;YACxB,gBAAgB,GAAG,qBAAqB,CAAC,KAAK,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;YACvE,YAAY,GAAG,YAAY,CAAC,CAAC,wBAAwB;YACrD,MAAM;QAER,KAAK,gBAAgB,CAAC,cAAc;YAClC,gBAAgB,GAAG,sBAAsB,CAAC,KAAK,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;YACxE,YAAY,GAAG,KAAK,CAAC,YAAY,KAAK,iBAAiB,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,cAAc,CAAC;YACnG,MAAM;QAER,KAAK,gBAAgB,CAAC,eAAe;YACnC,gBAAgB,GAAG,uBAAuB,CAAC,KAAK,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;YACzE,YAAY,GAAG,KAAK,CAAC,YAAY,KAAK,iBAAiB,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,cAAc,CAAC;YACnG,MAAM;QAER,KAAK,gBAAgB,CAAC,UAAU,CAAC;QACjC,KAAK,gBAAgB,CAAC,UAAU,CAAC;QACjC,KAAK,gBAAgB,CAAC,OAAO,CAAC;QAC9B,KAAK,gBAAgB,CAAC,SAAS;YAC7B,wDAAwD;YACxD,IAAI,KAAK,CAAC,YAAY,KAAK,iBAAiB,CAAC,UAAU,EAAE,CAAC;gBACxD,YAAY,GAAG,YAAY,CAAC;gBAC5B,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC,GAAG,GAAG,CAAC,CAAC;YAC7E,CAAC;iBAAM,CAAC;gBACN,YAAY,GAAG,cAAc,CAAC;gBAC9B,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,aAAa,GAAG,QAAQ,EAAE,aAAa,CAAC,CAAC;YAC7E,CAAC;YACD,MAAM;QAER,KAAK,gBAAgB,CAAC,MAAM;YAC1B,oCAAoC;YACpC,gBAAgB,GAAG,KAAK,CAAC,aAAa,IAAI,CAAC,CAAC;YAC5C,YAAY,GAAG,cAAc,CAAC;YAC9B,MAAM;QAER,KAAK,gBAAgB,CAAC,QAAQ;YAC5B,2CAA2C;YAC3C,gBAAgB,GAAG,KAAK,CAAC,wBAAwB,IAAI,CAAC,CAAC;YACvD,YAAY,GAAG,cAAc,CAAC;YAC9B,MAAM;QAER,KAAK,gBAAgB,CAAC,WAAW;YAC/B,4CAA4C;YAC5C,IAAI,KAAK,CAAC,YAAY,KAAK,iBAAiB,CAAC,UAAU,EAAE,CAAC;gBACxD,YAAY,GAAG,YAAY,CAAC;gBAC5B,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC,GAAG,GAAG,CAAC,CAAC;YAC7E,CAAC;iBAAM,CAAC;gBACN,YAAY,GAAG,cAAc,CAAC;gBAC9B,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;YAClE,CAAC;YACD,MAAM;QAER;YACE,6BAA6B;YAC7B,IAAI,KAAK,CAAC,YAAY,KAAK,iBAAiB,CAAC,UAAU,EAAE,CAAC;gBACxD,YAAY,GAAG,YAAY,CAAC;gBAC5B,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC,GAAG,GAAG,CAAC,CAAC;YAC7E,CAAC;iBAAM,CAAC;gBACN,YAAY,GAAG,cAAc,CAAC;gBAC9B,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;YAClE,CAAC;IACL,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,aAAa,GAAG,gBAAgB,CAAC,CAAC;IAEjE,OAAO;QACL,UAAU,EAAE,eAAe;QAC3B,QAAQ,EAAE,KAAK,CAAC,EAAE;QAClB,UAAU,EAAE,KAAK,CAAC,KAAK;QACvB,YAAY;QACZ,aAAa;QACb,gBAAgB;QAChB,aAAa,EAAE,aAAa;QAC5B,UAAU;QACV,wCAAwC;QACxC,GAAG,CAAC,KAAK,CAAC,mBAAmB,IAAI,MAAM,IAAI,KAAK,CAAC,cAAc,IAAI;YACjE,WAAW,EAAE;gBACX,MAAM;gBACN,cAAc,EAAE,KAAK,CAAC,cAAc;gBACpC,gBAAgB,EAAE,IAAI,CAAC,KAAK,CAAC,gBAAgB,GAAG,CAAC,KAAK,CAAC,cAAc,GAAG,GAAG,CAAC,CAAC;aAC9E;SACF,CAAC;KACH,CAAC;AACJ,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,KAAmB,EACnB,QAAgB,EAChB,WAAmB,EACX,EAAE;IACV,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,IAAI,CAAC,CAAC;IAC3C,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,IAAI,CAAC,CAAC;IAC3C,MAAM,kBAAkB,GAAG,KAAK,CAAC,kBAAkB,IAAI,GAAG,CAAC,CAAC,0BAA0B;IAEtF,6CAA6C;IAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,WAAW,GAAG,WAAW,CAAC,CAAC,CAAC;IAChE,MAAM,WAAW,GAAG,IAAI,GAAG,WAAW,CAAC;IAEvC,qCAAqC;IACrC,MAAM,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,GAAG,kBAAkB,CAAC,GAAG,GAAG,CAAC,CAAC;IAC/E,OAAO,WAAW,GAAG,iBAAiB,CAAC;AACzC,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,KAAmB,EACnB,QAAgB,EAChB,WAAmB,EACX,EAAE;IACV,8BAA8B;IAC9B,IAAI,KAAK,CAAC,YAAY,IAAI,QAAQ,GAAG,KAAK,CAAC,YAAY,EAAE,CAAC;QACxD,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,KAAK,CAAC,YAAY,IAAI,QAAQ,GAAG,KAAK,CAAC,YAAY,EAAE,CAAC;QACxD,OAAO,CAAC,CAAC,CAAC,2BAA2B;IACvC,CAAC;IAED,6BAA6B;IAC7B,IAAI,KAAK,CAAC,eAAe,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,KAAK,CAAC,eAA2D,CAAC;QAChF,qCAAqC;QACrC,MAAM,cAAc,GAAG,KAAK;aACzB,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,IAAI,IAAI,CAAC,GAAG,CAAC;aACpC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAE9C,IAAI,cAAc,EAAE,CAAC;YACnB,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,GAAG,QAAQ,GAAG,cAAc,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC;IAED,+BAA+B;IAC/B,IAAI,KAAK,CAAC,YAAY,KAAK,iBAAiB,CAAC,UAAU,EAAE,CAAC;QACxD,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,GAAG,QAAQ,GAAG,KAAK,CAAC,aAAa,CAAC,GAAG,GAAG,CAAC,CAAC;IAC1E,CAAC;SAAM,CAAC;QACN,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,aAAa,GAAG,QAAQ,EAAE,WAAW,GAAG,QAAQ,CAAC,CAAC;IAC1E,CAAC;AACH,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,KAAmB,EACnB,QAAgB,EAChB,WAAmB,EACX,EAAE;IACV,6BAA6B;IAC7B,OAAO,sBAAsB,CAAC,KAAK,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;AAC9D,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CACxC,KAAmB,EACnB,WAAmB,EACnB,WAAiB,EACT,EAAE;IACV,4CAA4C;IAC5C,IAAI,KAAK,CAAC,cAAc,IAAI,WAAW,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC;QAC/D,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,KAAK,CAAC,YAAY,KAAK,iBAAiB,CAAC,UAAU,EAAE,CAAC;QACxD,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,GAAG,KAAK,CAAC,aAAa,CAAC,GAAG,GAAG,CAAC,CAAC;IAC/D,CAAC;SAAM,CAAC;QACN,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;IACpD,CAAC;AACH,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,KAAmB,EACnB,YAAoD,EAC5C,EAAE;IACV,4DAA4D;IAC5D,OAAO,KAAK,CAAC,aAAa,IAAI,CAAC,CAAC;AAClC,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,MAAsB,EAAU,EAAE;IAC1E,IAAI,MAAM,CAAC,YAAY,KAAK,YAAY,EAAE,CAAC;QACzC,OAAO,GAAG,MAAM,CAAC,UAAU,MAAM,MAAM,CAAC,aAAa,OAAO,qBAAqB,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IAC3H,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,MAAM,CAAC,UAAU,OAAO,qBAAqB,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAChG,CAAC;AACH,CAAC,CAAC"}
|
|
@@ -30,15 +30,20 @@ export declare function convertDollarsToCents(price: number | undefined | null):
|
|
|
30
30
|
*/
|
|
31
31
|
export declare function calculateStripeFee(amountDollars: number): number;
|
|
32
32
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
33
|
+
* Stripe card processing pass-through (2.9% + $0.30), in cents — single source of truth with {@link STRIPE_PROCESSING_FEE}.
|
|
34
|
+
* Use for Connect `application_fee_amount` and checkout line items so totals match the checkout UI.
|
|
35
|
+
*/
|
|
36
|
+
export declare function calculateStripeProcessingFeeCents(amountCents: number): number;
|
|
37
|
+
/**
|
|
38
|
+
* Bash **platform** fee only (currently 0% — no Bash take on tickets). Not the Stripe processing fee.
|
|
39
|
+
* @deprecated Prefer {@link calculateStripeProcessingFeeCents} for Stripe pass-through on ticket/donation charges.
|
|
35
40
|
*/
|
|
36
41
|
export declare function calculateBashAppFee(total: number): number;
|
|
37
42
|
/**
|
|
38
43
|
* Calculate Stripe's processing fee for donations — transparent pass-through only.
|
|
39
|
-
*
|
|
44
|
+
* Same formula as tickets: {@link STRIPE_PROCESSING_FEE}.
|
|
40
45
|
* @param amountCents - Donation amount in cents
|
|
41
|
-
* @returns Stripe processing fee in cents
|
|
46
|
+
* @returns Stripe processing fee in cents (integer)
|
|
42
47
|
*/
|
|
43
48
|
export declare function calculateStripeDonationFee(amountCents: number): number;
|
|
44
49
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paymentUtils.d.ts","sourceRoot":"","sources":["../../src/utils/paymentUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,UAAU,EAAE,gBAAgB,IAAI,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"paymentUtils.d.ts","sourceRoot":"","sources":["../../src/utils/paymentUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,UAAU,EAAE,gBAAgB,IAAI,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAO5H,OAAO,EACL,sBAAsB,EAEvB,MAAM,mBAAmB,CAAC;AAE3B;;;;GAIG;AACH,wBAAgB,8BAA8B,CAC5C,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,kBAAkB,GAAG,SAAS,GACxC,MAAM,CAeR;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,WAAW,EAAE,UAAU,EAAE,EACzB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,sBAAsB,EAAE,CAAC,GAChD,MAAM,CAYR;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,UAAU,EAAE,EACzB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,sBAAsB,EAAE,CAAC,GAChD,MAAM,CAYR;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAC/B,MAAM,CAKR;AACD,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAC/B,MAAM,CAKR;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAIhE;AAED;;;GAGG;AACH,wBAAgB,iCAAiC,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAI7E;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED;;;;;GAKG;AACH,wBAAgB,yCAAyC,CACvD,KAAK,EAAE,MAAM,EACb,cAAc,CAAC,EAAE,cAAc,GAAG,IAAI,GACrC,MAAM,CAkBR;AAED;;;;;;GAMG;AACH,wBAAgB,yCAAyC,CACvD,KAAK,EAAE,MAAM,EACb,cAAc,CAAC,EAAE,cAAc,GAAG,IAAI,GACrC,MAAM,CAeR;AAED;;;;;;GAMG;AACH,wBAAgB,yCAAyC,CACvD,KAAK,EAAE,MAAM,EACb,cAAc,CAAC,EAAE,cAAc,GAAG,IAAI,GACrC,MAAM,CAeR;AAMD,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;KAC/B,GAAG,IAAI,sBAAsB,GAAG,oBAAoB;CACtD,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,EAAE,mBAe5B,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { VenuePricingPlan as VenuePricingPlanOption } from "@prisma/client";
|
|
2
|
-
import { BASH_EVENT_FEES, SERVICE_BOOKING_FEES,
|
|
2
|
+
import { BASH_EVENT_FEES, PARTNER_PAYMENT_FEES, SERVICE_BOOKING_FEES, STRIPE_PROCESSING_FEE, } from "../membershipDefinitions.js";
|
|
3
3
|
import { PRICE_DOLLARS_AND_CENTS_RATIO, } from "../definitions.js";
|
|
4
4
|
/**
|
|
5
5
|
* Returns the amount of discount in dollars
|
|
@@ -78,23 +78,34 @@ export function convertDollarsToCents(price) {
|
|
|
78
78
|
export function calculateStripeFee(amountDollars) {
|
|
79
79
|
if (amountDollars <= 0)
|
|
80
80
|
return 0;
|
|
81
|
-
|
|
81
|
+
const cents = Math.round(amountDollars * PRICE_DOLLARS_AND_CENTS_RATIO);
|
|
82
|
+
return convertCentsToDollars(calculateStripeProcessingFeeCents(cents));
|
|
82
83
|
}
|
|
83
84
|
/**
|
|
84
|
-
*
|
|
85
|
-
*
|
|
85
|
+
* Stripe card processing pass-through (2.9% + $0.30), in cents — single source of truth with {@link STRIPE_PROCESSING_FEE}.
|
|
86
|
+
* Use for Connect `application_fee_amount` and checkout line items so totals match the checkout UI.
|
|
87
|
+
*/
|
|
88
|
+
export function calculateStripeProcessingFeeCents(amountCents) {
|
|
89
|
+
if (amountCents <= 0)
|
|
90
|
+
return 0;
|
|
91
|
+
const { percent, fixedCents } = STRIPE_PROCESSING_FEE;
|
|
92
|
+
return Math.floor(amountCents * percent) + fixedCents;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Bash **platform** fee only (currently 0% — no Bash take on tickets). Not the Stripe processing fee.
|
|
96
|
+
* @deprecated Prefer {@link calculateStripeProcessingFeeCents} for Stripe pass-through on ticket/donation charges.
|
|
86
97
|
*/
|
|
87
98
|
export function calculateBashAppFee(total) {
|
|
88
99
|
return parseFloat((total * BASH_EVENT_FEES.Basic.percent).toFixed(2));
|
|
89
100
|
}
|
|
90
101
|
/**
|
|
91
102
|
* Calculate Stripe's processing fee for donations — transparent pass-through only.
|
|
92
|
-
*
|
|
103
|
+
* Same formula as tickets: {@link STRIPE_PROCESSING_FEE}.
|
|
93
104
|
* @param amountCents - Donation amount in cents
|
|
94
|
-
* @returns Stripe processing fee in cents
|
|
105
|
+
* @returns Stripe processing fee in cents (integer)
|
|
95
106
|
*/
|
|
96
107
|
export function calculateStripeDonationFee(amountCents) {
|
|
97
|
-
return
|
|
108
|
+
return calculateStripeProcessingFeeCents(amountCents);
|
|
98
109
|
}
|
|
99
110
|
/**
|
|
100
111
|
* Calculate platform fee for bash tickets/donations with membership tier discounts and caps
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paymentUtils.js","sourceRoot":"","sources":["../../src/utils/paymentUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkD,gBAAgB,IAAI,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC5H,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,oBAAoB,
|
|
1
|
+
{"version":3,"file":"paymentUtils.js","sourceRoot":"","sources":["../../src/utils/paymentUtils.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bash-app/bash-common",
|
|
3
|
-
"version": "30.
|
|
3
|
+
"version": "30.172.0",
|
|
4
4
|
"description": "Common data and scripts to use on the frontend and backend",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"generate": "prisma generate",
|
|
11
11
|
"db": "prisma generate && prisma db push",
|
|
12
12
|
"tsc": "NODE_OPTIONS='--max-old-space-size=16384' tsc",
|
|
13
|
+
"typecheck": "NODE_OPTIONS='--max-old-space-size=16384' tsc --noEmit",
|
|
13
14
|
"block-malicious": "../scripts/block-malicious-patterns.sh .",
|
|
14
15
|
"prepublishOnly": "npm run build"
|
|
15
16
|
},
|
package/prisma/schema.prisma
CHANGED
|
@@ -447,9 +447,9 @@ model Promoter {
|
|
|
447
447
|
earningsGenerated Float @default(0.00)
|
|
448
448
|
createdAt DateTime @default(now())
|
|
449
449
|
updatedAt DateTime @updatedAt
|
|
450
|
-
userId String
|
|
450
|
+
userId String? // null until invited promoter signs up (do not use host id as placeholder)
|
|
451
451
|
promoCodes BashEventPromoCode[]
|
|
452
|
-
promoterUser User
|
|
452
|
+
promoterUser User? @relation(fields: [userId], references: [id])
|
|
453
453
|
|
|
454
454
|
@@unique([promoterId, promotedForBash])
|
|
455
455
|
}
|
|
@@ -614,6 +614,7 @@ model BashEvent {
|
|
|
614
614
|
topPromoterPrize String? // Optional prize label: "Free table for your crew"
|
|
615
615
|
promoterLeaderboardIsPublic Boolean @default(false) // Host opts in to public leaderboard
|
|
616
616
|
showAttendees Boolean @default(true)
|
|
617
|
+
attendeeDisplayMode String @default("All") // "All" | "NetworkOnly" | "Hidden"
|
|
617
618
|
servicePreferences Json? // New tiered status: { "Entertainment": "need", "Sponsors": "booked_closed", ... }
|
|
618
619
|
bookedServices Json? // Booked service details: { "Entertainment": { serviceId: "...", providerId: "...", bookedAt: "..." }, ... }
|
|
619
620
|
serviceVisibility Json? // DEPRECATED: Use servicePreferences instead. Kept for backward compatibility during migration.
|
|
@@ -1073,6 +1074,21 @@ model BookingCommission {
|
|
|
1073
1074
|
@@index([status])
|
|
1074
1075
|
}
|
|
1075
1076
|
|
|
1077
|
+
/// Inbound sponsor / brand partnership interest from the public /for-sponsors page.
|
|
1078
|
+
model SponsorInterest {
|
|
1079
|
+
id String @id @default(cuid())
|
|
1080
|
+
companyName String
|
|
1081
|
+
contactName String
|
|
1082
|
+
email String
|
|
1083
|
+
phone String?
|
|
1084
|
+
budget String?
|
|
1085
|
+
message String?
|
|
1086
|
+
createdAt DateTime @default(now())
|
|
1087
|
+
|
|
1088
|
+
@@index([email])
|
|
1089
|
+
@@index([createdAt])
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1076
1092
|
model TicketTier {
|
|
1077
1093
|
id String @id @default(cuid())
|
|
1078
1094
|
bashEventId String
|
|
@@ -1514,6 +1530,7 @@ model User {
|
|
|
1514
1530
|
familyName String?
|
|
1515
1531
|
nameChangeCount Int @default(0)
|
|
1516
1532
|
hash String?
|
|
1533
|
+
previousPasswordHashes String[] @default([]) // Last 5 bcrypt hashes (oldest first) for password-reuse prevention
|
|
1517
1534
|
emailVerified DateTime?
|
|
1518
1535
|
image String?
|
|
1519
1536
|
imageUpdatedAt DateTime? // When Google/OAuth image was last updated
|
|
@@ -1588,6 +1605,8 @@ model User {
|
|
|
1588
1605
|
venmoUsername String?
|
|
1589
1606
|
venmoQRCodeUrl String?
|
|
1590
1607
|
zelleEmail String?
|
|
1608
|
+
/// Optional Venmo / Zelle / CashApp handle shown to hosts (promo requests, code assignment). Bash does not move money.
|
|
1609
|
+
paymentHandle String?
|
|
1591
1610
|
zellePhone String?
|
|
1592
1611
|
zelleQRCodeUrl String?
|
|
1593
1612
|
isAmbashador Boolean @default(false)
|
|
@@ -1620,6 +1639,7 @@ model User {
|
|
|
1620
1639
|
birthdayOfferDeliveries BirthdayOfferDelivery[]
|
|
1621
1640
|
birthdayBoostGrants BirthdayBoostGrant[]
|
|
1622
1641
|
birthdayRewardRedemptions BirthdayRewardRedemption[]
|
|
1642
|
+
birthdayRewardFavorites BirthdayRewardFavorite[]
|
|
1623
1643
|
birthdayDealSuggestions BirthdayDealSuggestion[]
|
|
1624
1644
|
rewardReports RewardReport[]
|
|
1625
1645
|
rewardReportsReviewed RewardReport[] @relation("RewardReportReviewedBy")
|
|
@@ -5837,6 +5857,19 @@ model BirthdayBoostGrant {
|
|
|
5837
5857
|
@@index([birthdayYear])
|
|
5838
5858
|
}
|
|
5839
5859
|
|
|
5860
|
+
/// Starred catalog or national-chain birthday deals (rewardId = DB catalog id or national-* id from code)
|
|
5861
|
+
model BirthdayRewardFavorite {
|
|
5862
|
+
id String @id @default(cuid())
|
|
5863
|
+
userId String
|
|
5864
|
+
rewardId String
|
|
5865
|
+
createdAt DateTime @default(now())
|
|
5866
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
5867
|
+
|
|
5868
|
+
@@unique([userId, rewardId])
|
|
5869
|
+
@@index([rewardId])
|
|
5870
|
+
@@index([userId])
|
|
5871
|
+
}
|
|
5872
|
+
|
|
5840
5873
|
// User-recorded places where they picked up a birthday reward (with optional rating)
|
|
5841
5874
|
model BirthdayRewardRedemption {
|
|
5842
5875
|
id String @id @default(cuid())
|
package/src/definitions.ts
CHANGED
|
@@ -546,18 +546,33 @@ export interface SignInEmailWithPassword {
|
|
|
546
546
|
|
|
547
547
|
export interface ForgotPassword {
|
|
548
548
|
email: string;
|
|
549
|
+
/** Internal app path to open after successful reset (optional; server validates). */
|
|
550
|
+
redirect?: string;
|
|
549
551
|
}
|
|
550
552
|
|
|
553
|
+
/** Password reset: either legacy `{ email, otp, password }` or `{ resetToken, password }`. */
|
|
551
554
|
export interface ResetPassword {
|
|
552
|
-
email: string;
|
|
553
555
|
password: string;
|
|
554
|
-
|
|
556
|
+
email?: string;
|
|
557
|
+
otp?: string;
|
|
558
|
+
/** Opaque JWT from /reset-password/<token> link (preferred; email not in URL). */
|
|
559
|
+
resetToken?: string;
|
|
555
560
|
}
|
|
556
561
|
|
|
557
562
|
export interface ApiResult<T, P extends ErrorDataType = ErrorDataType> {
|
|
558
563
|
data?: T;
|
|
564
|
+
/** PATCH group member / some RSVP endpoints — true when BashPoints RSVP bonus was newly awarded */
|
|
565
|
+
rsvpBonusAwarded?: boolean;
|
|
566
|
+
/** POST event task assign — true when volunteer guestlist invite was created */
|
|
567
|
+
addedToGuestlist?: boolean;
|
|
568
|
+
/** POST event task assign — true when FirstTaskTaken BashPoints were newly awarded */
|
|
569
|
+
taskBonusAwarded?: boolean;
|
|
570
|
+
/** POST /volunteer — true when first service profile bonus was newly awarded */
|
|
571
|
+
bonusAwarded?: boolean;
|
|
559
572
|
status?: number;
|
|
560
573
|
token?: string;
|
|
574
|
+
/** e.g. safe path to navigate after password reset */
|
|
575
|
+
returnTo?: string;
|
|
561
576
|
error?: string;
|
|
562
577
|
errorType?: ApiErrorType;
|
|
563
578
|
errorData?: P;
|
|
@@ -785,6 +800,8 @@ export interface StripeBusinessLinkArgs {
|
|
|
785
800
|
export interface StripeConfirmPaymentResult {
|
|
786
801
|
bashEventId: string;
|
|
787
802
|
numberOfTickets: number;
|
|
803
|
+
/** Sum of tier prices × qty (cents), for client-side BashPoints purchase-reward estimate */
|
|
804
|
+
ticketsSubtotalCents?: number;
|
|
788
805
|
}
|
|
789
806
|
|
|
790
807
|
export interface IMediaUploadArgs {
|
package/src/extendedSchemas.ts
CHANGED
|
@@ -146,6 +146,8 @@ export const FRONT_END_USER_DATA_TO_SELECT = {
|
|
|
146
146
|
isBashInsider: true,
|
|
147
147
|
scoutTier: true,
|
|
148
148
|
isFirstInCity: true,
|
|
149
|
+
/** Venmo / Zelle / CashApp handle for off-platform payouts (promoters). */
|
|
150
|
+
paymentHandle: true,
|
|
149
151
|
} satisfies Prisma.UserSelect;
|
|
150
152
|
|
|
151
153
|
export const PRIVATE_USER_ACCOUNT_TO_SELECT = {
|
|
@@ -811,6 +813,8 @@ export interface VolunteerServiceExt extends VolunteerService {
|
|
|
811
813
|
serviceRange?: ServiceRange | null;
|
|
812
814
|
media?: Media[];
|
|
813
815
|
links?: Link[];
|
|
816
|
+
/** Set by API when a first-profile BashPoints bonus was awarded on create/update. */
|
|
817
|
+
bonusAwarded?: boolean;
|
|
814
818
|
// availableDateTimes?: Availability[];
|
|
815
819
|
}
|
|
816
820
|
|
|
@@ -930,6 +934,8 @@ export interface InvitationExtraData extends Invitation {
|
|
|
930
934
|
export interface AssociatedBashExt extends AssociatedBash {
|
|
931
935
|
bashEvent: BashEventExt;
|
|
932
936
|
invitation?: Partial<InvitationExt>;
|
|
937
|
+
/** Present on upsert response when RSVP bonus was newly awarded this request */
|
|
938
|
+
rsvpBonusAwarded?: boolean;
|
|
933
939
|
}
|
|
934
940
|
|
|
935
941
|
export interface AssociatedServiceExt extends AssociatedService {
|
|
@@ -232,6 +232,8 @@ export const SCOUT_PROGRAM_CONFIG = {
|
|
|
232
232
|
scoutCommissionRate: 0.03, // 3% commission on completed bookings
|
|
233
233
|
agentCommissionRate: 0.06, // 6% commission (upgraded status)
|
|
234
234
|
agentThreshold: 5, // 5+ service profiles = Agent status
|
|
235
|
+
/** Higher rate when the booked service is a sponsor profile (Scout-referred). */
|
|
236
|
+
sponsorBrokerCommissionRate: 0.10, // 10% on sponsor-profile bookings
|
|
235
237
|
} as const;
|
|
236
238
|
|
|
237
239
|
// ============================================================================
|
|
@@ -507,7 +509,7 @@ export const MEMBERSHIP_LIMITS: Record<MembershipTier, {
|
|
|
507
509
|
Basic: {
|
|
508
510
|
// Event Creation
|
|
509
511
|
canCreateEvents: true,
|
|
510
|
-
minimumTicketPriceCents: 0, // $0
|
|
512
|
+
minimumTicketPriceCents: 0, // $0 or any price — platform service fee only on tickets $5+
|
|
511
513
|
maxEventsPerMonth: -1, // Unlimited
|
|
512
514
|
featuredEventsPerMonth: 0, // Must pay
|
|
513
515
|
|
|
@@ -9,6 +9,8 @@ import {
|
|
|
9
9
|
convertDollarsToCents,
|
|
10
10
|
calculateBashAppFee,
|
|
11
11
|
calculateBashAppFeeWithMembershipDiscount,
|
|
12
|
+
calculateStripeFee,
|
|
13
|
+
calculateStripeProcessingFeeCents,
|
|
12
14
|
calculateTotalPriceWithoutTax,
|
|
13
15
|
calculateTotalBashPoints,
|
|
14
16
|
calculateStripeDonationFee,
|
|
@@ -72,28 +74,24 @@ describe("PaymentUtils - Core Functions", () => {
|
|
|
72
74
|
});
|
|
73
75
|
|
|
74
76
|
describe("Platform Fees", () => {
|
|
75
|
-
test("calculateBashAppFee", () => {
|
|
76
|
-
expect(calculateBashAppFee(1000)).toBe(
|
|
77
|
+
test("calculateBashAppFee is Bash platform cut only (currently 0%)", () => {
|
|
78
|
+
expect(calculateBashAppFee(1000)).toBe(0);
|
|
77
79
|
});
|
|
78
80
|
|
|
79
|
-
test("calculateBashAppFeeWithMembershipDiscount -
|
|
80
|
-
|
|
81
|
-
expect(
|
|
81
|
+
test("calculateBashAppFeeWithMembershipDiscount - all tiers 0% Bash fee", () => {
|
|
82
|
+
expect(calculateBashAppFeeWithMembershipDiscount(10000, "Basic" as any)).toBe(0);
|
|
83
|
+
expect(calculateBashAppFeeWithMembershipDiscount(10000, "Premium" as any)).toBe(0);
|
|
84
|
+
expect(calculateBashAppFeeWithMembershipDiscount(100, "Premium" as any)).toBe(0);
|
|
85
|
+
expect(calculateBashAppFeeWithMembershipDiscount(100000, "Basic" as any)).toBe(0);
|
|
82
86
|
});
|
|
83
87
|
|
|
84
|
-
test("
|
|
85
|
-
|
|
86
|
-
expect(
|
|
88
|
+
test("calculateStripeProcessingFeeCents matches 2.9% + $0.30 on subtotal", () => {
|
|
89
|
+
expect(calculateStripeProcessingFeeCents(10000)).toBe(320); // $100 ticket
|
|
90
|
+
expect(calculateStripeProcessingFeeCents(0)).toBe(0);
|
|
87
91
|
});
|
|
88
92
|
|
|
89
|
-
test("
|
|
90
|
-
|
|
91
|
-
expect(fee).toBe(50); // minimum is 50 cents
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
test("applies cap", () => {
|
|
95
|
-
const fee = calculateBashAppFeeWithMembershipDiscount(100000, "Basic" as any);
|
|
96
|
-
expect(fee).toBe(1000); // cap at $10
|
|
93
|
+
test("calculateStripeFee (dollars) aligns with calculateStripeProcessingFeeCents", () => {
|
|
94
|
+
expect(calculateStripeFee(100)).toBe(3.2);
|
|
97
95
|
});
|
|
98
96
|
});
|
|
99
97
|
|
package/src/utils/apiUtils.ts
CHANGED
|
@@ -21,6 +21,15 @@ export function getUserName(contactOrUser: Partial<CombinedUserOrContact> | unde
|
|
|
21
21
|
return combinedName ?? user.email ?? '';
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
/** Treat null, undefined, whitespace-only, or empty string as "no image". */
|
|
25
|
+
function nonEmptyImageUrl(url: string | null | undefined): string | undefined {
|
|
26
|
+
if (url == null) {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
const trimmed = url.trim();
|
|
30
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
31
|
+
}
|
|
32
|
+
|
|
24
33
|
export function getUserImage(contactOrUser: CombinedUserOrContact | undefined): string {
|
|
25
34
|
if (!contactOrUser) {
|
|
26
35
|
return '';
|
|
@@ -30,25 +39,28 @@ export function getUserImage(contactOrUser: CombinedUserOrContact | undefined):
|
|
|
30
39
|
return noProfilePicture;
|
|
31
40
|
}
|
|
32
41
|
const user = contactOrUser as CombinedUser;
|
|
33
|
-
|
|
42
|
+
|
|
43
|
+
const uploaded = nonEmptyImageUrl(user.uploadedImage);
|
|
44
|
+
const googleImg = nonEmptyImageUrl(user.image);
|
|
45
|
+
|
|
34
46
|
// Prioritize the most recently updated image for best UX
|
|
35
47
|
// If both images exist, compare timestamps
|
|
36
|
-
if (
|
|
48
|
+
if (uploaded && googleImg) {
|
|
37
49
|
const uploadedTime = user.uploadedImageUpdatedAt ? new Date(user.uploadedImageUpdatedAt).getTime() : 0;
|
|
38
50
|
const googleTime = user.imageUpdatedAt ? new Date(user.imageUpdatedAt).getTime() : 0;
|
|
39
|
-
|
|
51
|
+
|
|
40
52
|
// Return the most recently updated image
|
|
41
53
|
if (uploadedTime > googleTime) {
|
|
42
|
-
return
|
|
54
|
+
return uploaded;
|
|
43
55
|
} else if (googleTime > 0) {
|
|
44
|
-
return
|
|
56
|
+
return googleImg;
|
|
45
57
|
}
|
|
46
58
|
// If no timestamps, fall back to uploadedImage (existing behavior for backward compatibility)
|
|
47
|
-
return
|
|
59
|
+
return uploaded;
|
|
48
60
|
}
|
|
49
|
-
|
|
50
|
-
// If only one image exists, return it
|
|
51
|
-
return
|
|
61
|
+
|
|
62
|
+
// If only one image exists, return it (never return "" — that breaks <img src="">)
|
|
63
|
+
return uploaded ?? googleImg ?? noProfilePicture;
|
|
52
64
|
}
|
|
53
65
|
|
|
54
66
|
export function getContactOrUserEmail(contactOrUser: Partial<ContactOrUser>): string {
|
|
@@ -533,11 +533,12 @@ describe("bestPriceResolver", () => {
|
|
|
533
533
|
});
|
|
534
534
|
|
|
535
535
|
describe("findBestPrice - Attribution", () => {
|
|
536
|
-
it("should track promoter attribution", () => {
|
|
537
|
-
const promoWithPromoter
|
|
536
|
+
it("should track promoter attribution using Promoter.userId (not Promoter row id)", () => {
|
|
537
|
+
const promoWithPromoter = {
|
|
538
538
|
...mockPromoCode,
|
|
539
|
-
promoterId: "promoter-
|
|
540
|
-
|
|
539
|
+
promoterId: "promoter-row-cuid",
|
|
540
|
+
promoter: { userId: "actual-user-uuid" },
|
|
541
|
+
} as BashEventPromoCode & { promoter?: { userId: string } };
|
|
541
542
|
|
|
542
543
|
const options: BestPriceOptions = {
|
|
543
544
|
ticketPrice: 5000,
|
|
@@ -551,7 +552,7 @@ describe("bestPriceResolver", () => {
|
|
|
551
552
|
const result = findBestPrice(options);
|
|
552
553
|
|
|
553
554
|
expect(result.appliedDiscounts[0]).toHaveProperty("attribution");
|
|
554
|
-
expect(result.appliedDiscounts[0].attribution?.userId).toBe("
|
|
555
|
+
expect(result.appliedDiscounts[0].attribution?.userId).toBe("actual-user-uuid");
|
|
555
556
|
expect(result.appliedDiscounts[0].attribution?.commissionAmount).toBeGreaterThan(0);
|
|
556
557
|
});
|
|
557
558
|
});
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { BashEventPromoCode, SpecialOffer, SpecialOfferType, OfferDiscountType } from "@prisma/client";
|
|
2
2
|
import { convertCentsToDollars } from "../paymentUtils.js";
|
|
3
3
|
|
|
4
|
+
/** Promo code with optional promoter row (include `userId` for checkout attribution). */
|
|
5
|
+
export type BashEventPromoCodeWithPromoter = BashEventPromoCode & {
|
|
6
|
+
promoter?: { userId: string | null } | null;
|
|
7
|
+
};
|
|
8
|
+
|
|
4
9
|
export interface DiscountResult {
|
|
5
10
|
sourceType: 'PROMO_CODE' | 'SPECIAL_OFFER';
|
|
6
11
|
sourceId: string;
|
|
@@ -21,7 +26,7 @@ export interface DiscountResult {
|
|
|
21
26
|
* Calculate discount from a promo code
|
|
22
27
|
*/
|
|
23
28
|
export const calculatePromoCodeDiscount = (
|
|
24
|
-
promoCode:
|
|
29
|
+
promoCode: BashEventPromoCodeWithPromoter,
|
|
25
30
|
ticketPrice: number, // In cents
|
|
26
31
|
quantity: number
|
|
27
32
|
): DiscountResult => {
|
|
@@ -53,14 +58,16 @@ export const calculatePromoCodeDiscount = (
|
|
|
53
58
|
amountDiscounted,
|
|
54
59
|
originalPrice: originalTotal,
|
|
55
60
|
finalPrice,
|
|
56
|
-
//
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
// Attribution = promoter's User id only (never Promoter row id — breaks dashboards).
|
|
62
|
+
// Omit if promoter pending signup (no userId yet) or relation not loaded.
|
|
63
|
+
...(promoCode.promoterId &&
|
|
64
|
+
promoCode.promoter?.userId && {
|
|
65
|
+
attribution: {
|
|
66
|
+
userId: promoCode.promoter.userId,
|
|
67
|
+
commissionRate: 5.0, // Legacy field on AppliedDiscount; dollar commissions disabled in API
|
|
68
|
+
commissionAmount: Math.floor(amountDiscounted * 0.05),
|
|
69
|
+
},
|
|
70
|
+
}),
|
|
64
71
|
};
|
|
65
72
|
};
|
|
66
73
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { BashEventPromoCode, MembershipTier, TicketTier, VenuePricingPlan as VenuePricingPlanOption } from "@prisma/client";
|
|
2
2
|
import {
|
|
3
3
|
BASH_EVENT_FEES,
|
|
4
|
-
SERVICE_BOOKING_FEES,
|
|
5
4
|
PARTNER_PAYMENT_FEES,
|
|
5
|
+
SERVICE_BOOKING_FEES,
|
|
6
|
+
STRIPE_PROCESSING_FEE,
|
|
6
7
|
} from "../membershipDefinitions.js";
|
|
7
8
|
import {
|
|
8
9
|
NumberOfTicketsForDate,
|
|
@@ -105,12 +106,23 @@ export function convertDollarsToCents(
|
|
|
105
106
|
*/
|
|
106
107
|
export function calculateStripeFee(amountDollars: number): number {
|
|
107
108
|
if (amountDollars <= 0) return 0;
|
|
108
|
-
|
|
109
|
+
const cents = Math.round(amountDollars * PRICE_DOLLARS_AND_CENTS_RATIO);
|
|
110
|
+
return convertCentsToDollars(calculateStripeProcessingFeeCents(cents));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Stripe card processing pass-through (2.9% + $0.30), in cents — single source of truth with {@link STRIPE_PROCESSING_FEE}.
|
|
115
|
+
* Use for Connect `application_fee_amount` and checkout line items so totals match the checkout UI.
|
|
116
|
+
*/
|
|
117
|
+
export function calculateStripeProcessingFeeCents(amountCents: number): number {
|
|
118
|
+
if (amountCents <= 0) return 0;
|
|
119
|
+
const { percent, fixedCents } = STRIPE_PROCESSING_FEE;
|
|
120
|
+
return Math.floor(amountCents * percent) + fixedCents;
|
|
109
121
|
}
|
|
110
122
|
|
|
111
123
|
/**
|
|
112
|
-
*
|
|
113
|
-
* @deprecated
|
|
124
|
+
* Bash **platform** fee only (currently 0% — no Bash take on tickets). Not the Stripe processing fee.
|
|
125
|
+
* @deprecated Prefer {@link calculateStripeProcessingFeeCents} for Stripe pass-through on ticket/donation charges.
|
|
114
126
|
*/
|
|
115
127
|
export function calculateBashAppFee(total: number): number {
|
|
116
128
|
return parseFloat((total * BASH_EVENT_FEES.Basic.percent).toFixed(2));
|
|
@@ -118,12 +130,12 @@ export function calculateBashAppFee(total: number): number {
|
|
|
118
130
|
|
|
119
131
|
/**
|
|
120
132
|
* Calculate Stripe's processing fee for donations — transparent pass-through only.
|
|
121
|
-
*
|
|
133
|
+
* Same formula as tickets: {@link STRIPE_PROCESSING_FEE}.
|
|
122
134
|
* @param amountCents - Donation amount in cents
|
|
123
|
-
* @returns Stripe processing fee in cents
|
|
135
|
+
* @returns Stripe processing fee in cents (integer)
|
|
124
136
|
*/
|
|
125
137
|
export function calculateStripeDonationFee(amountCents: number): number {
|
|
126
|
-
return
|
|
138
|
+
return calculateStripeProcessingFeeCents(amountCents);
|
|
127
139
|
}
|
|
128
140
|
|
|
129
141
|
/**
|