@wtree/payload-ecommerce-coupon 3.77.9 → 3.78.2

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
@@ -1,3 +1,4 @@
1
+ import { APIError } from "payload";
1
2
  //#region \0rolldown/runtime.js
2
3
  var __create = Object.create;
3
4
  var __defProp = Object.defineProperty;
@@ -451,37 +452,37 @@ const createReferralProgramsCollection = (pluginConfig) => {
451
452
  delete: access.isAdmin || (() => false)
452
453
  },
453
454
  hooks: { beforeChange: [({ data }) => {
454
- if (!data.commissionRules || !Array.isArray(data.commissionRules) || data.commissionRules.length === 0) throw new Error("At least one commission rule is required");
455
+ if (!data.commissionRules || !Array.isArray(data.commissionRules) || data.commissionRules.length === 0) throw new APIError("At least one commission rule is required", 400);
455
456
  const maxAmount = toNumber(data.maxAmount);
456
- if (maxAmount != null && maxAmount < 0) throw new Error("Max Amount must be a non-negative number");
457
+ if (maxAmount != null && maxAmount < 0) throw new APIError("Max Amount must be a non-negative number", 400);
457
458
  const minOrderAmount = toNumber(data.minOrderAmount);
458
- if (minOrderAmount != null && minOrderAmount < 0) throw new Error("Minimum Order Amount must be a non-negative number");
459
+ if (minOrderAmount != null && minOrderAmount < 0) throw new APIError("Minimum Order Amount must be a non-negative number", 400);
459
460
  data.maxAmount = maxAmount ?? null;
460
461
  data.minOrderAmount = minOrderAmount ?? null;
461
462
  data.commissionRules = data.commissionRules.map((rule, index) => {
462
463
  const r = rule;
463
- if (!r.totalCommission) throw new Error(`Commission rule ${index + 1}: Total Commission is required`);
464
- if (!r.totalCommission.type || !allowedTotalCommissionTypes.includes(r.totalCommission.type)) throw new Error(`Commission rule ${index + 1}: Total Commission type must be one of ${allowedTotalCommissionTypes.join(", ")}`);
464
+ if (!r.totalCommission) throw new APIError(`Commission rule ${index + 1}: Total Commission is required`, 400);
465
+ if (!r.totalCommission.type || !allowedTotalCommissionTypes.includes(r.totalCommission.type)) throw new APIError(`Commission rule ${index + 1}: Total Commission type must be one of ${allowedTotalCommissionTypes.join(", ")}`, 400);
465
466
  const type = r.totalCommission.type;
466
- const totalValue = toNumber(r.totalCommission.value);
467
- if (type === "percentage") {
468
- if (totalValue == null || totalValue < 0) throw new Error(`Commission rule ${index + 1}: Total Commission value must be a non-negative number`);
469
- if (totalValue > 100) throw new Error(`Commission rule ${index + 1}: Percentage Total Commission cannot exceed 100`);
470
- }
471
467
  const appliesTo = r.appliesTo ?? "all";
472
- if (appliesTo === "products" && (!r.products || r.products.length === 0)) throw new Error(`Commission rule ${index + 1}: At least one product is required`);
473
- if ((appliesTo === "segments" || appliesTo === "categories") && (!r.categories || r.categories.length === 0) && (!r.tags || r.tags.length === 0)) throw new Error(`Commission rule ${index + 1}: At least one category or tag is required`);
468
+ if (appliesTo === "products" && (!r.products || r.products.length === 0)) throw new APIError(`Commission rule ${index + 1}: At least one product is required`, 400);
469
+ if ((appliesTo === "segments" || appliesTo === "categories") && (!r.categories || r.categories.length === 0) && (!r.tags || r.tags.length === 0)) throw new APIError(`Commission rule ${index + 1}: At least one category or tag is required`, 400);
474
470
  let partnerSplit;
475
471
  let customerSplit;
476
472
  let partnerPercent = null;
477
473
  let customerPercent = null;
478
474
  let partnerAmount = null;
479
475
  let customerAmount = null;
476
+ let splitWarning = null;
480
477
  if (type === "percentage") {
481
478
  const partnerPctInput = toNumber(r.partnerPercent) ?? toNumber(r.partnerSplit);
482
- if (partnerPctInput == null || partnerPctInput < 0 || partnerPctInput > 100) throw new Error(`Commission rule ${index + 1}: Partner Split must be between 0 and 100`);
483
- const customerPctComputed = 100 - partnerPctInput;
484
- if (customerPctComputed < 0 || customerPctComputed > 100) throw new Error(`Commission rule ${index + 1}: Customer percentage must be between 0 and 100`);
479
+ const customerPctInput = toNumber(r.customerPercent) ?? toNumber(r.customerSplit);
480
+ if (partnerPctInput == null || partnerPctInput < 0 || partnerPctInput > 100) throw new APIError(`Commission rule ${index + 1}: Partner Split must be between 0 and 100`, 400);
481
+ if (customerPctInput != null && (customerPctInput < 0 || customerPctInput > 100)) throw new APIError(`Commission rule ${index + 1}: Customer percentage must be between 0 and 100`, 400);
482
+ const customerPctComputed = customerPctInput != null ? customerPctInput : 100 - partnerPctInput;
483
+ const percentTotal = partnerPctInput + customerPctComputed;
484
+ if (percentTotal > 100) throw new APIError(`Commission rule ${index + 1}: Partner percentage + Customer percentage cannot exceed 100`, 400);
485
+ if (percentTotal > 50) splitWarning = `High total split configured: ${percentTotal}% (partner + customer).`;
485
486
  partnerPercent = partnerPctInput;
486
487
  customerPercent = customerPctComputed;
487
488
  partnerSplit = partnerPctInput;
@@ -494,36 +495,33 @@ const createReferralProgramsCollection = (pluginConfig) => {
494
495
  const hasNewFixedInputs = partnerAmountInput != null || customerAmountInput != null;
495
496
  const hasLegacyFixedInputs = legacyPartnerSplitInput != null || legacyCustomerSplitInput != null;
496
497
  if (hasNewFixedInputs) {
497
- if (partnerAmountInput == null || partnerAmountInput < 0) throw new Error(`Commission rule ${index + 1}: Partner fixed amount must be a non-negative number`);
498
- if (customerAmountInput == null || customerAmountInput < 0) throw new Error(`Commission rule ${index + 1}: Customer fixed amount must be a non-negative number`);
498
+ if (partnerAmountInput == null || partnerAmountInput < 0) throw new APIError(`Commission rule ${index + 1}: Partner fixed amount must be a non-negative number`, 400);
499
+ if (customerAmountInput == null || customerAmountInput < 0) throw new APIError(`Commission rule ${index + 1}: Customer fixed amount must be a non-negative number`, 400);
499
500
  partnerAmount = partnerAmountInput;
500
501
  customerAmount = customerAmountInput;
501
502
  partnerSplit = toCents(partnerAmountInput);
502
503
  customerSplit = toCents(customerAmountInput);
503
504
  } else if (hasLegacyFixedInputs) {
504
- if (legacyPartnerSplitInput == null || legacyPartnerSplitInput < 0) throw new Error(`Commission rule ${index + 1}: For fixed commissions, both partner and customer values must be non-negative numbers`);
505
- const legacyHasTotalValue = toNumber(r.totalCommission?.value) != null;
506
- const resolvedLegacyCustomerSplit = legacyCustomerSplitInput ?? (legacyHasTotalValue ? 100 - legacyPartnerSplitInput : null);
507
- if (resolvedLegacyCustomerSplit == null || resolvedLegacyCustomerSplit < 0) throw new Error(`Commission rule ${index + 1}: For fixed commissions, both partner and customer values must be non-negative numbers`);
505
+ 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);
506
+ const resolvedLegacyCustomerSplit = legacyCustomerSplitInput ?? 100 - legacyPartnerSplitInput;
507
+ if (resolvedLegacyCustomerSplit == null || resolvedLegacyCustomerSplit < 0) throw new APIError(`Commission rule ${index + 1}: For fixed commissions, both partner and customer values must be non-negative numbers`, 400);
508
508
  partnerSplit = legacyPartnerSplitInput;
509
509
  customerSplit = resolvedLegacyCustomerSplit;
510
510
  partnerAmount = null;
511
511
  customerAmount = null;
512
- } else throw new Error(`Commission rule ${index + 1}: For fixed commissions, both partner and customer values must be provided`);
512
+ } else throw new APIError(`Commission rule ${index + 1}: For fixed commissions, both partner and customer values must be provided`, 400);
513
513
  }
514
514
  return {
515
515
  ...rule,
516
516
  appliesTo: appliesTo === "categories" ? "segments" : appliesTo,
517
- totalCommission: {
518
- type,
519
- value: type === "percentage" ? totalValue : null
520
- },
517
+ totalCommission: { type },
521
518
  partnerPercent,
522
519
  customerPercent,
523
520
  partnerAmount,
524
521
  customerAmount,
525
522
  partnerSplit,
526
- customerSplit
523
+ customerSplit,
524
+ splitWarning
527
525
  };
528
526
  });
529
527
  return data;
@@ -623,15 +621,6 @@ const createReferralProgramsCollection = (pluginConfig) => {
623
621
  value
624
622
  })),
