@wtree/payload-ecommerce-coupon 3.78.2 → 3.78.4
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/README.md +33 -6
- package/dist/client/hooks.d.ts +1 -1
- package/dist/client/hooks.d.ts.map +1 -1
- package/dist/client/index.d.ts +8 -8
- package/dist/client/index.d.ts.map +1 -1
- package/dist/collections/createCouponsCollection.d.ts +2 -2
- package/dist/collections/createCouponsCollection.d.ts.map +1 -1
- package/dist/collections/createReferralCodesCollection.d.ts +2 -2
- package/dist/collections/createReferralCodesCollection.d.ts.map +1 -1
- package/dist/collections/createReferralProgramsCollection.d.ts +2 -2
- package/dist/collections/createReferralProgramsCollection.d.ts.map +1 -1
- package/dist/components/PartnerDashboard/CommissionBreakdown.d.ts +2 -2
- package/dist/components/PartnerDashboard/CommissionBreakdown.d.ts.map +1 -1
- package/dist/components/PartnerDashboard/EarningsSummary.d.ts +2 -2
- package/dist/components/PartnerDashboard/EarningsSummary.d.ts.map +1 -1
- package/dist/components/PartnerDashboard/ProgramOverview.d.ts +3 -3
- package/dist/components/PartnerDashboard/ProgramOverview.d.ts.map +1 -1
- package/dist/components/PartnerDashboard/RecentReferrals.d.ts +3 -3
- package/dist/components/PartnerDashboard/RecentReferrals.d.ts.map +1 -1
- package/dist/components/PartnerDashboard/ReferralCodes.d.ts +3 -3
- package/dist/components/PartnerDashboard/ReferralCodes.d.ts.map +1 -1
- package/dist/components/PartnerDashboard/ReferralPerformance.d.ts +2 -2
- package/dist/components/PartnerDashboard/ReferralPerformance.d.ts.map +1 -1
- package/dist/components/PartnerDashboard/index.d.ts +1 -1
- package/dist/components/PartnerDashboard/index.d.ts.map +1 -1
- package/dist/endpoints/applyCoupon.d.ts +2 -2
- package/dist/endpoints/applyCoupon.d.ts.map +1 -1
- package/dist/endpoints/partnerStats.d.ts +2 -2
- package/dist/endpoints/partnerStats.d.ts.map +1 -1
- package/dist/endpoints/validateCoupon.d.ts +2 -2
- package/dist/endpoints/validateCoupon.d.ts.map +1 -1
- package/dist/hooks/recalculateCart.d.ts +2 -2
- package/dist/hooks/recalculateCart.d.ts.map +1 -1
- package/dist/index.d.ts +17 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +158 -54
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +122 -18
- package/dist/index.mjs.map +1 -1
- package/dist/plugin.d.ts +2 -2
- package/dist/plugin.d.ts.map +1 -1
- package/dist/types.d.ts +4 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/utilities/calculateValues.d.ts +2 -2
- package/dist/utilities/calculateValues.d.ts.map +1 -1
- package/dist/utilities/getCartTotalWithDiscounts.d.ts.map +1 -1
- package/dist/utilities/migrateReferralRulesV2.d.ts.map +1 -1
- package/dist/utilities/pricing.d.ts.map +1 -1
- package/dist/utilities/pushTypeScriptProperties.d.ts +1 -1
- package/dist/utilities/pushTypeScriptProperties.d.ts.map +1 -1
- package/dist/utilities/recordCouponUsageForOrder.d.ts +2 -2
- package/dist/utilities/recordCouponUsageForOrder.d.ts.map +1 -1
- package/dist/utilities/sanitizePluginConfig.d.ts +1 -1
- package/dist/utilities/sanitizePluginConfig.d.ts.map +1 -1
- package/dist/utilities/userRoles.d.ts +3 -3
- package/dist/utilities/userRoles.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { APIError } from "payload";
|
|
1
|
+
import { APIError, addDataAndFileToRequest } from "payload";
|
|
2
2
|
//#region \0rolldown/runtime.js
|
|
3
3
|
var __create = Object.create;
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -453,11 +453,14 @@ const createReferralProgramsCollection = (pluginConfig) => {
|
|
|
453
453
|
},
|
|
454
454
|
hooks: { beforeChange: [({ data }) => {
|
|
455
455
|
if (!data.commissionRules || !Array.isArray(data.commissionRules) || data.commissionRules.length === 0) throw new APIError("At least one commission rule is required", 400);
|
|
456
|
-
const
|
|
457
|
-
if (
|
|
456
|
+
const maxPartnerCommissionPerOrder = toNumber(data.maxPartnerCommissionPerOrder);
|
|
457
|
+
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);
|
|
459
|
+
if (maxCustomerDiscountPerOrder != null && maxCustomerDiscountPerOrder < 0) throw new APIError("Maximum discount for customer per order must be a non-negative number", 400);
|
|
458
460
|
const minOrderAmount = toNumber(data.minOrderAmount);
|
|
459
461
|
if (minOrderAmount != null && minOrderAmount < 0) throw new APIError("Minimum Order Amount must be a non-negative number", 400);
|
|
460
|
-
data.
|
|
462
|
+
data.maxPartnerCommissionPerOrder = maxPartnerCommissionPerOrder != null ? toCents(maxPartnerCommissionPerOrder) : null;
|
|
463
|
+
data.maxCustomerDiscountPerOrder = maxCustomerDiscountPerOrder != null ? toCents(maxCustomerDiscountPerOrder) : null;
|
|
461
464
|
data.minOrderAmount = minOrderAmount ?? null;
|
|
462
465
|
data.commissionRules = data.commissionRules.map((rule, index) => {
|
|
463
466
|
const r = rule;
|
|
@@ -540,10 +543,16 @@ const createReferralProgramsCollection = (pluginConfig) => {
|
|
|
540
543
|
admin: { description: "Whether this referral program is currently active" }
|
|
541
544
|
},
|
|
542
545
|
{
|
|
543
|
-
name: "
|
|
546
|
+
name: "maxPartnerCommissionPerOrder",
|
|
544
547
|
type: "number",
|
|
545
548
|
min: 0,
|
|
546
|
-
admin: { description: "Maximum commission
|
|
549
|
+
admin: { description: "Maximum commission per order for partner. Leave empty for no cap. Enter value in currency units (will be converted to cents)." }
|
|
550
|
+
},
|
|
551
|
+
{
|
|
552
|
+
name: "maxCustomerDiscountPerOrder",
|
|
553
|
+
type: "number",
|
|
554
|
+
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)." }
|
|
547
556
|
},
|
|
548
557
|
{
|
|
549
558
|
name: "minOrderAmount",
|
|
@@ -758,11 +767,11 @@ function getRuleSplits(rule) {
|
|
|
758
767
|
customerSplit: typeof rule.customerSplit === "number" ? rule.customerSplit : typeof rule.refereeSplit === "number" ? rule.refereeSplit : 100 - partnerRaw
|
|
759
768
|
};
|
|
760
769
|
}
|
|
761
|
-
function calculateItemRewardByRule({ rule, itemTotal, quantity,
|
|
770
|
+
function calculateItemRewardByRule({ rule, itemTotal, quantity, allowedTotalCommissionTypes }) {
|
|
762
771
|
const allowedTypes = allowedCommissionTypesSet(allowedTotalCommissionTypes);
|
|
763
772
|
if (rule.totalCommission) {
|
|
764
773
|
if (!allowedTypes.has(rule.totalCommission.type)) return null;
|
|
765
|
-
const resolvedMaxAmount = typeof
|
|
774
|
+
const resolvedMaxAmount = typeof rule.totalCommission.maxAmount === "number" && Number.isFinite(rule.totalCommission.maxAmount) ? rule.totalCommission.maxAmount : null;
|
|
766
775
|
if (rule.totalCommission.type === "fixed" && rule.totalCommission.value == null) {
|
|
767
776
|
const partnerAmtPerUnit = typeof rule.partnerSplit === "number" ? rule.partnerSplit : null;
|
|
768
777
|
const customerAmtPerUnit = typeof rule.customerSplit === "number" ? rule.customerSplit : null;
|
|
@@ -821,7 +830,7 @@ function getItemCategoryIds(item) {
|
|
|
821
830
|
function getItemTagIds(item) {
|
|
822
831
|
return Array.isArray(item?.product?.tags) ? normalizeIds(item.product.tags) : [];
|
|
823
832
|
}
|
|
824
|
-
function selectBestRuleForItem({ rules, item, itemTotal, quantity, cartTotal, minOrderAmount,
|
|
833
|
+
function selectBestRuleForItem({ rules, item, itemTotal, quantity, cartTotal, minOrderAmount, allowedTotalCommissionTypes }) {
|
|
825
834
|
const allowedTypes = allowedCommissionTypesSet(allowedTotalCommissionTypes);
|
|
826
835
|
const eligibleRules = rules.filter((rule) => {
|
|
827
836
|
if (!(rule?.totalCommission?.type ? allowedTypes.has(rule.totalCommission.type) : true)) return false;
|
|
@@ -851,7 +860,6 @@ function selectBestRuleForItem({ rules, item, itemTotal, quantity, cartTotal, mi
|
|
|
851
860
|
rule,
|
|
852
861
|
itemTotal,
|
|
853
862
|
quantity,
|
|
854
|
-
maxAmount,
|
|
855
863
|
allowedTotalCommissionTypes
|
|
856
864
|
});
|
|
857
865
|
if (!reward) continue;
|
|
@@ -916,13 +924,16 @@ function calculateCommissionAndDiscount({ cartItems, program, currencyCode = "AE
|
|
|
916
924
|
quantity,
|
|
917
925
|
cartTotal,
|
|
918
926
|
minOrderAmount: typeof program?.minOrderAmount === "number" && Number.isFinite(program.minOrderAmount) ? program.minOrderAmount : null,
|
|
919
|
-
maxAmount: typeof program?.maxAmount === "number" && Number.isFinite(program.maxAmount) ? program.maxAmount : null,
|
|
920
927
|
allowedTotalCommissionTypes
|
|
921
928
|
});
|
|
922
929
|
if (!bestMatch) continue;
|
|
923
930
|
totalPartnerCommission += bestMatch.reward.partner;
|
|
924
931
|
totalCustomerDiscount += bestMatch.reward.customer;
|
|
925
932
|
}
|
|
933
|
+
const maxPartnerCommissionPerOrder = typeof program?.maxPartnerCommissionPerOrder === "number" && Number.isFinite(program.maxPartnerCommissionPerOrder) ? program.maxPartnerCommissionPerOrder : null;
|
|
934
|
+
const maxCustomerDiscountPerOrder = typeof program?.maxCustomerDiscountPerOrder === "number" && Number.isFinite(program.maxCustomerDiscountPerOrder) ? program.maxCustomerDiscountPerOrder : null;
|
|
935
|
+
if (maxPartnerCommissionPerOrder != null) totalPartnerCommission = Math.min(totalPartnerCommission, maxPartnerCommissionPerOrder);
|
|
936
|
+
if (maxCustomerDiscountPerOrder != null) totalCustomerDiscount = Math.min(totalCustomerDiscount, maxCustomerDiscountPerOrder);
|
|
926
937
|
return {
|
|
927
938
|
partnerCommission: totalPartnerCommission,
|
|
928
939
|
customerDiscount: totalCustomerDiscount
|
|
@@ -946,6 +957,22 @@ function writeField$1(doc, field, value) {
|
|
|
946
957
|
function normalizeCode$1(value) {
|
|
947
958
|
return typeof value === "string" ? value.trim().toUpperCase() : "";
|
|
948
959
|
}
|
|
960
|
+
async function ensureRequestData$1(req) {
|
|
961
|
+
if (req?.data && typeof req.data === "object") return req.data;
|
|
962
|
+
try {
|
|
963
|
+
await addDataAndFileToRequest(req);
|
|
964
|
+
} catch {}
|
|
965
|
+
if (req?.data && typeof req.data === "object") return req.data;
|
|
966
|
+
try {
|
|
967
|
+
const parsed = await req?.json?.();
|
|
968
|
+
if (parsed && typeof parsed === "object") {
|
|
969
|
+
req.data = parsed;
|
|
970
|
+
return parsed;
|
|
971
|
+
}
|
|
972
|
+
} catch {}
|
|
973
|
+
req.data = {};
|
|
974
|
+
return req.data;
|
|
975
|
+
}
|
|
949
976
|
async function findByNormalizedCode$1({ payload, collection, normalizedCode }) {
|
|
950
977
|
const exactQuery = await payload.find({
|
|
951
978
|
collection,
|
|
@@ -975,9 +1002,11 @@ const applyCouponHandler = ({ pluginConfig }) => async (req) => {
|
|
|
975
1002
|
const { payload } = req;
|
|
976
1003
|
const fields = pluginConfig.integration.fields;
|
|
977
1004
|
const collections = pluginConfig.integration.collections;
|
|
978
|
-
const
|
|
979
|
-
const
|
|
980
|
-
const
|
|
1005
|
+
const data = await ensureRequestData$1(req);
|
|
1006
|
+
const rawCode = data?.code;
|
|
1007
|
+
const cartIDRaw = data?.cartID;
|
|
1008
|
+
const cartID = typeof cartIDRaw === "string" || typeof cartIDRaw === "number" ? cartIDRaw : null;
|
|
1009
|
+
const customerEmail = typeof data?.customerEmail === "string" ? data.customerEmail : void 0;
|
|
981
1010
|
const normalizedCode = normalizeCode$1(rawCode);
|
|
982
1011
|
if (!normalizedCode || !cartID) return Response.json({
|
|
983
1012
|
success: false,
|
|
@@ -1406,6 +1435,22 @@ function relationId$2(value) {
|
|
|
1406
1435
|
function normalizeCode(value) {
|
|
1407
1436
|
return typeof value === "string" ? value.trim().toUpperCase() : "";
|
|
1408
1437
|
}
|
|
1438
|
+
async function ensureRequestData(req) {
|
|
1439
|
+
if (req?.data && typeof req.data === "object") return req.data;
|
|
1440
|
+
try {
|
|
1441
|
+
await addDataAndFileToRequest(req);
|
|
1442
|
+
} catch {}
|
|
1443
|
+
if (req?.data && typeof req.data === "object") return req.data;
|
|
1444
|
+
try {
|
|
1445
|
+
const parsed = await req?.json?.();
|
|
1446
|
+
if (parsed && typeof parsed === "object") {
|
|
1447
|
+
req.data = parsed;
|
|
1448
|
+
return parsed;
|
|
1449
|
+
}
|
|
1450
|
+
} catch {}
|
|
1451
|
+
req.data = {};
|
|
1452
|
+
return req.data;
|
|
1453
|
+
}
|
|
1409
1454
|
async function findByNormalizedCode({ payload, collection, normalizedCode }) {
|
|
1410
1455
|
const normalizedQuery = await payload.find({
|
|
1411
1456
|
collection,
|
|
@@ -1433,10 +1478,12 @@ async function findByNormalizedCode({ payload, collection, normalizedCode }) {
|
|
|
1433
1478
|
}
|
|
1434
1479
|
const validateCouponHandler = ({ pluginConfig }) => async (req) => {
|
|
1435
1480
|
const { payload } = req;
|
|
1436
|
-
const
|
|
1437
|
-
const
|
|
1438
|
-
const
|
|
1439
|
-
const
|
|
1481
|
+
const data = await ensureRequestData(req);
|
|
1482
|
+
const rawCode = data?.code;
|
|
1483
|
+
const cartValue = typeof data?.cartValue === "number" ? data.cartValue : void 0;
|
|
1484
|
+
const cartIDRaw = data?.cartID;
|
|
1485
|
+
const cartID = typeof cartIDRaw === "string" || typeof cartIDRaw === "number" ? cartIDRaw : void 0;
|
|
1486
|
+
const customerEmail = typeof data?.customerEmail === "string" ? data.customerEmail : void 0;
|
|
1440
1487
|
const normalizedCode = normalizeCode(rawCode);
|
|
1441
1488
|
if (!normalizedCode) return Response.json({
|
|
1442
1489
|
success: false,
|
|
@@ -2131,6 +2178,55 @@ const sanitizePluginConfig = ({ pluginConfig }) => {
|
|
|
2131
2178
|
const RECALCULATE_HOOK_KEY = "__payloadEcommerceCouponRecalculateHook__";
|
|
2132
2179
|
const asArray = (value) => Array.isArray(value) ? value : [];
|
|
2133
2180
|
const hasNamedField = (collection, fieldName) => asArray(collection.fields).some((f) => f?.name === fieldName);
|
|
2181
|
+
const normalizePath$1 = (path) => {
|
|
2182
|
+
if (!path) return "/";
|
|
2183
|
+
return (path.startsWith("/") ? path : `/${path}`).replace(/\/+$/, "") || "/";
|
|
2184
|
+
};
|
|
2185
|
+
const toCollectionEndpointPath = ({ endpointPath, collectionSlug }) => {
|
|
2186
|
+
const normalizedEndpointPath = normalizePath$1(endpointPath);
|
|
2187
|
+
const normalizedCollectionPath = normalizePath$1(`/${collectionSlug}`);
|
|
2188
|
+
if (!normalizedEndpointPath.startsWith(`${normalizedCollectionPath}/`)) return null;
|
|
2189
|
+
const relative = normalizedEndpointPath.slice(normalizedCollectionPath.length);
|
|
2190
|
+
return relative.startsWith("/") ? relative : `/${relative}`;
|
|
2191
|
+
};
|
|
2192
|
+
const ensureCouponCollectionEndpoints = ({ collection, pluginConfig }) => {
|
|
2193
|
+
const couponsSlug = pluginConfig.collections.couponsSlug;
|
|
2194
|
+
const applyPath = toCollectionEndpointPath({
|
|
2195
|
+
endpointPath: pluginConfig.endpoints.applyCoupon,
|
|
2196
|
+
collectionSlug: couponsSlug
|
|
2197
|
+
});
|
|
2198
|
+
const validatePath = toCollectionEndpointPath({
|
|
2199
|
+
endpointPath: pluginConfig.endpoints.validateCoupon,
|
|
2200
|
+
collectionSlug: couponsSlug
|
|
2201
|
+
});
|
|
2202
|
+
if (!applyPath && !validatePath) return collection;
|
|
2203
|
+
const endpoints = asArray(collection.endpoints);
|
|
2204
|
+
const endpointKeys = new Set(endpoints.map((e) => `${(e?.method || "get").toLowerCase()}:${e?.path || ""}`));
|
|
2205
|
+
if (validatePath) {
|
|
2206
|
+
const validateKey = `post:${validatePath}`;
|
|
2207
|
+
if (!endpointKeys.has(validateKey)) {
|
|
2208
|
+
endpointKeys.add(validateKey);
|
|
2209
|
+
endpoints.push({
|
|
2210
|
+
path: validatePath,
|
|
2211
|
+
method: "post",
|
|
2212
|
+
handler: validateCouponEndpoint({ pluginConfig }).handler
|
|
2213
|
+
});
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
2216
|
+
if (applyPath) {
|
|
2217
|
+
const applyKey = `post:${applyPath}`;
|
|
2218
|
+
if (!endpointKeys.has(applyKey)) {
|
|
2219
|
+
endpointKeys.add(applyKey);
|
|
2220
|
+
endpoints.push({
|
|
2221
|
+
path: applyPath,
|
|
2222
|
+
method: "post",
|
|
2223
|
+
handler: applyCouponEndpoint({ pluginConfig }).handler
|
|
2224
|
+
});
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2227
|
+
collection.endpoints = endpoints;
|
|
2228
|
+
return collection;
|
|
2229
|
+
};
|
|
2134
2230
|
const addFieldsToCollection = (config, targetSlug, newFields) => {
|
|
2135
2231
|
const collections = asArray(config.collections);
|
|
2136
2232
|
const idx = collections.findIndex((c) => c.slug === targetSlug);
|
|
@@ -2215,11 +2311,19 @@ const payloadEcommerceCouponPlugin = (pluginOptions = {}) => async (incomingConf
|
|
|
2215
2311
|
if (pluginConfig.referralConfig.allowBothSystems) {
|
|
2216
2312
|
let couponsCollection = createCouponsCollection(pluginConfig);
|
|
2217
2313
|
if (pluginOptions.collections?.couponsCollectionOverride) couponsCollection = await pluginOptions.collections.couponsCollectionOverride({ defaultCollection: couponsCollection });
|
|
2314
|
+
couponsCollection = ensureCouponCollectionEndpoints({
|
|
2315
|
+
collection: couponsCollection,
|
|
2316
|
+
pluginConfig
|
|
2317
|
+
});
|
|
2218
2318
|
collectionsToAdd.push(couponsCollection);
|
|
2219
2319
|
}
|
|
2220
2320
|
} else {
|
|
2221
2321
|
let couponsCollection = createCouponsCollection(pluginConfig);
|
|
2222
2322
|
if (pluginOptions.collections?.couponsCollectionOverride) couponsCollection = await pluginOptions.collections.couponsCollectionOverride({ defaultCollection: couponsCollection });
|
|
2323
|
+
couponsCollection = ensureCouponCollectionEndpoints({
|
|
2324
|
+
collection: couponsCollection,
|
|
2325
|
+
pluginConfig
|
|
2326
|
+
});
|
|
2223
2327
|
collectionsToAdd.push(couponsCollection);
|
|
2224
2328
|
}
|
|
2225
2329
|
const existingSlugs = new Set(asArray(incomingConfig.collections).map((c) => c.slug));
|