@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.
@@ -1,4 +1,4 @@
1
- import type { CollectionConfig } from "payload";
1
+ import { type CollectionConfig } from "payload";
2
2
  import type { SanitizedCouponPluginOptions } from "../types";
3
3
  export declare const createReferralProgramsCollection: (pluginConfig: SanitizedCouponPluginOptions) => CollectionConfig;
4
4
  //# sourceMappingURL=createReferralProgramsCollection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createReferralProgramsCollection.d.ts","sourceRoot":"","sources":["../../src/collections/createReferralProgramsCollection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,UAAU,CAAC;AA0B7D,eAAO,MAAM,gCAAgC,GAC3C,cAAc,4BAA4B,KACzC,gBAsZF,CAAC"}
1
+ {"version":3,"file":"createReferralProgramsCollection.d.ts","sourceRoot":"","sources":["../../src/collections/createReferralProgramsCollection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAE1D,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,UAAU,CAAC;AA0B7D,eAAO,MAAM,gCAAgC,GAC3C,cAAc,4BAA4B,KACzC,gBAgYF,CAAC"}
package/dist/index.js CHANGED
@@ -22,6 +22,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
22
22
  enumerable: true
23
23
  }) : target, mod));
24
24
  //#endregion
25
+ let payload = require("payload");
25
26
  //#region src/collections/createCouponsCollection.ts
