@wtree/payload-ecommerce-coupon 3.78.6 → 3.78.8

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.
@@ -1,4 +1,15 @@
1
1
  import { type CollectionConfig } from 'payload';
2
2
  import type { SanitizedCouponPluginOptions } from '../types';
3
+ /**
4
+ * Scaling policy:
5
+ * - Admin inputs normal currency values (e.g. 100 means $100).
6
+ * - Internally, maxPartnerCommissionPerOrder, maxCustomerDiscountPerOrder, and
7
+ * minOrderAmount are stored in x100 (integer cents) form to avoid floating-point
8
+ * drift on monetary cap fields.
9
+ * - beforeChange → multiply by 100 before persisting.
10
+ * - afterRead → divide by 100 before returning to admin / calculation code.
11
+ * - partnerAmount / customerAmount per-rule fixed amounts are NOT scaled here;
12
+ * they represent per-item fixed currency amounts and are stored as-is.
13
+ */
3
14
  export declare const createReferralProgramsCollection: (pluginConfig: SanitizedCouponPluginOptions) => CollectionConfig;
4
15
  //# sourceMappingURL=createReferralProgramsCollection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createReferralProgramsCollection.d.ts","sourceRoot":"","sources":["../../src/collections/createReferralProgramsCollection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAEzD,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,UAAU,CAAA;AAsB5D,eAAO,MAAM,gCAAgC,GAC3C,cAAc,4BAA4B,KACzC,gBA0ZF,CAAA"}
