UNPKG

@pisell/pisellos

Version:

一个可扩展的前端模块化SDK框架,支持插件系统

462 lines (460 loc) 20.5 kB
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 });