625
623
  defaultValue: allowedTotalCommissionTypes.includes("fixed") ? "fixed" : "percentage"
626
- }, {
627
- name: "value",
628
- type: "number",
629
- min: 0,
630
- max: 100,
631
- admin: {
632
- condition: (_, siblingData) => siblingData?.type === "percentage",
633
- description: "Total commission percentage for this rule (0-100). Partner/Customer percentages split this 100-based bucket."
634
- }
635
624
  }]
636
625
  },
637
626
  {
@@ -641,7 +630,7 @@ const createReferralProgramsCollection = (pluginConfig) => {
641
630
  max: 100,
642
631
  admin: {
643
632
  condition: (_, siblingData) => siblingData?.totalCommission?.type === "percentage",
644
- description: "Partner share in percent (0-100). Customer share is auto-calculated as 100 - Partner."
633
+ description: "Partner share in percent (0-100)"
645
634
  }
646
635
  },
647
636
  {
@@ -650,17 +639,9 @@ const createReferralProgramsCollection = (pluginConfig) => {
650
639
  min: 0,
651
640
  max: 100,
652
641
  admin: {
653
- readOnly: true,
654
642
  condition: (_, siblingData) => siblingData?.totalCommission?.type === "percentage",
655
- description: "Auto-calculated customer share percentage."
656
- },
657
- hooks: { beforeValidate: [({ siblingData }) => {
658
- if (!siblingData || siblingData.totalCommission?.type !== "percentage") return null;
659
- const partner = toNumber(siblingData.partnerPercent) ?? toNumber(siblingData.partnerSplit) ?? 0;
660
- if (partner < 0) return 100;
661
- if (partner > 100) return 0;
662
- return 100 - partner;
663
- }] }
643
+ description: "Customer share percentage. (0-100). Partner + Customer cannot exceed 100."
644
+ }
664
645
  },
665
646
  {
666
647
  name: "partnerAmount",
@@ -781,13 +762,25 @@ function calculateItemRewardByRule({ rule, itemTotal, quantity, maxAmount, allow
781
762
  const allowedTypes = allowedCommissionTypesSet(allowedTotalCommissionTypes);
782
763
  if (rule.totalCommission) {
783
764
  if (!allowedTypes.has(rule.totalCommission.type)) return null;
765
+ const resolvedMaxAmount = typeof maxAmount === "number" && Number.isFinite(maxAmount) ? maxAmount : typeof rule.totalCommission.maxAmount === "number" && Number.isFinite(rule.totalCommission.maxAmount) ? rule.totalCommission.maxAmount : null;
784
766
  if (rule.totalCommission.type === "fixed" && rule.totalCommission.value == null) {
785
- const partnerAmt = typeof rule.partnerSplit === "number" ? rule.partnerSplit : null;
786
- const customerAmt = typeof rule.customerSplit === "number" ? rule.customerSplit : null;
787
- if (partnerAmt == null || customerAmt == null) return null;
767
+ const partnerAmtPerUnit = typeof rule.partnerSplit === "number" ? rule.partnerSplit : null;
768
+ const customerAmtPerUnit = typeof rule.customerSplit === "number" ? rule.customerSplit : null;
769
+ if (partnerAmtPerUnit == null || customerAmtPerUnit == null) return null;
770
+ let partner = partnerAmtPerUnit * quantity;
771
+ let customer = customerAmtPerUnit * quantity;
772
+ if (resolvedMaxAmount != null) {
773
+ const maxPotForLine = resolvedMaxAmount * quantity;
774
+ const totalPot = partner + customer;
775
+ if (totalPot > maxPotForLine && totalPot > 0) {
776
+ const ratio = maxPotForLine / totalPot;
777
+ partner = Math.floor(partner * ratio);
778
+ customer = Math.floor(customer * ratio);
779
+ }
780
+ }
788
781
  return {
789
- partner: partnerAmt * quantity,
790
- customer: customerAmt * quantity
782
+ partner,
783
+ customer
791
784
  };
792
785
  }
793
786
  const splits = getRuleSplits(rule);
@@ -795,7 +788,6 @@ function calculateItemRewardByRule({ rule, itemTotal, quantity, maxAmount, allow
795
788
  let totalPot = 0;
796
789
  if (rule.totalCommission.type === "percentage") totalPot = itemTotal * rule.totalCommission.value / 100;
797
790
  else totalPot = rule.totalCommission.value * quantity;
798
- const resolvedMaxAmount = typeof maxAmount === "number" && Number.isFinite(maxAmount) ? maxAmount : typeof rule.totalCommission.maxAmount === "number" && Number.isFinite(rule.totalCommission.maxAmount) ? rule.totalCommission.maxAmount : null;
799
791
  if (resolvedMaxAmount != null) {
800
792
  const maxPotForLine = resolvedMaxAmount * quantity;
801
793
  if (totalPot > maxPotForLine) totalPot = maxPotForLine;