1
+ {"version":3,"file":"createReferralProgramsCollection.d.ts","sourceRoot":"","sources":["../../src/collections/createReferralProgramsCollection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAEzD,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,UAAU,CAAA;AAsB5D;;;;;;;;;;GAUG;AAEH,eAAO,MAAM,gCAAgC,GAC3C,cAAc,4BAA4B,KACzC,gBAkcF,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"applyCoupon.d.ts","sourceRoot":"","sources":["../../src/endpoints/applyCoupon.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,SAAS,CAAA;AACrF,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,UAAU,CAAA;AAQ5D,KAAK,IAAI,GAAG;IACV,YAAY,EAAE,4BAA4B,CAAA;CAC3C,CAAA;AAqGD,eAAO,MAAM,kBAAkB,GAC5B,kBAAkB,IAAI,KAAG,cAgHzB,CAAA;AAgRH,eAAO,MAAM,mBAAmB,GAAI,kBAAkB,IAAI,KAAG,QAI3D,CAAA"}
1
+ {"version":3,"file":"applyCoupon.d.ts","sourceRoot":"","sources":["../../src/endpoints/applyCoupon.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,SAAS,CAAA;AACrF,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,UAAU,CAAA;AAQ5D,KAAK,IAAI,GAAG;IACV,YAAY,EAAE,4BAA4B,CAAA;CAC3C,CAAA;AAqGD,eAAO,MAAM,kBAAkB,GAC5B,kBAAkB,IAAI,KAAG,cAgHzB,CAAA;AAqRH,eAAO,MAAM,mBAAmB,GAAI,kBAAkB,IAAI,KAAG,QAI3D,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"validateCoupon.d.ts","sourceRoot":"","sources":["../../src/endpoints/validateCoupon.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,SAAS,CAAA;AAErF,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,UAAU,CAAA;AAO5D,KAAK,IAAI,GAAG;IACV,YAAY,EAAE,4BAA4B,CAAA;CAC3C,CAAA;AA4FD,eAAO,MAAM,qBAAqB,GAC/B,kBAAkB,IAAI,KAAG,cAiEzB,CAAA;AA+OH,eAAO,MAAM,sBAAsB,GAAI,kBAAkB,IAAI,KAAG,QAI9D,CAAA"}
1
+ {"version":3,"file":"validateCoupon.d.ts","sourceRoot":"","sources":["../../src/endpoints/validateCoupon.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,SAAS,CAAA;AAErF,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,UAAU,CAAA;AAO5D,KAAK,IAAI,GAAG;IACV,YAAY,EAAE,4BAA4B,CAAA;CAC3C,CAAA;AA4FD,eAAO,MAAM,qBAAqB,GAC/B,kBAAkB,IAAI,KAAG,cAiEzB,CAAA;AAqPH,eAAO,MAAM,sBAAsB,GAAI,kBAAkB,IAAI,KAAG,QAI9D,CAAA"}
package/dist/index.js CHANGED
@@ -427,6 +427,17 @@ const createReferralCodesCollection = (pluginConfig) => {
427
427
  function toNumber(value) {
428
428
  return typeof value === "number" && Number.isFinite(value) ? value : null;
429
429
  }
430
+ /**
431
+ * Scaling policy:
432
+ * - Admin inputs normal currency values (e.g. 100 means $100).
433
+ * - Internally, maxPartnerCommissionPerOrder, maxCustomerDiscountPerOrder, and
434
+ * minOrderAmount are stored in x100 (integer cents) form to avoid floating-point
435
+ * drift on monetary cap fields.
436
+ * - beforeChange → multiply by 100 before persisting.
437
+ * - afterRead → divide by 100 before returning to admin / calculation code.
438
+ * - partnerAmount / customerAmount per-rule fixed amounts are NOT scaled here;
439
+ * they represent per-item fixed currency amounts and are stored as-is.
440
+ */
430
441
  const createReferralProgramsCollection = (pluginConfig) => {
431
442
  const { collections, access, adminGroups, referralConfig, integration } = pluginConfig;
432
443
  const allowedTotalCommissionTypes = referralConfig.allowedTotalCommissionTypes;
@@ -449,88 +460,102 @@ const createReferralProgramsCollection = (pluginConfig) => {
449
460
  update: access.isAdmin || (() => false),
450
461
  delete: access.isAdmin || (() => false)
451
462
  },
452
- hooks: { beforeChange: [({ data }) => {
453
- if (!data.commissionRules || !Array.isArray(data.commissionRules) || data.commissionRules.length === 0) throw new payload.APIError("At least one commission rule is required", 400);
454
- const maxPartnerCommissionPerOrder = toNumber(data.maxPartnerCommissionPerOrder);
455
- if (maxPartnerCommissionPerOrder != null && maxPartnerCommissionPerOrder < 0) throw new payload.APIError("Maximum commission per order for partner must be a non-negative number", 400);
456
- const maxCustomerDiscountPerOrder = toNumber(data.maxCustomerDiscountPerOrder);
457
- if (maxCustomerDiscountPerOrder != null && maxCustomerDiscountPerOrder < 0) throw new payload.APIError("Maximum discount for customer per order must be a non-negative number", 400);
458
- const minOrderAmount = toNumber(data.minOrderAmount);
459
- if (minOrderAmount != null && minOrderAmount < 0) throw new payload.APIError("Minimum Order Amount must be a non-negative number", 400);
460
- data.maxPartnerCommissionPerOrder = maxPartnerCommissionPerOrder != null ? maxPartnerCommissionPerOrder : null;
461
- data.maxCustomerDiscountPerOrder = maxCustomerDiscountPerOrder != null ? maxCustomerDiscountPerOrder : null;
462
- data.minOrderAmount = minOrderAmount ?? null;
463
- data.commissionRules = data.commissionRules.map((rule, index) => {
464
- const r = rule;
465
- if (!r.totalCommission) throw new payload.APIError(`Commission rule ${index + 1}: Total Commission is required`, 400);
466
- if (!r.totalCommission.type || !allowedTotalCommissionTypes.includes(r.totalCommission.type)) throw new payload.APIError(`Commission rule ${index + 1}: Total Commission type must be one of ${allowedTotalCommissionTypes.join(", ")}`, 400);
467
- const type = r.totalCommission.type;
468
- const appliesTo = r.appliesTo ?? "all";
469
- if (appliesTo === "products" && (!r.products || r.products.length === 0)) throw new payload.APIError(`Commission rule ${index + 1}: At least one product is required`, 400);
470
- if ((appliesTo === "segments" || appliesTo === "categories") && (!r.categories || r.categories.length === 0) && (!r.tags || r.tags.length === 0)) throw new payload.APIError(`Commission rule ${index + 1}: At least one category or tag is required`, 400);
471
- let partnerSplit;
472
- let customerSplit;
473
- let partnerPercent = null;
474
- let customerPercent = null;
475
- let partnerAmount = null;
476
- let customerAmount = null;
477
- let splitWarning = null;
478
- if (type === "percentage") {
479
- const partnerPctInput = toNumber(r.partnerPercent) ?? toNumber(r.partnerSplit);
480
- const customerPctInput = toNumber(r.customerPercent) ?? toNumber(r.customerSplit);
481
- if (partnerPctInput == null || partnerPctInput < 0 || partnerPctInput > 100) throw new payload.APIError(`Commission rule ${index + 1}: Partner Split must be between 0 and 100`, 400);
482
- if (customerPctInput != null && (customerPctInput < 0 || customerPctInput > 100)) throw new payload.APIError(`Commission rule ${index + 1}: Customer percentage must be between 0 and 100`, 400);
483
- const customerPctComputed = customerPctInput != null ? customerPctInput : 100 - partnerPctInput;
484
- const percentTotal = partnerPctInput + customerPctComputed;
485
- if (percentTotal > 100) throw new payload.APIError(`Commission rule ${index + 1}: Partner percentage + Customer percentage cannot exceed 100`, 400);
486
- if (percentTotal > 50) splitWarning = `High total split configured: ${percentTotal}% (partner + customer).`;
487
- partnerPercent = partnerPctInput;
488
- customerPercent = customerPctComputed;
489
- partnerSplit = partnerPctInput;
490
- customerSplit = customerPctComputed;
491
- } else {
492
- const partnerAmountInput = toNumber(r.partnerAmount);
493
- const customerAmountInput = toNumber(r.customerAmount);
494
- const legacyPartnerSplitInput = toNumber(r.partnerSplit);
495
- const legacyCustomerSplitInput = toNumber(r.customerSplit);
496
- const hasNewFixedInputs = partnerAmountInput != null || customerAmountInput != null;
497
- const hasLegacyFixedInputs = legacyPartnerSplitInput != null || legacyCustomerSplitInput != null;
498
- if (hasNewFixedInputs) {
499
- if (partnerAmountInput == null || partnerAmountInput < 0) throw new payload.APIError(`Commission rule ${index + 1}: Partner fixed amount must be a non-negative number`, 400);
500
- if (customerAmountInput == null || customerAmountInput < 0) throw new payload.APIError(`Commission rule ${index + 1}: Customer fixed amount must be a non-negative number`, 400);
501
- partnerAmount = partnerAmountInput;
502
- customerAmount = customerAmountInput;
503
- partnerSplit = partnerAmountInput;
504
- customerSplit = customerAmountInput;
505
- } else if (hasLegacyFixedInputs) {
506
- if (legacyPartnerSplitInput == null || legacyPartnerSplitInput < 0) throw new payload.APIError(`Commission rule ${index + 1}: For fixed commissions, both partner and customer values must be non-negative numbers`, 400);
507
- const resolvedLegacyCustomerSplit = legacyCustomerSplitInput ?? 100 - legacyPartnerSplitInput;
508
- if (resolvedLegacyCustomerSplit == null || resolvedLegacyCustomerSplit < 0) throw new payload.APIError(`Commission rule ${index + 1}: For fixed commissions, both partner and customer values must be non-negative numbers`, 400);
509
- partnerSplit = legacyPartnerSplitInput;
510
- customerSplit = resolvedLegacyCustomerSplit;
511
- partnerAmount = null;
512
- customerAmount = null;
513
- } else throw new payload.APIError(`Commission rule ${index + 1}: For fixed commissions, both partner and customer values must be provided`, 400);
514
- }
515
- return {
516
- ...rule,
517
- appliesTo: appliesTo === "categories" ? "segments" : appliesTo,
518
- totalCommission: {
519
- type,
520
- ...typeof r.totalCommission.value === "number" ? { value: r.totalCommission.value } : {},
521
- ...typeof r.totalCommission.maxAmount === "number" ? { maxAmount: r.totalCommission.maxAmount } : {}
522
- },
523
- partnerPercent,
524
- customerPercent,
525
- partnerAmount,
526
- customerAmount,
527
- partnerSplit,
528
- customerSplit,
529
- splitWarning
463
+ hooks: {
464
+ beforeChange: [({ data }) => {
465
+ if (!data.commissionRules || !Array.isArray(data.commissionRules) || data.commissionRules.length === 0) throw new payload.APIError("At least one commission rule is required", 400);
466
+ const rawMaxPartner = toNumber(data.maxPartnerCommissionPerOrder);
467
+ if (rawMaxPartner != null && rawMaxPartner < 0) throw new payload.APIError("Maximum commission per order for partner must be a non-negative number", 400);
468
+ const rawMaxCustomer = toNumber(data.maxCustomerDiscountPerOrder);
469
+ if (rawMaxCustomer != null && rawMaxCustomer < 0) throw new payload.APIError("Maximum discount for customer per order must be a non-negative number", 400);
470
+ const rawMinOrder = toNumber(data.minOrderAmount);
471
+ if (rawMinOrder != null && rawMinOrder < 0) throw new payload.APIError("Minimum Order Amount must be a non-negative number", 400);
472
+ data.maxPartnerCommissionPerOrder = rawMaxPartner != null ? Math.round(rawMaxPartner * 100) : null;
473
+ data.maxCustomerDiscountPerOrder = rawMaxCustomer != null ? Math.round(rawMaxCustomer * 100) : null;
474
+ data.minOrderAmount = rawMinOrder != null ? Math.round(rawMinOrder * 100) : null;
475
+ data.commissionRules = data.commissionRules.map((rule, index) => {
476
+ const r = rule;
477
+ if (!r.totalCommission) throw new payload.APIError(`Commission rule ${index + 1}: Total Commission is required`, 400);
478
+ if (!r.totalCommission.type || !allowedTotalCommissionTypes.includes(r.totalCommission.type)) throw new payload.APIError(`Commission rule ${index + 1}: Total Commission type must be one of ${allowedTotalCommissionTypes.join(", ")}`, 400);
479
+ const type = r.totalCommission.type;
480
+ const appliesTo = r.appliesTo ?? "all";
481
+ if (appliesTo === "products" && (!r.products || r.products.length === 0)) throw new payload.APIError(`Commission rule ${index + 1}: At least one product is required`, 400);
482
+ if ((appliesTo === "segments" || appliesTo === "categories") && (!r.categories || r.categories.length === 0) && (!r.tags || r.tags.length === 0)) throw new payload.APIError(`Commission rule ${index + 1}: At least one category or tag is required`, 400);
483
+ let partnerSplit;
484
+ let customerSplit;
485
+ let partnerPercent = null;
486
+ let customerPercent = null;
487
+ let partnerAmount = null;
488
+ let customerAmount = null;
489
+ let splitWarning = null;
490
+ if (type === "percentage") {
491
+ const partnerPctInput = toNumber(r.partnerPercent) ?? toNumber(r.partnerSplit);
492
+ const customerPctInput = toNumber(r.customerPercent) ?? toNumber(r.customerSplit);
493
+ if (partnerPctInput == null || partnerPctInput < 0 || partnerPctInput > 100) throw new payload.APIError(`Commission rule ${index + 1}: Partner Split must be between 0 and 100`, 400);
494
+ if (customerPctInput != null && (customerPctInput < 0 || customerPctInput > 100)) throw new payload.APIError(`Commission rule ${index + 1}: Customer percentage must be between 0 and 100`, 400);
495
+ const customerPctComputed = customerPctInput != null ? customerPctInput : 100 - partnerPctInput;
496
+ const percentTotal = partnerPctInput + customerPctComputed;
497
+ if (percentTotal > 100) throw new payload.APIError(`Commission rule ${index + 1}: Partner percentage + Customer percentage cannot exceed 100`, 400);
498
+ if (percentTotal > 50) splitWarning = `High total split configured: ${percentTotal}% (partner + customer).`;
499
+ partnerPercent = partnerPctInput;
500
+ customerPercent = customerPctComputed;
501
+ partnerSplit = partnerPctInput;
502
+ customerSplit = customerPctComputed;
503
+ } else {
504
+ const partnerAmountInput = toNumber(r.partnerAmount);
505
+ const customerAmountInput = toNumber(r.customerAmount);
506
+ const legacyPartnerSplitInput = toNumber(r.partnerSplit);
507
+ const legacyCustomerSplitInput = toNumber(r.customerSplit);
508
+ const hasNewFixedInputs = partnerAmountInput != null || customerAmountInput != null;
509
+ const hasLegacyFixedInputs = legacyPartnerSplitInput != null || legacyCustomerSplitInput != null;
510
+ if (hasNewFixedInputs) {
511
+ if (partnerAmountInput == null || partnerAmountInput < 0) throw new payload.APIError(`Commission rule ${index + 1}: Partner fixed amount must be a non-negative number`, 400);
512
+ if (customerAmountInput == null || customerAmountInput < 0) throw new payload.APIError(`Commission rule ${index + 1}: Customer fixed amount must be a non-negative number`, 400);
513
+ partnerAmount = partnerAmountInput;
514
+ customerAmount = customerAmountInput;
515
+ partnerSplit = partnerAmountInput;
516
+ customerSplit = customerAmountInput;
517
+ } else if (hasLegacyFixedInputs) {
518
+ if (legacyPartnerSplitInput == null || legacyPartnerSplitInput < 0) throw new payload.APIError(`Commission rule ${index + 1}: For fixed commissions, both partner and customer values must be non-negative numbers`, 400);
519
+ const resolvedLegacyCustomerSplit = legacyCustomerSplitInput ?? 100 - legacyPartnerSplitInput;
520
+ if (resolvedLegacyCustomerSplit == null || resolvedLegacyCustomerSplit < 0) throw new payload.APIError(`Commission rule ${index + 1}: For fixed commissions, both partner and customer values must be non-negative numbers`, 400);
521
+ partnerSplit = legacyPartnerSplitInput;
522
+ customerSplit = resolvedLegacyCustomerSplit;
523
+ partnerAmount = null;
524
+ customerAmount = null;
525
+ } else throw new payload.APIError(`Commission rule ${index + 1}: For fixed commissions, both partner and customer values must be provided`, 400);
526
+ }
527
+ return {
528
+ ...rule,
529
+ appliesTo: appliesTo === "categories" ? "segments" : appliesTo,
530
+ totalCommission: {
531
+ type,
532
+ ...typeof r.totalCommission.value === "number" ? { value: r.totalCommission.value } : {},
533
+ ...typeof r.totalCommission.maxAmount === "number" ? { maxAmount: r.totalCommission.maxAmount } : {}
534
+ },
535
+ partnerPercent,
536
+ customerPercent,
537
+ partnerAmount,
538
+ customerAmount,
539
+ partnerSplit,
540
+ customerSplit,
541
+ splitWarning
542
+ };
543
+ });
544
+ return data;
545
+ }],
546
+ afterRead: [({ doc }) => {
547
+ if (!doc) return doc;
548
+ const unscale = (value) => {
549
+ const n = toNumber(value);
550
+ if (n == null) return null;
551
+ return Math.round(n / 100 * 100) / 100;
530
552
  };
531
- });
532
- return data;
533
- }] },
553
+ doc.maxPartnerCommissionPerOrder = unscale(doc.maxPartnerCommissionPerOrder);
554
+ doc.maxCustomerDiscountPerOrder = unscale(doc.maxCustomerDiscountPerOrder);
555
+ doc.minOrderAmount = unscale(doc.minOrderAmount);
556
+ return doc;
557
+ }]
558
+ },
534
559
  fields: [
535
560
  {
536
561
  name: "name",
@@ -548,19 +573,19 @@ const createReferralProgramsCollection = (pluginConfig) => {
548
573
  name: "maxPartnerCommissionPerOrder",
549
574
  type: "number",
550
575
  min: 0,
551
- admin: { description: "Maximum commission per order for partner. Leave empty for no cap." }
576
+ admin: { description: "Maximum commission per order for partner (enter normal currency value, e.g. 50 for $50). Leave empty for no cap." }
552
577
  },
553
578
  {
554
579
  name: "maxCustomerDiscountPerOrder",
555
580
  type: "number",
556
581
  min: 0,
557
- admin: { description: "Maximum customer discount per order. Leave empty for no cap." }
582
+ admin: { description: "Maximum customer discount per order (enter normal currency value, e.g. 25 for $25). Leave empty for no cap." }
558
583
  },
559
584
  {
560
585
  name: "minOrderAmount",
561
586
  type: "number",
562
587
  min: 0,
563
- admin: { description: "Minimum cart subtotal required for this program. Leave empty for no minimum." }
588
+ admin: { description: "Minimum cart subtotal required for this program (enter normal currency value, e.g. 100 for $100). Leave empty for no minimum." }
564
589
  },
565
590
  {
566
591
  name: "commissionRules",
@@ -641,7 +666,7 @@ const createReferralProgramsCollection = (pluginConfig) => {
641
666
  max: 100,
642
667
  admin: {
643
668
  condition: (_, siblingData) => siblingData?.totalCommission?.type === "percentage",
644
- description: "Partner share in percent (0-100)"
669
+ description: "Partner share in percent (0100)"
645
670
  }
646
671
  },
647
672
  {
@@ -651,7 +676,7 @@ const createReferralProgramsCollection = (pluginConfig) => {
651
676
  max: 100,
652
677
  admin: {
653
678
  condition: (_, siblingData) => siblingData?.totalCommission?.type === "percentage",
654
- description: "Customer share percentage. (0-100). Partner + Customer cannot exceed 100."
679
+ description: "Customer share percentage (0100). Partner + Customer cannot exceed 100."
655
680
  }
656
681
  },
657
682
  {
@@ -660,7 +685,7 @@ const createReferralProgramsCollection = (pluginConfig) => {
660
685
  min: 0,
661
686
  admin: {
662
687
  condition: (_, siblingData) => siblingData?.totalCommission?.type === "fixed",
663
- description: "Fixed partner commission amount per item."
688
+ description: "Fixed partner commission amount per item (normal currency value, e.g. 12.50 for $12.50)."
664
689
  }
665
690
  },
666
691
  {
@@ -669,7 +694,7 @@ const createReferralProgramsCollection = (pluginConfig) => {
669
694
  min: 0,
670
695
  admin: {
671
696
  condition: (_, siblingData) => siblingData?.totalCommission?.type === "fixed",
672
- description: "Fixed customer discount amount per item."
697
+ description: "Fixed customer discount amount per item (normal currency value, e.g. 5 for $5)."
673
698
  }
674
699
  },
675
700
  {
@@ -678,7 +703,7 @@ const createReferralProgramsCollection = (pluginConfig) => {
678
703
  min: 0,
679
704
  admin: {
680
705
  hidden: true,
681
- description: "Canonical storage field. Percentage mode: percent. Fixed mode: amount."
706
+ description: "Canonical storage field. Percentage mode: percent value. Fixed mode: per-item amount."
682
707
  }
683
708
  },
684
709
  {
@@ -687,7 +712,7 @@ const createReferralProgramsCollection = (pluginConfig) => {
687
712
  min: 0,
688
713
  admin: {
689
714
  hidden: true,
690
- description: "Canonical storage field. Percentage mode: percent. Fixed mode: amount."
715
+ description: "Canonical storage field. Percentage mode: percent value. Fixed mode: per-item amount."
691
716
  }
692
717
  }
693
718
  ]
@@ -874,8 +899,7 @@ function selectBestRuleForItem({ rules, item, itemTotal, quantity, cartTotal, mi
874
899
  const eligibleRules = rules.filter((rule) => {
875
900
  if (!(rule?.totalCommission?.type ? allowedTypes.has(rule.totalCommission.type) : true)) return false;
876
901
  const resolvedMinOrderAmount = typeof minOrderAmount === "number" && Number.isFinite(minOrderAmount) ? minOrderAmount : typeof rule?.minOrderAmount === "number" && Number.isFinite(rule.minOrderAmount) ? rule.minOrderAmount : null;
877
- const shouldApplyMinOrder = rule?.totalCommission?.type !== "fixed";
878
- if (resolvedMinOrderAmount != null && shouldApplyMinOrder) return cartTotal >= resolvedMinOrderAmount;
902
+ if (resolvedMinOrderAmount != null) return cartTotal >= resolvedMinOrderAmount;
879
903
  return true;
880
904
  });
881
905
  const productId = relationId$5(item.product);
@@ -925,13 +949,10 @@ function selectBestRuleForItem({ rules, item, itemTotal, quantity, cartTotal, mi
925
949
  return best;
926
950
  }
927
951
  function getProgramMinimumOrderAmount({ program, allowedTotalCommissionTypes }) {
952
+ if (typeof program?.minOrderAmount === "number" && Number.isFinite(program.minOrderAmount)) return program.minOrderAmount;
928
953
  const rules = Array.isArray(program?.commissionRules) ? program.commissionRules : [];
929
954
  if (!rules.length) return null;
930
955
  const allowedTypes = allowedCommissionTypesSet(allowedTotalCommissionTypes);
931
- if (rules.some((rule) => {
932
- if (rule?.totalCommission?.type) return rule.totalCommission.type === "percentage" && allowedTypes.has(rule.totalCommission.type);
933
- return true;
934
- }) && typeof program?.minOrderAmount === "number" && Number.isFinite(program.minOrderAmount)) return program.minOrderAmount;
935
956
  const minValues = rules.filter((rule) => {
936
957
  if (rule?.totalCommission?.type) return allowedTypes.has(rule.totalCommission.type);
937
958
  return true;
@@ -1175,17 +1196,17 @@ async function handleCouponCode({ payload: payload$7, cart, cartID, normalizedCo
1175
1196
  }, { status: 400 });
1176
1197
  const cartSubtotal = Number(resolvers.getCartSubtotal(cart)) || 0;
1177
1198
  const cartTotal = Number(resolvers.getCartTotal(cart)) || cartSubtotal || 0;
1178
- if (coupon.minOrderValue && cartTotal < coupon.minOrderValue) return Response.json({
1199
+ if (coupon.minOrderValue && cartSubtotal < coupon.minOrderValue) return Response.json({
1179
1200
  success: false,
1180
1201
  error: `Minimum order value of ${coupon.minOrderValue} ${pluginConfig.defaultCurrency} required`
1181
1202
  }, { status: 400 });
1182
- if (coupon.maxOrderValue && cartTotal > coupon.maxOrderValue) return Response.json({
1203
+ if (coupon.maxOrderValue && cartSubtotal > coupon.maxOrderValue) return Response.json({
1183
1204
  success: false,
1184
1205
  error: `Maximum order value of ${coupon.maxOrderValue} ${pluginConfig.defaultCurrency} exceeded`
1185
1206
  }, { status: 400 });
1186
1207
  const discountAmount = calculateCouponDiscount({
1187
1208
  coupon,
1188
- cartTotal
1209
+ cartTotal: cartSubtotal
1189
1210
  });
1190
1211
  const nextTotal = roundTo2(Math.max(0, cartTotal - discountAmount));
1191
1212
  const data = {};
@@ -1247,12 +1268,13 @@ async function handleReferralCode({ payload: payload$8, cart, cartID, normalized
1247
1268
  error: "Referral code already applied to this cart"
1248
1269
  }, { status: 400 });
1249
1270
  const cartItems = resolvers.getCartItems(cart);
1250
- const cartTotal = Number(resolvers.getCartTotal(cart)) || Number(resolvers.getCartSubtotal(cart)) || 0;
1271
+ const cartSubtotal = Number(resolvers.getCartSubtotal(cart)) || 0;
1272
+ const cartTotal = Number(resolvers.getCartTotal(cart)) || cartSubtotal || 0;
1251
1273
  const minOrderAmount = getProgramMinimumOrderAmount({
1252
1274
  program,
1253
1275
  allowedTotalCommissionTypes: pluginConfig.referralConfig.allowedTotalCommissionTypes
1254
1276
  });
1255
- if (typeof minOrderAmount === "number" && cartTotal < minOrderAmount) return Response.json({
1277
+ if (typeof minOrderAmount === "number" && cartSubtotal < minOrderAmount) return Response.json({
1256
1278
  success: false,
1257
1279
  error: `Minimum order value of ${minOrderAmount} ${pluginConfig.defaultCurrency} required for this referral program`
1258
1280
  }, { status: 400 });
@@ -1260,7 +1282,7 @@ async function handleReferralCode({ payload: payload$8, cart, cartID, normalized
1260
1282
  cartItems,
1261
1283
  program,
1262
1284
  currencyCode: pluginConfig.defaultCurrency,
1263
- cartTotal,
1285
+ cartTotal: cartSubtotal,
1264
1286
  allowedTotalCommissionTypes: pluginConfig.referralConfig.allowedTotalCommissionTypes
1265
1287
  });
1266
1288
  const roundedPartnerCommission = roundTo2(partnerCommission);
@@ -1689,7 +1711,7 @@ async function validateReferralCode({ payload: payload$4, normalizedCode, cartID
1689
1711
  id: cartID,
1690
1712
  depth: 2
1691
1713
  }) : null;
1692
- const cartTotal = cart ? Number(resolvers.getCartTotal(cart)) || Number(resolvers.getCartSubtotal(cart)) || 0 : 0;
1714
+ const cartTotal = cart ? Number(resolvers.getCartSubtotal(cart)) || Number(resolvers.getCartTotal(cart)) || 0 : 0;
1693
1715
  const minOrderAmount = getProgramMinimumOrderAmount({
1694
1716
  program,
1695
1717
  allowedTotalCommissionTypes: pluginConfig.referralConfig.allowedTotalCommissionTypes