@wtree/payload-ecommerce-coupon 3.78.5 → 3.78.7

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/index.mjs CHANGED
@@ -422,12 +422,22 @@ const createReferralCodesCollection = (pluginConfig) => {
422
422
  };
423
423
  };
424
424
  //#endregion
425
+ //#region src/utilities/roundTo2.ts
426
+ /**
427
+ * Rounds a number to 2 decimal places (standard for monetary values).
428
+ */
429
+ function roundTo2(value) {
430
+ return Math.round(value * 100) / 100;
431
+ }
432
+ //#endregion
425
433
  //#region src/collections/createReferralProgramsCollection.ts
426
434
  function toNumber(value) {
427
435
  return typeof value === "number" && Number.isFinite(value) ? value : null;
428
436
  }
429
- function toCents(value) {
430
- return Math.round(value * 100);
437
+ function normalizeLegacyX100Money(value) {
438
+ if (value == null) return null;
439
+ if (Number.isInteger(value) && Math.abs(value) >= 1e3) return roundTo2(value / 100);
440
+ return value;
431
441
  }
432
442
  const createReferralProgramsCollection = (pluginConfig) => {
433
443
  const { collections, access, adminGroups, referralConfig, integration } = pluginConfig;
@@ -453,14 +463,14 @@ const createReferralProgramsCollection = (pluginConfig) => {
453
463
  },
454
464
  hooks: { beforeChange: [({ data }) => {
455
465
  if (!data.commissionRules || !Array.isArray(data.commissionRules) || data.commissionRules.length === 0) throw new APIError("At least one commission rule is required", 400);
456
- const maxPartnerCommissionPerOrder = toNumber(data.maxPartnerCommissionPerOrder);
466
+ const maxPartnerCommissionPerOrder = normalizeLegacyX100Money(toNumber(data.maxPartnerCommissionPerOrder));
457
467
  if (maxPartnerCommissionPerOrder != null && maxPartnerCommissionPerOrder < 0) throw new APIError("Maximum commission per order for partner must be a non-negative number", 400);
458
- const maxCustomerDiscountPerOrder = toNumber(data.maxCustomerDiscountPerOrder);
468
+ const maxCustomerDiscountPerOrder = normalizeLegacyX100Money(toNumber(data.maxCustomerDiscountPerOrder));
459
469
  if (maxCustomerDiscountPerOrder != null && maxCustomerDiscountPerOrder < 0) throw new APIError("Maximum discount for customer per order must be a non-negative number", 400);
460
- const minOrderAmount = toNumber(data.minOrderAmount);
470
+ const minOrderAmount = normalizeLegacyX100Money(toNumber(data.minOrderAmount));
461
471
  if (minOrderAmount != null && minOrderAmount < 0) throw new APIError("Minimum Order Amount must be a non-negative number", 400);
462
- data.maxPartnerCommissionPerOrder = maxPartnerCommissionPerOrder != null ? toCents(maxPartnerCommissionPerOrder) : null;
463
- data.maxCustomerDiscountPerOrder = maxCustomerDiscountPerOrder != null ? toCents(maxCustomerDiscountPerOrder) : null;
472
+ data.maxPartnerCommissionPerOrder = maxPartnerCommissionPerOrder != null ? maxPartnerCommissionPerOrder : null;
473
+ data.maxCustomerDiscountPerOrder = maxCustomerDiscountPerOrder != null ? maxCustomerDiscountPerOrder : null;
464
474
  data.minOrderAmount = minOrderAmount ?? null;
465
475
  data.commissionRules = data.commissionRules.map((rule, index) => {
466
476
  const r = rule;
@@ -491,8 +501,8 @@ const createReferralProgramsCollection = (pluginConfig) => {
491
501
  partnerSplit = partnerPctInput;
492
502
  customerSplit = customerPctComputed;
493
503
  } else {
494
- const partnerAmountInput = toNumber(r.partnerAmount);
495
- const customerAmountInput = toNumber(r.customerAmount);
504
+ const partnerAmountInput = normalizeLegacyX100Money(toNumber(r.partnerAmount));
505
+ const customerAmountInput = normalizeLegacyX100Money(toNumber(r.customerAmount));
496
506
  const legacyPartnerSplitInput = toNumber(r.partnerSplit);
497
507
  const legacyCustomerSplitInput = toNumber(r.customerSplit);
498
508
  const hasNewFixedInputs = partnerAmountInput != null || customerAmountInput != null;
@@ -502,8 +512,8 @@ const createReferralProgramsCollection = (pluginConfig) => {
502
512
  if (customerAmountInput == null || customerAmountInput < 0) throw new APIError(`Commission rule ${index + 1}: Customer fixed amount must be a non-negative number`, 400);
503
513
  partnerAmount = partnerAmountInput;
504
514
  customerAmount = customerAmountInput;
505
- partnerSplit = toCents(partnerAmountInput);
506
- customerSplit = toCents(customerAmountInput);
515
+ partnerSplit = partnerAmountInput;
516
+ customerSplit = customerAmountInput;
507
517
  } else if (hasLegacyFixedInputs) {
508
518
  if (legacyPartnerSplitInput == null || legacyPartnerSplitInput < 0) throw new APIError(`Commission rule ${index + 1}: For fixed commissions, both partner and customer values must be non-negative numbers`, 400);
509
519
  const resolvedLegacyCustomerSplit = legacyCustomerSplitInput ?? 100 - legacyPartnerSplitInput;
@@ -517,7 +527,11 @@ const createReferralProgramsCollection = (pluginConfig) => {
517
527
  return {
518
528
  ...rule,
519
529
  appliesTo: appliesTo === "categories" ? "segments" : appliesTo,
520
- totalCommission: { type },
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
+ },
521
535
  partnerPercent,
522
536
  customerPercent,
523
537
  partnerAmount,
@@ -546,19 +560,19 @@ const createReferralProgramsCollection = (pluginConfig) => {
546
560
  name: "maxPartnerCommissionPerOrder",
547
561
  type: "number",
548
562
  min: 0,
549
- admin: { description: "Maximum commission per order for partner. Leave empty for no cap. Enter value in currency units (will be converted to cents)." }
563
+ admin: { description: "Maximum commission per order for partner (normal currency value, ). Leave empty for no cap." }
550
564
  },
551
565
  {
552
566
  name: "maxCustomerDiscountPerOrder",
553
567
  type: "number",
554
568
  min: 0,
555
- admin: { description: "Maximum customer discount per order. Leave empty for no cap. Enter value in currency units (will be converted to cents)." }
569
+ admin: { description: "Maximum customer discount per order (normal currency value, ). Leave empty for no cap." }
556
570
  },
557
571
  {
558
572
  name: "minOrderAmount",
559
573
  type: "number",
560
574
  min: 0,
561
- admin: { description: "Minimum cart subtotal required for this program. Leave empty for no minimum." }
575
+ admin: { description: "Minimum cart subtotal required for this program (normal currency value, ). Leave empty for no minimum." }
562
576
  },
563
577
  {
564
578
  name: "commissionRules",
@@ -658,7 +672,7 @@ const createReferralProgramsCollection = (pluginConfig) => {
658
672
  min: 0,
659
673
  admin: {
660
674
  condition: (_, siblingData) => siblingData?.totalCommission?.type === "fixed",
661
- description: "Fixed partner commission amount per item."
675
+ description: "Fixed partner commission amount per item (normal currency value)."
662
676
  }
663
677
  },
664
678
  {
@@ -667,7 +681,7 @@ const createReferralProgramsCollection = (pluginConfig) => {
667
681
  min: 0,
668
682
  admin: {
669
683
  condition: (_, siblingData) => siblingData?.totalCommission?.type === "fixed",
670
- description: "Fixed customer discount amount per item."
684
+ description: "Fixed customer discount amount per item (normal currency value)."
671
685
  }
672
686
  },
673
687
  {
@@ -676,7 +690,7 @@ const createReferralProgramsCollection = (pluginConfig) => {
676
690
  min: 0,
677
691
  admin: {
678
692
  hidden: true,
679
- description: "Canonical storage field. Percentage mode: percent. Fixed mode: amount in cents."
693
+ description: "Canonical storage field. Percentage mode: percent. Fixed mode: amount."
680
694
  }
681
695
  },
682
696
  {
@@ -685,7 +699,7 @@ const createReferralProgramsCollection = (pluginConfig) => {
685
699
  min: 0,
686
700
  admin: {
687
701
  hidden: true,
688
- description: "Canonical storage field. Percentage mode: percent. Fixed mode: amount in cents."
702
+ description: "Canonical storage field. Percentage mode: percent. Fixed mode: amount."
689
703
  }
690
704
  }
691
705
  ]
@@ -694,14 +708,6 @@ const createReferralProgramsCollection = (pluginConfig) => {
694
708
  timestamps: true
695
709
  };
696
710
  };
697
- //#endregion
698
- //#region src/utilities/roundTo2.ts
699
- /**
700
- * Rounds a number to 2 decimal places (standard for monetary values).
701
- */
702
- function roundTo2(value) {
703
- return Math.round(value * 100) / 100;
704
- }
705
711
  function normalizeCurrencyCode(currencyCode) {
706
712
  if (!currencyCode) return "AED";
707
713
  return currencyCode.toUpperCase();
@@ -792,15 +798,52 @@ function calculateItemRewardByRule({ rule, itemTotal, quantity, allowedTotalComm
792
798
  customer
793
799
  };
794
800
  }
795
- const splits = getRuleSplits(rule);
796
- if (!splits) return null;
797
801
  let totalPot = 0;
798
- if (rule.totalCommission.type === "percentage") totalPot = itemTotal * rule.totalCommission.value / 100;
799
- else totalPot = rule.totalCommission.value * quantity;
802
+ if (rule.totalCommission.type === "percentage") {
803
+ const commissionValue = typeof rule.totalCommission.value === "number" && Number.isFinite(rule.totalCommission.value) ? rule.totalCommission.value : null;
804
+ if (commissionValue == null) {
805
+ const partnerPercentInput = typeof rule.partnerPercent === "number" ? rule.partnerPercent : typeof rule.partnerSplit === "number" ? rule.partnerSplit : null;
806
+ if (partnerPercentInput == null || partnerPercentInput < 0 || partnerPercentInput > 100) return null;
807
+ const customerPercentInput = typeof rule.customerPercent === "number" ? rule.customerPercent : typeof rule.customerSplit === "number" ? rule.customerSplit : 100 - partnerPercentInput;
808
+ if (customerPercentInput == null || customerPercentInput < 0 || customerPercentInput > 100) return null;
809
+ const partner = itemTotal * partnerPercentInput / 100;
810
+ const customer = itemTotal * customerPercentInput / 100;
811
+ if (resolvedMaxAmount != null) {
812
+ const maxPotForLine = resolvedMaxAmount * quantity;
813
+ const totalForLine = partner + customer;
814
+ if (totalForLine > maxPotForLine && totalForLine > 0) {
815
+ const ratio = maxPotForLine / totalForLine;
816
+ return {
817
+ partner: Math.floor(partner * ratio),
818
+ customer: Math.floor(customer * ratio)
819
+ };
820
+ }
821
+ }
822
+ return {
823
+ partner: Math.floor(partner),
824
+ customer: Math.floor(customer)
825
+ };
826
+ }
827
+ totalPot = itemTotal * commissionValue / 100;
828
+ } else {
829
+ const splits = getRuleSplits(rule);
830
+ if (!splits) return null;
831
+ totalPot = rule.totalCommission.value * quantity;
832
+ if (resolvedMaxAmount != null) {
833
+ const maxPotForLine = resolvedMaxAmount * quantity;
834
+ if (totalPot > maxPotForLine) totalPot = maxPotForLine;
835
+ }
836
+ return {
837
+ partner: Math.floor(totalPot * splits.partnerSplit / 100),
838
+ customer: Math.floor(totalPot * splits.customerSplit / 100)
839
+ };
840
+ }
800
841
  if (resolvedMaxAmount != null) {
801
842
  const maxPotForLine = resolvedMaxAmount * quantity;
802
843
  if (totalPot > maxPotForLine) totalPot = maxPotForLine;
803
844
  }
845
+ const splits = getRuleSplits(rule);
846
+ if (!splits) return null;
804
847
  return {
805
848
  partner: Math.floor(totalPot * splits.partnerSplit / 100),
806
849
  customer: Math.floor(totalPot * splits.customerSplit / 100)
@@ -885,10 +928,10 @@ function selectBestRuleForItem({ rules, item, itemTotal, quantity, cartTotal, mi
885
928
  return best;
886
929
  }
887
930
  function getProgramMinimumOrderAmount({ program, allowedTotalCommissionTypes }) {
931
+ if (typeof program?.minOrderAmount === "number" && Number.isFinite(program.minOrderAmount)) return program.minOrderAmount;
888
932
  const rules = Array.isArray(program?.commissionRules) ? program.commissionRules : [];
889
933
  if (!rules.length) return null;
890
934
  const allowedTypes = allowedCommissionTypesSet(allowedTotalCommissionTypes);
891
- if (typeof program?.minOrderAmount === "number" && Number.isFinite(program.minOrderAmount)) return program.minOrderAmount;
892
935
  const minValues = rules.filter((rule) => {
893
936
  if (rule?.totalCommission?.type) return allowedTypes.has(rule.totalCommission.type);
894
937
  return true;