26
27
  const createCouponsCollection = (pluginConfig) => {
27
28
  const { collections, access, defaultCurrency, adminGroups, integration } = pluginConfig;
@@ -452,37 +453,37 @@ const createReferralProgramsCollection = (pluginConfig) => {
452
453
  delete: access.isAdmin || (() => false)
453
454
  },
454
455
  hooks: { beforeChange: [({ data }) => {
455
- if (!data.commissionRules || !Array.isArray(data.commissionRules) || data.commissionRules.length === 0) throw new Error("At least one commission rule is required");
456
+ if (!data.commissionRules || !Array.isArray(data.commissionRules) || data.commissionRules.length === 0) throw new payload.APIError("At least one commission rule is required", 400);
456
457
  const maxAmount = toNumber(data.maxAmount);
457
- if (maxAmount != null && maxAmount < 0) throw new Error("Max Amount must be a non-negative number");
458
+ if (maxAmount != null && maxAmount < 0) throw new payload.APIError("Max Amount must be a non-negative number", 400);
458
459
  const minOrderAmount = toNumber(data.minOrderAmount);
459
- if (minOrderAmount != null && minOrderAmount < 0) throw new Error("Minimum Order Amount must be a non-negative number");
460
+ if (minOrderAmount != null && minOrderAmount < 0) throw new payload.APIError("Minimum Order Amount must be a non-negative number", 400);
460
461
  data.maxAmount = maxAmount ?? null;
461
462
  data.minOrderAmount = minOrderAmount ?? null;
462
463
  data.commissionRules = data.commissionRules.map((rule, index) => {
463
464
  const r = rule;
464
- if (!r.totalCommission) throw new Error(`Commission rule ${index + 1}: Total Commission is required`);
465
- 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(", ")}`);
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);
466
467
  const type = r.totalCommission.type;
467
- const totalValue = toNumber(r.totalCommission.value);
468
- if (type === "percentage") {
469
- if (totalValue == null || totalValue < 0) throw new Error(`Commission rule ${index + 1}: Total Commission value must be a non-negative number`);
470
- if (totalValue > 100) throw new Error(`Commission rule ${index + 1}: Percentage Total Commission cannot exceed 100`);
471
- }
472
468
  const appliesTo = r.appliesTo ?? "all";
473
- if (appliesTo === "products" && (!r.products || r.products.length === 0)) throw new Error(`Commission rule ${index + 1}: At least one product is required`);
474
- 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`);
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);
475
471
  let partnerSplit;
476
472
  let customerSplit;
477
473
  let partnerPercent = null;
478
474
  let customerPercent = null;
479
475
  let partnerAmount = null;
480
476
  let customerAmount = null;
477
+ let splitWarning = null;
481
478
  if (type === "percentage") {
482
479
  const partnerPctInput = toNumber(r.partnerPercent) ?? toNumber(r.partnerSplit);
483
- if (partnerPctInput == null || partnerPctInput < 0 || partnerPctInput > 100) throw new Error(`Commission rule ${index + 1}: Partner Split must be between 0 and 100`);
484
- const customerPctComputed = 100 - partnerPctInput;
485
- if (customerPctComputed < 0 || customerPctComputed > 100) throw new Error(`Commission rule ${index + 1}: Customer percentage must be between 0 and 100`);
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).`;
486
487
  partnerPercent = partnerPctInput;
487
488
  customerPercent = customerPctComputed;
488
489
  partnerSplit = partnerPctInput;
@@ -495,36 +496,33 @@ const createReferralProgramsCollection = (pluginConfig) => {
495
496
  const hasNewFixedInputs = partnerAmountInput != null || customerAmountInput != null;
496
497
  const hasLegacyFixedInputs = legacyPartnerSplitInput != null || legacyCustomerSplitInput != null;
497
498
  if (hasNewFixedInputs) {
498
- if (partnerAmountInput == null || partnerAmountInput < 0) throw new Error(`Commission rule ${index + 1}: Partner fixed amount must be a non-negative number`);
499
- if (customerAmountInput == null || customerAmountInput < 0) throw new Error(`Commission rule ${index + 1}: Customer fixed amount must be a non-negative number`);
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);
500
501
  partnerAmount = partnerAmountInput;
501
502
  customerAmount = customerAmountInput;
502
503
  partnerSplit = toCents(partnerAmountInput);
503
504
  customerSplit = toCents(customerAmountInput);
504
505
  } else if (hasLegacyFixedInputs) {
505
- 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`);
506
- const legacyHasTotalValue = toNumber(r.totalCommission?.value) != null;
507
- const resolvedLegacyCustomerSplit = legacyCustomerSplitInput ?? (legacyHasTotalValue ? 100 - legacyPartnerSplitInput : null);
508
- 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`);
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
509
  partnerSplit = legacyPartnerSplitInput;
510
510
  customerSplit = resolvedLegacyCustomerSplit;
511
511
  partnerAmount = null;
512
512
  customerAmount = null;
513
- } else throw new Error(`Commission rule ${index + 1}: For fixed commissions, both partner and customer values must be provided`);
513
+ } else throw new payload.APIError(`Commission rule ${index + 1}: For fixed commissions, both partner and customer values must be provided`, 400);
514
514
  }
515
515
  return {
516
516
  ...rule,
517
517
  appliesTo: appliesTo === "categories" ? "segments" : appliesTo,
518
- totalCommission: {
519
- type,
520
- value: type === "percentage" ? totalValue : null
521
- },
518
+ totalCommission: { type },
522
519
  partnerPercent,
523
520
  customerPercent,
524
521
  partnerAmount,
525
522
  customerAmount,
526
523
  partnerSplit,
527
- customerSplit
524
+ customerSplit,
525
+ splitWarning
528
526
  };
529
527
  });
530
528
  return data;
@@ -624,15 +622,6 @@ const createReferralProgramsCollection = (pluginConfig) => {
624
622
  value
625
623
  })),
626
624
  defaultValue: allowedTotalCommissionTypes.includes("fixed") ? "fixed" : "percentage"
627
- }, {
628
- name: "value",
629
- type: "number",
630
- min: 0,
631
- max: 100,
632
- admin: {
633
- condition: (_, siblingData) => siblingData?.type === "percentage",
634
- description: "Total commission percentage for this rule (0-100). Partner/Customer percentages split this 100-based bucket."
635
- }
636
625
  }]
637
626
  },
638
627
  {
@@ -642,7 +631,7 @@ const createReferralProgramsCollection = (pluginConfig) => {
642
631
  max: 100,
643
632
  admin: {
644
633
  condition: (_, siblingData) => siblingData?.totalCommission?.type === "percentage",
645
- description: "Partner share in percent (0-100). Customer share is auto-calculated as 100 - Partner."
634
+ description: "Partner share in percent (0-100)"
646
635
  }
647
636
  },
648
637
  {
@@ -651,17 +640,9 @@ const createReferralProgramsCollection = (pluginConfig) => {
651
640
  min: 0,
652
641
  max: 100,
653
642
  admin: {
654
- readOnly: true,
655
643
  condition: (_, siblingData) => siblingData?.totalCommission?.type === "percentage",
656
- description: "Auto-calculated customer share percentage."
657
- },
658
- hooks: { beforeValidate: [({ siblingData }) => {
659
- if (!siblingData || siblingData.totalCommission?.type !== "percentage") return null;
660
- const partner = toNumber(siblingData.partnerPercent) ?? toNumber(siblingData.partnerSplit) ?? 0;
661
- if (partner < 0) return 100;
662
- if (partner > 100) return 0;
663
- return 100 - partner;
664
- }] }
644
+ description: "Customer share percentage. (0-100). Partner + Customer cannot exceed 100."
645
+ }
665
646
  },
666
647
  {
667
648
  name: "partnerAmount",
@@ -782,13 +763,25 @@ function calculateItemRewardByRule({ rule, itemTotal, quantity, maxAmount, allow
782
763
  const allowedTypes = allowedCommissionTypesSet(allowedTotalCommissionTypes);
783
764
  if (rule.totalCommission) {
784
765
  if (!allowedTypes.has(rule.totalCommission.type)) return null;
766
+ const resolvedMaxAmount = typeof maxAmount === "number" && Number.isFinite(maxAmount) ? maxAmount : typeof rule.totalCommission.maxAmount === "number" && Number.isFinite(rule.totalCommission.maxAmount) ? rule.totalCommission.maxAmount : null;
785
767
  if (rule.totalCommission.type === "fixed" && rule.totalCommission.value == null) {
786
- const partnerAmt = typeof rule.partnerSplit === "number" ? rule.partnerSplit : null;
787
- const customerAmt = typeof rule.customerSplit === "number" ? rule.customerSplit : null;
788
- if (partnerAmt == null || customerAmt == null) return null;
768
+ const partnerAmtPerUnit = typeof rule.partnerSplit === "number" ? rule.partnerSplit : null;
769
+ const customerAmtPerUnit = typeof rule.customerSplit === "number" ? rule.customerSplit : null;
770
+ if (partnerAmtPerUnit == null || customerAmtPerUnit == null) return null;
771
+ let partner = partnerAmtPerUnit * quantity;
772
+ let customer = customerAmtPerUnit * quantity;
773
+ if (resolvedMaxAmount != null) {
774
+ const maxPotForLine = resolvedMaxAmount * quantity;
775
+ const totalPot = partner + customer;
776
+ if (totalPot > maxPotForLine && totalPot > 0) {
777
+ const ratio = maxPotForLine / totalPot;
778
+ partner = Math.floor(partner * ratio);
779
+ customer = Math.floor(customer * ratio);
780
+ }
781
+ }
789
782
  return {
790
- partner: partnerAmt * quantity,
791
- customer: customerAmt * quantity
783
+ partner,
784
+ customer
792
785
  };
793
786
  }
794
787
  const splits = getRuleSplits(rule);
@@ -796,7 +789,6 @@ function calculateItemRewardByRule({ rule, itemTotal, quantity, maxAmount, allow
796
789
  let totalPot = 0;
797
790
  if (rule.totalCommission.type === "percentage") totalPot = itemTotal * rule.totalCommission.value / 100;
798
791
  else totalPot = rule.totalCommission.value * quantity;
799
- const resolvedMaxAmount = typeof maxAmount === "number" && Number.isFinite(maxAmount) ? maxAmount : typeof rule.totalCommission.maxAmount === "number" && Number.isFinite(rule.totalCommission.maxAmount) ? rule.totalCommission.maxAmount : null;
800
792
  if (resolvedMaxAmount != null) {
801
793
  const maxPotForLine = resolvedMaxAmount * quantity;
802
794
  if (totalPot > maxPotForLine) totalPot = maxPotForLine;