@pisell/pisellos
Version:
一个可扩展的前端模块化SDK框架,支持插件系统
462 lines (460 loc) • 20.5 kB
JavaScript
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/modules/Rules/index.ts
var Rules_exports = {};
__export(Rules_exports, {
RulesModule: () => RulesModule
});
module.exports = __toCommonJS(Rules_exports);
var import_BaseModule = require("../BaseModule");
var import_types = require("./types");
var import_utils = require("../../solution/ShopDiscount/utils");
var import_utils2 = require("../Cart/utils");
var import_decimal = __toESM(require("decimal.js"));
var RulesModule = class extends import_BaseModule.BaseModule {
constructor(name, version) {
super(name, version);
this.defaultName = "rules";
this.defaultVersion = "1.0.0";
this.hooks = {};
}
async initialize(core, options) {
this.core = core;
this.hooks = options == null ? void 0 : options.hooks;
this.store = options == null ? void 0 : options.store;
}
async setRulesList(rulesList) {
this.store.rulesList = rulesList;
await this.core.effects.emit(import_types.RulesHooks.OnRulesListChange, rulesList);
}
getRulesList() {
return this.store.rulesList;
}
// 判断discountList 是否可以对当前productList生效
isDiscountListAvailable({
oldDiscountList,
newDiscountList,
productList
}) {
if (!newDiscountList || newDiscountList.length === 0) {
return {
isAvailable: false,
discountList: oldDiscountList,
productList
};
}
if (productList.every((item) => {
var _a;
return item.booking_id && (((_a = item.discount_list) == null ? void 0 : _a.length) || item.price == 0);
})) {
return {
isAvailable: false,
discountList: oldDiscountList,
productList
};
}
const mergedDiscountList = (0, import_utils.uniqueById)((0, import_utils.uniqueById)([
...oldDiscountList,
...newDiscountList
]), "product_id");
const result = this.calcDiscount({
discountList: mergedDiscountList,
productList: [...productList]
}, {
scan: true
});
let hasApplicableDiscount = false;
const newDiscountIds = newDiscountList.map((discount) => discount.id);
result.productList.forEach((product) => {
const { discount_list } = this.hooks.getProduct(product);
if (discount_list && discount_list.length > 0) {
const usedNewDiscount = discount_list.some(
(discount) => {
var _a;
return newDiscountIds.includes((_a = discount == null ? void 0 : discount.discount) == null ? void 0 : _a.resource_id);
}
);
if (usedNewDiscount) {
hasApplicableDiscount = true;
}
}
});
return {
isAvailable: hasApplicableDiscount,
discountList: hasApplicableDiscount ? result.discountList : oldDiscountList,
productList: hasApplicableDiscount ? result.productList : productList
};
}
calcDiscount({
discountList,
productList
}, options) {
const isEditModeAddNewProduct = productList.find((n) => n.booking_id) && productList.find((n) => !n.booking_id);
const editModeDiscount = [];
const addModeDiscount = [];
discountList.forEach((discount) => {
if (discount.isEditMode) {
editModeDiscount.push(discount);
} else {
addModeDiscount.push(discount);
}
});
const filteredDiscountList = addModeDiscount.filter((discount) => {
return !discount.isManualSelect;
});
const sortedDiscountList = [...filteredDiscountList].sort((a, b) => {
if (a.tag === "good_pass" && b.tag !== "good_pass")
return -1;
if (b.tag === "good_pass" && a.tag !== "good_pass")
return 1;
if (a.tag === "good_pass" && b.tag === "good_pass") {
return compareByExpireTime(a, b);
} else if (a.tag === "product_discount_card" && b.tag === "product_discount_card") {
if (a.par_value !== b.par_value) {
const valueA = new import_decimal.default(100).minus(a.par_value || 0);
const valueB = new import_decimal.default(100).minus(b.par_value || 0);
return valueA.minus(valueB).toNumber();
}
return compareByExpireTime(a, b);
}
return compareByExpireTime(a, b);
function compareByExpireTime(itemA, itemB) {
if (itemA.expire_time && itemB.expire_time) {
const timeA = new Date(itemA.expire_time).getTime();
const timeB = new Date(itemB.expire_time).getTime();
return timeA - timeB;
}
return itemA.expire_time ? -1 : itemB.expire_time ? 1 : 0;
}
});
const sortedProductList = [...productList].sort((a, b) => {
var _a, _b;
const aProduct = this.hooks.getProduct(a);
const bProduct = this.hooks.getProduct(b);
const priceA = new import_decimal.default(aProduct.price || "0");
const priceB = new import_decimal.default(bProduct.price || "0");
if (priceA.toNumber() === priceB.toNumber()) {
if (aProduct.quantity === bProduct.quantity) {
return ((_a = bProduct.discount_list) == null ? void 0 : _a.length) - ((_b = aProduct.discount_list) == null ? void 0 : _b.length);
}
return aProduct.quantity - bProduct.quantity;
}
return priceB.toNumber() - priceA.toNumber();
});
const usedDiscounts = /* @__PURE__ */ new Map();
const discountApplicability = /* @__PURE__ */ new Map();
const discountApplicableProducts = /* @__PURE__ */ new Map();
addModeDiscount.forEach((discount) => {
discountApplicability.set(discount.id, []);
discountApplicableProducts.set(discount.id, []);
});
const processedProductsMap = /* @__PURE__ */ new Map();
const appliedDiscountProducts = /* @__PURE__ */ new Map();
sortedProductList.forEach((originProduct) => {
const product = this.hooks.getProduct(originProduct);
addModeDiscount.forEach((discount) => {
var _a, _b, _c;
const limitedData = discount == null ? void 0 : discount.limited_relation_product_data;
const isLimitedProduct = limitedData.type === "product_all" || limitedData.product_ids && limitedData.product_ids.includes(product.id);
const isAvailableProduct = !((product == null ? void 0 : product.booking_id) && ((_a = product == null ? void 0 : product.discount_list) == null ? void 0 : _a.length) && ((_b = product == null ? void 0 : product.discount_list) == null ? void 0 : _b.every((discount2) => discount2.id && ["good_pass", "discount_card", "product_discount_card"].includes(discount2.tag || discount2.type))));
if (isAvailableProduct && isLimitedProduct) {
(_c = discountApplicability.get(discount.id)) == null ? void 0 : _c.push(product.id);
const applicableProducts = discountApplicableProducts.get(discount.id) || [];
applicableProducts.push({
amount: product.price,
type: discount.tag || discount.type,
tag: discount.tag || discount.type,
discount: {
resource_id: discount.id,
title: discount.format_title,
original_amount: product.origin_total,
pre_value: discount.par_value,
product_id: originProduct.id
},
num: product.num || 1
});
discountApplicableProducts.set(discount.id, applicableProducts);
}
});
});
console.log(sortedProductList, "sortedProductListsortedProductList");
sortedProductList.forEach((originProduct, i) => {
var _a, _b, _c, _d, _e, _f;
const product = this.hooks.getProduct(originProduct);
if ((product == null ? void 0 : product.booking_id) && ((_a = product.discount_list) == null ? void 0 : _a.length) && ((_b = product == null ? void 0 : product.discount_list) == null ? void 0 : _b.every((discount) => discount.id && ["good_pass", "discount_card", "product_discount_card"].includes(discount.tag || discount.type)))) {
processedProductsMap.set(product._id, [originProduct]);
return;
}
const applicableDiscounts = sortedDiscountList.filter((discount) => {
if (Number(product.price) === 0 || !product.price)
return false;
const targetUsedDiscounts = usedDiscounts.get(discount.id);
if (targetUsedDiscounts && (discount.tag || discount.type) === "good_pass")
return false;
const limitedData = discount.limited_relation_product_data;
if (limitedData.type === "product_all") {
return true;
} else if (limitedData.product_ids && limitedData.product_ids.includes(product.id)) {
return true;
}
return false;
});
const selectedDiscount = applicableDiscounts[0];
let isManualDiscount = typeof product.isManualDiscount === "boolean" ? product.isManualDiscount : product.total != product.origin_total && (!((_c = product.discount_list) == null ? void 0 : _c.length) || ((_e = (_d = product == null ? void 0 : product.discount_list) == null ? void 0 : _d.every) == null ? void 0 : _e.call(_d, (item) => item.type === "product")));
if ((options == null ? void 0 : options.discountId) && product.discount_list.some((item) => {
var _a2;
return ((_a2 = item.discount) == null ? void 0 : _a2.resource_id) === options.discountId;
})) {
isManualDiscount = false;
}
if (applicableDiscounts.length === 0 || isManualDiscount) {
if (product.isClient) {
processedProductsMap.set(
product._id,
[this.hooks.setProduct(originProduct, {
...isManualDiscount ? {} : {
origin_total: (0, import_utils2.getProductOriginTotalPrice)({
product: {
original_price: product.original_price
},
bundle: product.bundle,
options: product.options
}),
variant: originProduct._productInit.variant,
original_price: originProduct._productInit.original_price,
total: (0, import_utils2.getProductTotalPrice)({
product: {
price: product.price
},
bundle: product.bundle,
options: product.options
}),
price: product.price
},
discount_list: []
})]
);
} else {
processedProductsMap.set(
product._id,
[this.hooks.setProduct(originProduct, {
...isManualDiscount ? {} : {
_id: product._id.split("___")[0] + "___" + i,
total: product.origin_total || product.total,
price: product.price
},
discount_list: []
})]
);
}
return;
}
if (applicableDiscounts.length && product.booking_id && typeof selectedDiscount.isManualSelect === "undefined" && !(options == null ? void 0 : options.scan) && !isEditModeAddNewProduct) {
return;
}
const isNeedSplit = (selectedDiscount.tag || selectedDiscount.type) === "good_pass";
const splitCount = isNeedSplit ? Math.min(product.quantity, applicableDiscounts.filter((item) => (item.tag || item.type) === "good_pass").length) : 1;
const arr = [];
if (splitCount < product.quantity && isNeedSplit) {
arr.push(this.hooks.setProduct(originProduct, {
discount_list: [],
quantity: product.quantity - splitCount,
_id: product._id.split("___")[0]
}));
}
for (let i2 = 0; i2 < splitCount; i2++) {
const selectedDiscount2 = applicableDiscounts[i2];
usedDiscounts.set(selectedDiscount2.id, true);
const appliedProducts = appliedDiscountProducts.get(selectedDiscount2.id) || [];
const targetProductPrice = selectedDiscount2.tag === "good_pass" ? "0" : new import_decimal.default(100).minus(selectedDiscount2.par_value || 0).div(100).mul(new import_decimal.default(product.price || 0)).toFixed(2);
const discountDetail = {
amount: selectedDiscount2.tag === "good_pass" ? product.price : new import_decimal.default(product.price || 0).minus(new import_decimal.default(targetProductPrice)).toNumber(),
type: selectedDiscount2.tag === "product_discount_card" ? "discount_card" : selectedDiscount2.tag,
discount: {
resource_id: selectedDiscount2.id,
title: selectedDiscount2.format_title,
original_amount: product.origin_total || product.price,
product_id: originProduct.id,
percent: selectedDiscount2.par_value
},
num: product.num || 1
};
appliedProducts.push(discountDetail);
appliedDiscountProducts.set(selectedDiscount2.id, appliedProducts);
if (product.isClient) {
const variant = (_f = originProduct._productOrigin.variant) == null ? void 0 : _f.map((n) => {
var _a2;
if (n.id === ((_a2 = originProduct._productOrigin) == null ? void 0 : _a2.product_variant_id)) {
n.original_price = n.price;
const targetProductPrice2 = selectedDiscount2.tag === "good_pass" ? "0" : new import_decimal.default(100).minus(selectedDiscount2.par_value || 0).div(100).mul(new import_decimal.default(n.price || 0)).toFixed(2);
n.price = targetProductPrice2;
}
return n;
});
arr.push(this.hooks.setProduct(originProduct, {
discount_list: [discountDetail],
price: new import_decimal.default(targetProductPrice).toNumber(),
quantity: isNeedSplit ? 1 : product.quantity,
origin_total: (0, import_utils2.getProductOriginTotalPrice)({
product: {
original_price: targetProductPrice
},
bundle: product.bundle,
options: product.options
}),
variant,
original_price: new import_decimal.default(product.price).toNumber(),
total: (0, import_utils2.getProductTotalPrice)({
product: {
price: targetProductPrice
},
bundle: product.bundle,
options: product.options
})
}));
} else {
arr.push(this.hooks.setProduct(originProduct, {
discount_list: [discountDetail],
_id: product._id.split("___")[0] + "___" + selectedDiscount2.id,
price: new import_decimal.default(targetProductPrice).toNumber(),
quantity: isNeedSplit ? 1 : product.quantity,
total: new import_decimal.default(product.origin_total || product.total || 0).minus(new import_decimal.default(product.price || 0).minus(new import_decimal.default(targetProductPrice))).toNumber(),
origin_total: product.origin_total || product.total
}));
}
}
console.log(arr, "arrarrarr");
processedProductsMap.set(product._id, arr);
});
const processedProductList = [];
productList.forEach((originProduct) => {
const product = this.hooks.getProduct(originProduct);
const getDefaultProduct = () => {
if (product.isClient) {
return this.hooks.setProduct(originProduct, {
discount_list: [],
price: product.price,
origin_total: (0, import_utils2.getProductOriginTotalPrice)({
product: {
original_price: product.original_price
},
bundle: product.bundle,
options: product.options
}),
variant: originProduct._productInit.variant,
original_price: originProduct._productInit.original_price,
total: (0, import_utils2.getProductTotalPrice)({
product: {
price: product.price
},
bundle: product.bundle,
options: product.options
})
});
} else {
return this.hooks.setProduct(originProduct, {
discount_list: [],
total: product.total,
origin_total: product.origin_total,
price: product.price
});
}
};
const arr = processedProductsMap.get(product._id);
(arr == null ? void 0 : arr.length) ? processedProductList.push(...arr) : processedProductList.push(getDefaultProduct());
});
const updatedDiscountList = addModeDiscount.map((discount) => {
const applicableProducts = discountApplicability.get(discount.id) || [];
const applicableProductDetails = discountApplicableProducts.get(discount.id) || [];
const appliedProductDetails = appliedDiscountProducts.get(discount.id) || [];
const isAvailable = applicableProducts.length > 0;
if (typeof discount.isSelected === "boolean" && discount.isSelected === false && discount.isManualSelect) {
return {
...discount,
isSelected: false,
isAvailable,
// 正确设置可用性
applicableProductIds: applicableProducts,
// 添加可抵扣的商品详情
applicableProductDetails,
// 添加实际抵扣的商品详情(对于未选中的优惠券,为空数组)
appliedProductDetails: []
};
}
if (usedDiscounts.get(discount.id)) {
return {
...discount,
isSelected: true,
// 标记为可用,因为它已被应用
isAvailable: true,
// 记录适用的商品IDs
applicableProductIds: applicableProducts,
// 添加可抵扣的商品详情
applicableProductDetails,
// 添加实际抵扣的商品详情
appliedProductDetails
};
}
let isSelected = typeof discount.isSelected === "boolean" ? discount.isSelected : void 0;
if (isAvailable && appliedProductDetails.length && !discount.isManualSelect) {
isSelected = true;
} else if (!appliedProductDetails.length) {
isSelected = false;
}
return {
...discount,
// 如果有适用的商品,标记为可用
isAvailable,
isSelected,
// 记录适用的商品IDs
applicableProductIds: applicableProducts,
// 添加可抵扣的商品详情
applicableProductDetails,
// 添加实际抵扣的商品详情(对于未使用的优惠券,为空数组)
appliedProductDetails: []
};
});
console.log(processedProductList, "processedProductList");
return {
productList: processedProductList,
discountList: [...editModeDiscount, ...updatedDiscountList]
};
}
async destroy() {
this.core.effects.offByModuleDestroy(this.name);
await this.core.effects.emit(import_types.RulesHooks.OnDestroy, {});
console.log("[Rules] 已销毁");
}
async clear() {
console.log("[Rules] clear");
}
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
RulesModule
});