@pisell/pisellos 0.0.569 → 0.10.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/core/index.js +10 -6
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -3
- package/dist/model/strategy/adapter/promotion/index.js +9 -0
- package/dist/model/strategy/adapter/walletPass/evaluator.js +7 -5
- package/dist/model/strategy/adapter/walletPass/example.js +26 -3
- package/dist/model/strategy/adapter/walletPass/index.js +5 -5
- package/dist/model/strategy/adapter/walletPass/type.d.ts +0 -3
- package/dist/model/strategy/adapter/walletPass/utils.d.ts +0 -26
- package/dist/model/strategy/adapter/walletPass/utils.js +17 -92
- package/dist/model/strategy/strategy-example.js +19 -5
- package/dist/modules/BaseModule.d.ts +1 -1
- package/dist/modules/BaseModule.js +8 -10
- package/dist/modules/Cart/index.js +3 -0
- package/dist/modules/Cart/utils/cartProduct.js +1 -0
- package/dist/modules/Cart/utils/cartResource.js +0 -2
- package/dist/modules/Cart/utils/changePrice.js +9 -16
- package/dist/modules/Date/index.js +5 -1
- package/dist/modules/Discount/index.d.ts +0 -1
- package/dist/modules/Discount/index.js +7 -22
- package/dist/modules/Discount/types.d.ts +0 -1
- package/dist/modules/OpenData/index.js +2 -0
- package/dist/modules/Order/index.js +70 -40
- package/dist/modules/Payment/index.js +162 -97
- package/dist/modules/Payment/types.d.ts +4 -8
- package/dist/modules/Payment/walletpass.d.ts +0 -2
- package/dist/modules/Payment/walletpass.js +5 -4
- package/dist/modules/ProductList/index.d.ts +1 -1
- package/dist/modules/ProductList/index.js +3 -12
- package/dist/modules/ProductList/types.d.ts +0 -1
- package/dist/modules/Rules/index.js +126 -427
- package/dist/modules/SalesSummary/utils.js +1 -2
- package/dist/modules/Schedule/getDateIsInSchedule.js +0 -5
- package/dist/modules/Schedule/index.js +1 -0
- package/dist/modules/Schedule/utils.js +1 -0
- package/dist/modules/Step/index.js +1 -0
- package/dist/modules/Summary/utils.js +22 -43
- package/dist/plugins/request.js +4 -1
- package/dist/plugins/window.js +6 -2
- package/dist/server/index.js +129 -97
- package/dist/server/modules/menu/index.js +41 -32
- package/dist/server/modules/order/index.js +4 -2
- package/dist/server/modules/products/index.js +42 -24
- package/dist/server/modules/quotation/index.js +38 -29
- package/dist/server/modules/resource/index.js +4 -3
- package/dist/server/modules/schedule/index.js +35 -27
- package/dist/server/utils/product.js +1 -0
- package/dist/solution/BaseSales/index.js +41 -38
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/BookingByStep/index.js +60 -11
- package/dist/solution/BookingByStep/utils/capacity.js +11 -1
- package/dist/solution/BookingByStep/utils/resources.js +3 -1
- package/dist/solution/BookingByStep/utils/timeslots.js +43 -2
- package/dist/solution/BookingTicket/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.js +2 -0
- package/dist/solution/BookingTicket/utils/scan/cloudSearch.js +7 -6
- package/dist/solution/BookingTicket/utils/scan/handleScan.js +31 -25
- package/dist/solution/BookingTicket/utils/scan/index.js +10 -6
- package/dist/solution/BuyTickets/index.js +12 -9
- package/dist/solution/Checkout/index.js +252 -177
- package/dist/solution/Checkout/utils/index.js +16 -4
- package/dist/solution/RegisterAndLogin/index.js +76 -30
- package/dist/solution/ScanOrder/index.js +60 -50
- package/dist/solution/ShopDiscount/index.js +14 -15
- package/dist/solution/ShopDiscount/types.d.ts +4 -5
- package/dist/solution/ShopDiscount/utils.d.ts +0 -9
- package/dist/solution/ShopDiscount/utils.js +0 -9
- package/dist/solution/VenueBooking/index.d.ts +3 -31
- package/dist/solution/VenueBooking/index.js +496 -651
- package/dist/solution/VenueBooking/types.d.ts +1 -3
- package/dist/solution/VenueBooking/types.js +0 -1
- package/dist/solution/VenueBooking/utils/dateSummary.d.ts +2 -2
- package/dist/solution/VenueBooking/utils/dateSummary.js +25 -12
- package/dist/solution/VenueBooking/utils/timeSlot.d.ts +0 -2
- package/dist/solution/VenueBooking/utils/timeSlot.js +4 -9
- package/dist/types/index.d.ts +1 -1
- package/dist/utils/task.js +18 -15
- package/dist/utils/watch.js +1 -0
- package/lib/apis/picoding.js +0 -2
- package/lib/core/index.js +132 -130
- package/lib/effects/index.js +57 -46
- package/lib/index.d.ts +0 -1
- package/lib/index.js +50 -92
- package/lib/model/index.js +21 -14
- package/lib/model/strategy/adapter/dataVariant/adapter.js +50 -38
- package/lib/model/strategy/adapter/dataVariant/evaluator.js +236 -162
- package/lib/model/strategy/adapter/dataVariant/examples.js +237 -229
- package/lib/model/strategy/adapter/dataVariant/index.js +34 -39
- package/lib/model/strategy/adapter/dataVariant/type.js +28 -57
- package/lib/model/strategy/adapter/index.js +64 -100
- package/lib/model/strategy/adapter/itemRule/adapter.js +144 -156
- package/lib/model/strategy/adapter/itemRule/evaluator.js +48 -36
- package/lib/model/strategy/adapter/itemRule/examples.js +225 -295
- package/lib/model/strategy/adapter/itemRule/index.js +57 -83
- package/lib/model/strategy/adapter/itemRule/type.js +36 -97
- package/lib/model/strategy/adapter/promotion/adapter.js +63 -84
- package/lib/model/strategy/adapter/promotion/evaluator.js +231 -381
- package/lib/model/strategy/adapter/promotion/examples.js +159 -139
- package/lib/model/strategy/adapter/promotion/index.js +49 -1
- package/lib/model/strategy/adapter/promotion/type.js +35 -199
- package/lib/model/strategy/adapter/type.js +16 -4
- package/lib/model/strategy/adapter/walletPass/evaluator.js +152 -180
- package/lib/model/strategy/adapter/walletPass/example.js +190 -217
- package/lib/model/strategy/adapter/walletPass/index.js +51 -75
- package/lib/model/strategy/adapter/walletPass/locales.js +58 -36
- package/lib/model/strategy/adapter/walletPass/type.d.ts +0 -3
- package/lib/model/strategy/adapter/walletPass/type.js +16 -4
- package/lib/model/strategy/adapter/walletPass/utils.d.ts +0 -26
- package/lib/model/strategy/adapter/walletPass/utils.js +383 -678
- package/lib/model/strategy/engine.js +168 -270
- package/lib/model/strategy/index.js +34 -49
- package/lib/model/strategy/strategy-example.js +239 -243
- package/lib/model/strategy/type.js +40 -100
- package/lib/modules/Account/index.js +53 -39
- package/lib/modules/Account/types.js +33 -20
- package/lib/modules/AccountList/index.js +154 -116
- package/lib/modules/AccountList/types.js +31 -30
- package/lib/modules/AccountList/utils.js +30 -18
- package/lib/modules/BaseModule.d.ts +1 -1
- package/lib/modules/BaseModule.js +46 -25
- package/lib/modules/BookingContext/index.js +136 -158
- package/lib/modules/BookingContext/types.js +32 -46
- package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +143 -131
- package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +82 -75
- package/lib/modules/BookingContext/utils/cacheItemToBookingInput.js +150 -170
- package/lib/modules/BookingContext/utils/flexible.js +55 -38
- package/lib/modules/BookingContext/utils/formatResourceList.js +34 -19
- package/lib/modules/BookingContext/utils/index.js +41 -124
- package/lib/modules/BookingContext/utils/noResource.js +70 -58
- package/lib/modules/BookingContext/utils/orderLineDisplay.js +41 -14
- package/lib/modules/BookingContext/utils/productExtend.js +155 -202
- package/lib/modules/BookingContext/utils/resourceErrors.js +53 -53
- package/lib/modules/BookingContext/utils/resourceSelection.js +41 -19
- package/lib/modules/BookingContext/utils/resources.js +167 -209
- package/lib/modules/BookingContext/utils/serviceTimes.js +116 -115
- package/lib/modules/BookingContext/utils/timeSlices.js +80 -70
- package/lib/modules/Cart/index.js +124 -170
- package/lib/modules/Cart/types.js +51 -46
- package/lib/modules/Cart/utils/cartAccount.js +39 -40
- package/lib/modules/Cart/utils/cartDate.js +61 -56
- package/lib/modules/Cart/utils/cartDiscount.js +33 -28
- package/lib/modules/Cart/utils/cartNote.js +32 -27
- package/lib/modules/Cart/utils/cartProduct.js +251 -321
- package/lib/modules/Cart/utils/cartRelationForms.js +35 -29
- package/lib/modules/Cart/utils/cartResource.js +78 -72
- package/lib/modules/Cart/utils/changePrice.js +50 -28
- package/lib/modules/Cart/utils/index.js +48 -106
- package/lib/modules/Customer/constants.js +34 -13
- package/lib/modules/Customer/index.js +169 -232
- package/lib/modules/Customer/types.js +35 -38
- package/lib/modules/Date/index.js +115 -116
- package/lib/modules/Date/types.js +28 -16
- package/lib/modules/Date/utils.js +123 -174
- package/lib/modules/Discount/index.d.ts +0 -1
- package/lib/modules/Discount/index.js +128 -130
- package/lib/modules/Discount/types.d.ts +0 -1
- package/lib/modules/Discount/types.js +31 -9
- package/lib/modules/Guests/index.js +56 -30
- package/lib/modules/Guests/types.js +33 -23
- package/lib/modules/Holder/index.js +189 -209
- package/lib/modules/Holder/types.js +16 -4
- package/lib/modules/Holder/utils.js +49 -20
- package/lib/modules/OpenData/index.js +76 -69
- package/lib/modules/OpenData/types.js +16 -4
- package/lib/modules/OpenData/utils.js +78 -44
- package/lib/modules/Order/index.js +1909 -1572
- package/lib/modules/Order/types.js +35 -78
- package/lib/modules/Order/utils/bundleDiscountHydration.js +74 -41
- package/lib/modules/Order/utils/manualProductDiscount.js +123 -124
- package/lib/modules/Order/utils/orderCollectionIdentity.js +210 -148
- package/lib/modules/Order/utils.js +634 -799
- package/lib/modules/Payment/cash.js +33 -20
- package/lib/modules/Payment/cashRecommendationAlgorithm.js +76 -145
- package/lib/modules/Payment/eftpos.js +30 -16
- package/lib/modules/Payment/index.js +378 -518
- package/lib/modules/Payment/mx51.js +0 -1
- package/lib/modules/Payment/types.d.ts +4 -8
- package/lib/modules/Payment/types.js +107 -216
- package/lib/modules/Payment/utils.js +48 -51
- package/lib/modules/Payment/walletpass.d.ts +0 -2
- package/lib/modules/Payment/walletpass.js +211 -226
- package/lib/modules/Product/index.js +46 -51
- package/lib/modules/Product/types.js +16 -4
- package/lib/modules/Product/utils.js +33 -32
- package/lib/modules/ProductList/index.d.ts +1 -1
- package/lib/modules/ProductList/index.js +117 -117
- package/lib/modules/ProductList/types.d.ts +0 -1
- package/lib/modules/ProductList/types.js +31 -9
- package/lib/modules/Quotation/index.js +100 -66
- package/lib/modules/Quotation/types.js +16 -4
- package/lib/modules/Resource/index.js +59 -27
- package/lib/modules/Resource/types.js +32 -22
- package/lib/modules/Resource/utils.js +38 -30
- package/lib/modules/ResourcePlanner/index.js +61 -60
- package/lib/modules/ResourcePlanner/planner.js +384 -346
- package/lib/modules/ResourcePlanner/types.js +16 -4
- package/lib/modules/Rules/index.js +903 -1475
- package/lib/modules/Rules/types.js +40 -17
- package/lib/modules/SalesSummary/index.js +90 -85
- package/lib/modules/SalesSummary/types.js +16 -4
- package/lib/modules/SalesSummary/utils.js +427 -351
- package/lib/modules/ScanOrderLogger/index.js +79 -59
- package/lib/modules/ScanOrderLogger/providers/feishu.js +78 -54
- package/lib/modules/ScanOrderLogger/providers/grafana.js +36 -13
- package/lib/modules/ScanOrderLogger/types.js +16 -4
- package/lib/modules/Schedule/getDateIsInSchedule.js +163 -339
- package/lib/modules/Schedule/index.js +114 -100
- package/lib/modules/Schedule/type.js +16 -4
- package/lib/modules/Schedule/types.js +16 -4
- package/lib/modules/Schedule/utils.js +291 -433
- package/lib/modules/Step/index.js +52 -40
- package/lib/modules/Step/tyeps.js +16 -4
- package/lib/modules/Summary/index.js +71 -66
- package/lib/modules/Summary/types.js +16 -4
- package/lib/modules/Summary/utils.js +418 -791
- package/lib/modules/SurchargeList/index.js +60 -46
- package/lib/modules/SurchargeList/types.js +16 -4
- package/lib/modules/index.js +63 -245
- package/lib/plugins/app.js +16 -4
- package/lib/plugins/index.js +25 -36
- package/lib/plugins/request.js +126 -137
- package/lib/plugins/shopStore.js +16 -4
- package/lib/plugins/user.js +16 -4
- package/lib/plugins/window.js +179 -171
- package/lib/server/index.js +2337 -2675
- package/lib/server/modules/floor-plan/index.js +123 -102
- package/lib/server/modules/floor-plan/types.js +30 -15
- package/lib/server/modules/index.js +68 -106
- package/lib/server/modules/menu/index.js +122 -146
- package/lib/server/modules/menu/types.js +31 -18
- package/lib/server/modules/order/index.js +642 -567
- package/lib/server/modules/order/types.js +32 -117
- package/lib/server/modules/order/utils/filterBookings.js +194 -219
- package/lib/server/modules/order/utils/filterOrders.js +92 -118
- package/lib/server/modules/payment/index.js +83 -59
- package/lib/server/modules/payment/types.js +16 -4
- package/lib/server/modules/products/index.js +459 -575
- package/lib/server/modules/products/types.js +34 -44
- package/lib/server/modules/quotation/index.js +172 -137
- package/lib/server/modules/quotation/types.js +31 -21
- package/lib/server/modules/resource/index.js +184 -213
- package/lib/server/modules/resource/types.js +33 -42
- package/lib/server/modules/schedule/index.js +123 -135
- package/lib/server/modules/schedule/types.js +21 -14
- package/lib/server/modules/schedule/utils.js +163 -334
- package/lib/server/types.js +16 -4
- package/lib/server/utils/index.js +23 -25
- package/lib/server/utils/product.js +139 -196
- package/lib/server/utils/schedule.js +41 -34
- package/lib/server/utils/small-ticket.js +456 -478
- package/lib/server/utils/time.js +49 -40
- package/lib/solution/BaseSales/index.js +1016 -850
- package/lib/solution/BaseSales/types.js +37 -41
- package/lib/solution/BaseSales/utils/cartPromotion.js +460 -611
- package/lib/solution/BaseSales/utils/parseSalesResponse.js +105 -85
- package/lib/solution/BaseSales/utils/quotationPrice.js +114 -56
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +143 -102
- package/lib/solution/BaseSales/utils.js +140 -155
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/BookingByStep/index.js +1340 -1530
- package/lib/solution/BookingByStep/types.js +99 -40
- package/lib/solution/BookingByStep/utils/capacity.js +160 -192
- package/lib/solution/BookingByStep/utils/products.js +52 -42
- package/lib/solution/BookingByStep/utils/resources.js +330 -527
- package/lib/solution/BookingByStep/utils/stock.js +44 -65
- package/lib/solution/BookingByStep/utils/timeslots.js +131 -129
- package/lib/solution/BookingTicket/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.js +459 -543
- package/lib/solution/BookingTicket/types.js +77 -99
- package/lib/solution/BookingTicket/utils/addProductDecision.js +184 -219
- package/lib/solution/BookingTicket/utils/addTimeAvailability.js +89 -58
- package/lib/solution/BookingTicket/utils/bookingStatus.js +78 -107
- package/lib/solution/BookingTicket/utils/cartView.js +94 -110
- package/lib/solution/BookingTicket/utils/exampleData.js +0 -185
- package/lib/solution/BookingTicket/utils/orderCustomer.js +41 -18
- package/lib/solution/BookingTicket/utils/resolveBestAddTimePlan.js +86 -219
- package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.js +93 -144
- package/lib/solution/BookingTicket/utils/scan/cloudSearch.js +91 -79
- package/lib/solution/BookingTicket/utils/scan/formatGlobalScan.js +41 -54
- package/lib/solution/BookingTicket/utils/scan/handleScan.js +81 -84
- package/lib/solution/BookingTicket/utils/scan/index.js +104 -98
- package/lib/solution/BookingTicket/utils/scan/scanCache.js +43 -90
- package/lib/solution/BookingTicket/utils/scan/scanProductValues.js +64 -52
- package/lib/solution/BookingTicket/utils/sessionCatalogStale.js +58 -56
- package/lib/solution/BuyTickets/index.js +70 -67
- package/lib/solution/BuyTickets/types.js +38 -22
- package/lib/solution/Checkout/index.js +1158 -1451
- package/lib/solution/Checkout/types.js +61 -91
- package/lib/solution/Checkout/utils/index.js +156 -228
- package/lib/solution/PlaceOrder/index.js +0 -55
- package/lib/solution/RegisterAndLogin/config.js +460 -493
- package/lib/solution/RegisterAndLogin/index.js +630 -633
- package/lib/solution/RegisterAndLogin/types.js +76 -189
- package/lib/solution/RegisterAndLogin/utils.js +125 -183
- package/lib/solution/Sales/index.js +320 -317
- package/lib/solution/Sales/types.js +33 -27
- package/lib/solution/ScanOrder/index.js +862 -831
- package/lib/solution/ScanOrder/types.js +34 -33
- package/lib/solution/ScanOrder/utils.js +371 -406
- package/lib/solution/ShopDiscount/index.js +233 -235
- package/lib/solution/ShopDiscount/types.d.ts +4 -5
- package/lib/solution/ShopDiscount/types.js +37 -15
- package/lib/solution/ShopDiscount/utils.d.ts +0 -9
- package/lib/solution/ShopDiscount/utils.js +172 -309
- package/lib/solution/UnifiedBookingSales/index.js +405 -379
- package/lib/solution/UnifiedBookingSales/types.js +31 -12
- package/lib/solution/VenueBooking/index.d.ts +3 -31
- package/lib/solution/VenueBooking/index.js +916 -967
- package/lib/solution/VenueBooking/types.d.ts +1 -3
- package/lib/solution/VenueBooking/types.js +39 -20
- package/lib/solution/VenueBooking/utils/dateSummary.d.ts +2 -2
- package/lib/solution/VenueBooking/utils/dateSummary.js +62 -25
- package/lib/solution/VenueBooking/utils/resource.js +54 -31
- package/lib/solution/VenueBooking/utils/slotMerge.js +107 -94
- package/lib/solution/VenueBooking/utils/timeSlot.d.ts +0 -2
- package/lib/solution/VenueBooking/utils/timeSlot.js +133 -138
- package/lib/solution/VenueBooking/utils.js +67 -130
- package/lib/solution/index.js +41 -124
- package/lib/store/createStore.js +29 -32
- package/lib/types/index.d.ts +1 -1
- package/lib/types/index.js +16 -4
- package/lib/utils/task.js +36 -36
- package/lib/utils/watch.js +47 -81
- package/package.json +2 -4
- package/dist/solution/VenueBooking/utils/smartPricing.d.ts +0 -70
- package/dist/solution/VenueBooking/utils/smartPricing.js +0 -233
- package/lib/solution/VenueBooking/utils/smartPricing.d.ts +0 -70
- package/lib/solution/VenueBooking/utils/smartPricing.js +0 -192
|
@@ -1,32 +1,58 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
Object.
|
|
4
|
-
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
|
|
29
|
+
// src/modules/Rules/index.ts
|
|
30
|
+
var Rules_exports = {};
|
|
31
|
+
__export(Rules_exports, {
|
|
32
|
+
RulesModule: () => RulesModule
|
|
5
33
|
});
|
|
6
|
-
exports
|
|
7
|
-
var
|
|
8
|
-
var
|
|
9
|
-
var
|
|
10
|
-
var
|
|
11
|
-
var
|
|
12
|
-
var
|
|
13
|
-
var
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
defaultVersion = '1.0.0';
|
|
18
|
-
store;
|
|
19
|
-
window; // WindowPlugin 实例
|
|
20
|
-
hooks;
|
|
34
|
+
module.exports = __toCommonJS(Rules_exports);
|
|
35
|
+
var import_BaseModule = require("../BaseModule");
|
|
36
|
+
var import_types = require("./types");
|
|
37
|
+
var import_utils = require("../../solution/ShopDiscount/utils");
|
|
38
|
+
var import_utils2 = require("../Cart/utils");
|
|
39
|
+
var import_decimal = __toESM(require("decimal.js"));
|
|
40
|
+
var import_lodash_es = require("lodash-es");
|
|
41
|
+
var import_dayjs = __toESM(require("dayjs"));
|
|
42
|
+
var import_utils3 = require("../../solution/ShopDiscount/utils");
|
|
43
|
+
var import_utils4 = require("../../solution/ShopDiscount/utils");
|
|
44
|
+
var RulesModule = class extends import_BaseModule.BaseModule {
|
|
21
45
|
constructor(name, version) {
|
|
22
46
|
super(name, version);
|
|
47
|
+
this.defaultName = "rules";
|
|
48
|
+
this.defaultVersion = "1.0.0";
|
|
23
49
|
this.hooks = {};
|
|
24
50
|
}
|
|
25
51
|
async initialize(core, options) {
|
|
26
52
|
this.core = core;
|
|
27
|
-
this.hooks = options
|
|
28
|
-
this.store = options
|
|
29
|
-
this.window = core.getPlugin(
|
|
53
|
+
this.hooks = options == null ? void 0 : options.hooks;
|
|
54
|
+
this.store = options == null ? void 0 : options.store;
|
|
55
|
+
this.window = core.getPlugin("window");
|
|
30
56
|
}
|
|
31
57
|
async setRulesList(rulesList) {
|
|
32
58
|
this.store.rulesList = rulesList;
|
|
@@ -36,25 +62,22 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
36
62
|
return this.store.rulesList;
|
|
37
63
|
}
|
|
38
64
|
getWalletPassEvaluator() {
|
|
39
|
-
|
|
65
|
+
var _a, _b;
|
|
66
|
+
return (_b = (_a = this.window).getWalletPassEvaluator) == null ? void 0 : _b.call(_a);
|
|
40
67
|
}
|
|
41
|
-
|
|
42
68
|
// 商品不需要holder,则不需要判断,直接返回true,商品需要holder但是还没填写,那么暂时不使用带有holder的券,直到填写才去匹配
|
|
43
69
|
checkHolderMatch(discount, product, holders) {
|
|
44
|
-
|
|
45
|
-
if (discount.holder
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const orderHolderId = Array.isArray(holders) && holders.length > 0 ? holders[0].form_record_id || holders[0] : undefined;
|
|
70
|
+
var _a;
|
|
71
|
+
if (((_a = discount.holder) == null ? void 0 : _a.holder_type) !== "form")
|
|
72
|
+
return true;
|
|
73
|
+
const orderHolderId = Array.isArray(holders) && holders.length > 0 ? holders[0].form_record_id || holders[0] : void 0;
|
|
49
74
|
const productHolderId = Array.isArray(product.holder_id) ? product.holder_id[0] : product.holder_id;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
// 最终直接匹配 holder 是否相同
|
|
75
|
+
if (!product.isNeedHolder)
|
|
76
|
+
return true;
|
|
77
|
+
if (!orderHolderId && !productHolderId)
|
|
78
|
+
return false;
|
|
55
79
|
return (productHolderId || orderHolderId) === discount.holder.holder_id;
|
|
56
80
|
}
|
|
57
|
-
|
|
58
81
|
// 判断discountList 是否可以对当前productList生效
|
|
59
82
|
isDiscountListAvailable({
|
|
60
83
|
oldDiscountList,
|
|
@@ -64,7 +87,6 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
64
87
|
holders,
|
|
65
88
|
isFormSubject
|
|
66
89
|
}) {
|
|
67
|
-
// 首先检查是否有新的优惠券可应用
|
|
68
90
|
if (!newDiscountList || newDiscountList.length === 0) {
|
|
69
91
|
return {
|
|
70
92
|
isAvailable: false,
|
|
@@ -72,58 +94,57 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
72
94
|
productList
|
|
73
95
|
};
|
|
74
96
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if (productList.every(item => {
|
|
97
|
+
if (productList.every((item) => {
|
|
98
|
+
var _a;
|
|
78
99
|
const product = this.hooks.getProduct(item);
|
|
79
|
-
return product.booking_id && (product.discount_list
|
|
100
|
+
return product.booking_id && (((_a = product.discount_list) == null ? void 0 : _a.length) || product.total == 0);
|
|
80
101
|
})) {
|
|
81
102
|
return {
|
|
82
103
|
isAvailable: false,
|
|
83
104
|
discountList: oldDiscountList,
|
|
84
105
|
productList,
|
|
85
|
-
unavailableReason:
|
|
106
|
+
unavailableReason: import_types.UnavailableReason.AlreadyUsed
|
|
86
107
|
};
|
|
87
108
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
109
|
+
const filteredOldDiscountList = oldDiscountList.filter(
|
|
110
|
+
(discount) => !discount.isEditMode && (discount.tag !== "good_pass" || discount.isScan)
|
|
111
|
+
);
|
|
112
|
+
const mergedDiscountList = (0, import_utils.uniqueById)([
|
|
113
|
+
...filteredOldDiscountList,
|
|
114
|
+
...newDiscountList
|
|
115
|
+
]);
|
|
116
|
+
const result = this.calcDiscount(
|
|
117
|
+
{
|
|
118
|
+
discountList: mergedDiscountList,
|
|
119
|
+
productList: [...productList],
|
|
120
|
+
orderTotalAmount,
|
|
121
|
+
holders,
|
|
122
|
+
isFormSubject
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
scan: true
|
|
126
|
+
}
|
|
127
|
+
);
|
|
104
128
|
let hasApplicableDiscount = false;
|
|
105
|
-
const newDiscountIds = newDiscountList.map(discount => discount.id);
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
discount_list
|
|
111
|
-
bundle
|
|
112
|
-
} = this.hooks.getProduct(product);
|
|
113
|
-
const allDiscountList = [...(discount_list || [])];
|
|
114
|
-
(bundle || []).forEach(item => {
|
|
115
|
-
allDiscountList.push(...(item?.discount_list || []));
|
|
129
|
+
const newDiscountIds = newDiscountList.map((discount) => discount.id);
|
|
130
|
+
result.productList.forEach((product) => {
|
|
131
|
+
const { discount_list, bundle } = this.hooks.getProduct(product);
|
|
132
|
+
const allDiscountList = [...discount_list || []];
|
|
133
|
+
(bundle || []).forEach((item) => {
|
|
134
|
+
allDiscountList.push(...(item == null ? void 0 : item.discount_list) || []);
|
|
116
135
|
});
|
|
117
136
|
if (allDiscountList && allDiscountList.length > 0) {
|
|
118
|
-
|
|
119
|
-
|
|
137
|
+
const usedNewDiscount = allDiscountList.some(
|
|
138
|
+
(discount) => {
|
|
139
|
+
var _a;
|
|
140
|
+
return newDiscountIds.includes((_a = discount == null ? void 0 : discount.discount) == null ? void 0 : _a.resource_id);
|
|
141
|
+
}
|
|
142
|
+
);
|
|
120
143
|
if (usedNewDiscount) {
|
|
121
144
|
hasApplicableDiscount = true;
|
|
122
145
|
}
|
|
123
146
|
}
|
|
124
147
|
});
|
|
125
|
-
|
|
126
|
-
// 如果券不可用,判断不可用原因
|
|
127
148
|
let unavailableReason;
|
|
128
149
|
if (!hasApplicableDiscount) {
|
|
129
150
|
unavailableReason = this.getUnavailableReason(newDiscountList, productList);
|
|
@@ -136,51 +157,47 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
136
157
|
};
|
|
137
158
|
}
|
|
138
159
|
filterDiscountListByType(discountList, type) {
|
|
139
|
-
return (discountList || []).filter(item => item.type === type || item.tag === type);
|
|
160
|
+
return (discountList || []).filter((item) => item.type === type || item.tag === type);
|
|
140
161
|
}
|
|
141
|
-
|
|
142
162
|
/** 剔除指定 type/tag 的折扣项,保留手动改价(type=product) / 券等 */
|
|
143
163
|
excludeDiscountListByType(discountList, type) {
|
|
144
|
-
return (discountList || []).filter(item => item.type !== type && item.tag !== type);
|
|
164
|
+
return (discountList || []).filter((item) => item.type !== type && item.tag !== type);
|
|
145
165
|
}
|
|
146
|
-
|
|
147
166
|
/** 手动改价场景:去掉 promotion,保留 type=product 等行内折扣 */
|
|
148
167
|
resolveDiscountListForManualOverride(discountList) {
|
|
149
|
-
return this.excludeDiscountListByType(discountList,
|
|
168
|
+
return this.excludeDiscountListByType(discountList, "promotion");
|
|
150
169
|
}
|
|
151
170
|
// 获取券不可用的原因
|
|
152
171
|
getUnavailableReason(discountList, productList) {
|
|
153
|
-
|
|
172
|
+
var _a;
|
|
154
173
|
for (const discount of discountList) {
|
|
155
174
|
for (const item of productList) {
|
|
156
175
|
const product = this.hooks.getProduct(item);
|
|
157
|
-
const bookingTime = (product
|
|
158
|
-
const filteredList = (0,
|
|
176
|
+
const bookingTime = ((product == null ? void 0 : product.startDate) || (0, import_dayjs.default)()).format("YYYY-MM-DD HH:mm:ss");
|
|
177
|
+
const filteredList = (0, import_utils.filterDiscountListByBookingTime)([discount], bookingTime);
|
|
159
178
|
if (filteredList.length === 0) {
|
|
160
|
-
return
|
|
179
|
+
return import_types.UnavailableReason.TimeLimit;
|
|
161
180
|
}
|
|
162
181
|
}
|
|
163
182
|
}
|
|
164
|
-
|
|
165
|
-
// 检查商品适用性
|
|
166
183
|
for (const discount of discountList) {
|
|
167
184
|
const limitedData = discount.limited_relation_product_data;
|
|
168
185
|
let hasApplicableProduct = false;
|
|
169
186
|
for (const item of productList) {
|
|
170
187
|
const product = this.hooks.getProduct(item);
|
|
171
|
-
if (limitedData.type ===
|
|
188
|
+
if (limitedData.type === "product_all") {
|
|
172
189
|
hasApplicableProduct = true;
|
|
173
190
|
break;
|
|
174
|
-
} else if (limitedData.product_ids
|
|
191
|
+
} else if ((_a = limitedData.product_ids) == null ? void 0 : _a.includes(product.id)) {
|
|
175
192
|
hasApplicableProduct = true;
|
|
176
193
|
break;
|
|
177
194
|
}
|
|
178
195
|
}
|
|
179
196
|
if (!hasApplicableProduct) {
|
|
180
|
-
return
|
|
197
|
+
return import_types.UnavailableReason.ProductNotApplicable;
|
|
181
198
|
}
|
|
182
199
|
}
|
|
183
|
-
return
|
|
200
|
+
return import_types.UnavailableReason.Unknown;
|
|
184
201
|
}
|
|
185
202
|
calcDiscount({
|
|
186
203
|
discountList,
|
|
@@ -189,84 +206,83 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
189
206
|
isFormSubject,
|
|
190
207
|
orderTotalAmount
|
|
191
208
|
}, options) {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
const getOriginProductUid = originProduct => {
|
|
199
|
-
|
|
200
|
-
|
|
209
|
+
var _a;
|
|
210
|
+
const resolveIsFormSubject = (product) => typeof isFormSubject === "function" ? Boolean(isFormSubject(product)) : Boolean(isFormSubject);
|
|
211
|
+
const isEditModeAddNewProduct = productList.find((n) => n.booking_id) && productList.find((n) => !n.booking_id);
|
|
212
|
+
const reapplyBookingDiscountProductUids = new Set(
|
|
213
|
+
((options == null ? void 0 : options.reapplyBookingDiscountProductUids) || []).filter((uid) => uid !== void 0 && uid !== null && uid !== "").map(String)
|
|
214
|
+
);
|
|
215
|
+
const getOriginProductUid = (originProduct) => {
|
|
216
|
+
var _a2;
|
|
217
|
+
const uid = ((_a2 = originProduct == null ? void 0 : originProduct.metadata) == null ? void 0 : _a2.unique_identification_number) ?? (originProduct == null ? void 0 : originProduct.unique_identification_number);
|
|
218
|
+
if (uid === void 0 || uid === null || uid === "")
|
|
219
|
+
return void 0;
|
|
201
220
|
return String(uid);
|
|
202
221
|
};
|
|
203
222
|
const shouldReapplyBookingDiscount = (originProduct, selectedDiscount) => {
|
|
204
|
-
if (!selectedDiscount)
|
|
223
|
+
if (!selectedDiscount)
|
|
224
|
+
return false;
|
|
205
225
|
const uid = getOriginProductUid(originProduct);
|
|
206
|
-
if (!uid || !reapplyBookingDiscountProductUids.has(uid))
|
|
226
|
+
if (!uid || !reapplyBookingDiscountProductUids.has(uid))
|
|
227
|
+
return false;
|
|
207
228
|
const discountType = selectedDiscount.tag || selectedDiscount.type;
|
|
208
|
-
return selectedDiscount.isEditMode === true && selectedDiscount.isSelected === true && [
|
|
229
|
+
return selectedDiscount.isEditMode === true && selectedDiscount.isSelected === true && ["good_pass", "discount_card", "product_discount_card"].includes(discountType);
|
|
209
230
|
};
|
|
210
231
|
const resolveReapplyEditModeDiscountPercent = (originProduct, selectedDiscount) => {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
232
|
+
var _a2;
|
|
233
|
+
if (!shouldReapplyBookingDiscount(originProduct, selectedDiscount))
|
|
234
|
+
return void 0;
|
|
235
|
+
const discountType = (selectedDiscount == null ? void 0 : selectedDiscount.tag) || (selectedDiscount == null ? void 0 : selectedDiscount.type);
|
|
236
|
+
if (discountType !== "discount_card" && discountType !== "product_discount_card") {
|
|
237
|
+
return void 0;
|
|
215
238
|
}
|
|
216
|
-
const percent = Number(selectedDiscount.discount
|
|
217
|
-
return Number.isFinite(percent) ? percent :
|
|
239
|
+
const percent = Number((_a2 = selectedDiscount.discount) == null ? void 0 : _a2.percent);
|
|
240
|
+
return Number.isFinite(percent) ? percent : void 0;
|
|
218
241
|
};
|
|
219
242
|
const editModeDiscount = [];
|
|
220
243
|
const addModeDiscount = [];
|
|
221
|
-
discountList.forEach(discount => {
|
|
244
|
+
discountList.forEach((discount) => {
|
|
222
245
|
if (discount.isEditMode) {
|
|
223
246
|
editModeDiscount.push(discount);
|
|
224
247
|
} else {
|
|
225
248
|
addModeDiscount.push(discount);
|
|
226
249
|
}
|
|
227
250
|
});
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
editModeOrderLevelProductIds.add(discount?.discount?.discount_product_id);
|
|
251
|
+
const editModeOrderLevelProductIds = /* @__PURE__ */ new Set();
|
|
252
|
+
editModeDiscount.forEach((discount) => {
|
|
253
|
+
var _a2, _b;
|
|
254
|
+
if (((_a2 = discount.discount) == null ? void 0 : _a2.discount_calculation_mode) === "order_level") {
|
|
255
|
+
editModeOrderLevelProductIds.add((_b = discount == null ? void 0 : discount.discount) == null ? void 0 : _b.discount_product_id);
|
|
234
256
|
}
|
|
235
257
|
});
|
|
236
|
-
|
|
237
|
-
// 如果存在订单级别的编辑模式折扣,禁用 addModeDiscount 中相同 product_id 的折扣卡
|
|
238
258
|
if (editModeOrderLevelProductIds.size > 0) {
|
|
239
|
-
addModeDiscount.forEach(discount => {
|
|
259
|
+
addModeDiscount.forEach((discount) => {
|
|
240
260
|
if (editModeOrderLevelProductIds.has(discount.product_id)) {
|
|
241
261
|
discount.isDisabled = true;
|
|
242
262
|
}
|
|
243
263
|
});
|
|
244
264
|
}
|
|
245
|
-
const hasDiscountInput = editModeDiscount.length > 0 || addModeDiscount.length > 0 || Boolean(options
|
|
265
|
+
const hasDiscountInput = editModeDiscount.length > 0 || addModeDiscount.length > 0 || Boolean(options == null ? void 0 : options.discountId) || Boolean((_a = options == null ? void 0 : options.selectedList) == null ? void 0 : _a.length) || Boolean(options == null ? void 0 : options.scan);
|
|
246
266
|
if (!hasDiscountInput) {
|
|
247
267
|
return {
|
|
248
268
|
discountList,
|
|
249
269
|
productList
|
|
250
270
|
};
|
|
251
271
|
}
|
|
252
|
-
const canUseEditModeDiscountForReapply = discount => {
|
|
272
|
+
const canUseEditModeDiscountForReapply = (discount) => {
|
|
253
273
|
const discountType = discount.tag || discount.type;
|
|
254
|
-
return reapplyBookingDiscountProductUids.size > 0 && discount.isEditMode === true && discount.isSelected === true && [
|
|
274
|
+
return reapplyBookingDiscountProductUids.size > 0 && discount.isEditMode === true && discount.isSelected === true && ["good_pass", "discount_card", "product_discount_card"].includes(discountType);
|
|
255
275
|
};
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
// 🔥 扁平化商品列表:将 bundle 子商品展开为虚拟商品
|
|
262
|
-
const flattenProductsWithBundle = productList => {
|
|
276
|
+
const filteredDiscountList = [
|
|
277
|
+
...addModeDiscount.filter((discount) => !discount.isManualSelect),
|
|
278
|
+
...editModeDiscount.filter(canUseEditModeDiscountForReapply)
|
|
279
|
+
];
|
|
280
|
+
const flattenProductsWithBundle = (productList2) => {
|
|
263
281
|
const flattened = [];
|
|
264
|
-
|
|
282
|
+
productList2.forEach((originProduct) => {
|
|
265
283
|
const product = this.hooks.getProduct(originProduct);
|
|
266
|
-
|
|
267
|
-
// 1. 添加主商品
|
|
268
284
|
flattened.push({
|
|
269
|
-
type:
|
|
285
|
+
type: "main",
|
|
270
286
|
originProduct,
|
|
271
287
|
product,
|
|
272
288
|
price: Number(product.price || 0),
|
|
@@ -277,12 +293,10 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
277
293
|
num: product.num,
|
|
278
294
|
booking_id: product.booking_id
|
|
279
295
|
});
|
|
280
|
-
|
|
281
|
-
// 2. 展开 bundle 子商品
|
|
282
296
|
if (product.bundle && Array.isArray(product.bundle) && product.bundle.length > 0) {
|
|
283
297
|
product.bundle.forEach((bundleItem, bundleIndex) => {
|
|
284
298
|
flattened.push({
|
|
285
|
-
type:
|
|
299
|
+
type: "bundle",
|
|
286
300
|
originProduct,
|
|
287
301
|
parentProduct: product,
|
|
288
302
|
bundleItem,
|
|
@@ -295,8 +309,8 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
295
309
|
parentId: product._id,
|
|
296
310
|
num: bundleItem.num || 1,
|
|
297
311
|
quantity: bundleItem.num || 1,
|
|
298
|
-
total: new
|
|
299
|
-
origin_total: new
|
|
312
|
+
total: new import_decimal.default(bundleItem.price || 0).mul(bundleItem.num || 1).toNumber(),
|
|
313
|
+
origin_total: new import_decimal.default(bundleItem.price || 0).mul(bundleItem.num || 1).toNumber(),
|
|
300
314
|
original_price: bundleItem.original_price,
|
|
301
315
|
// 继承主商品属性
|
|
302
316
|
booking_id: bundleItem.booking_id,
|
|
@@ -307,157 +321,120 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
307
321
|
});
|
|
308
322
|
return flattened;
|
|
309
323
|
};
|
|
310
|
-
|
|
311
|
-
// 优惠力度排序,传进来的数据里可能有商品券,也可能有优惠券
|
|
312
|
-
// 新的优先级排序规则(从高到低):
|
|
313
|
-
// 1. 带有Holder的商品券(metadata?.holder?.type === 'custom' && tag === 'good_pass')
|
|
314
|
-
// 2. 带有Holder的商品级折扣卡(metadata?.holder?.type === 'custom' && tag === 'product_discount_card' && discount_calculation_mode !== 'order_level')
|
|
315
|
-
// 3. 带有Holder的订单级折扣卡(metadata?.holder?.type === 'custom' && tag === 'product_discount_card' && discount_calculation_mode === 'order_level')
|
|
316
|
-
// 4. Customer商品券(metadata?.holder?.type !== 'custom' && tag === 'good_pass')
|
|
317
|
-
// 5. Customer商品级折扣卡(metadata?.holder?.type !== 'custom' && tag === 'product_discount_card' && discount_calculation_mode !== 'order_level')
|
|
318
|
-
// 6. Customer订单级固定金额折扣(metadata?.holder?.type !== 'custom' && tag === 'product_discount_card' && discount_calculation_mode === 'order_level')
|
|
319
|
-
// 同一优先级内部:固定金额优先于百分比,金额/折扣力度越大越优先,最后按过期时间排序
|
|
320
324
|
const sortedDiscountList = [...filteredDiscountList].sort((a, b) => {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
const isGoodPass = discount => discount.tag ===
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
const getPriority = discount => {
|
|
325
|
+
const isHolderDiscount = (discount) => {
|
|
326
|
+
var _a2, _b;
|
|
327
|
+
return ((_b = (_a2 = discount.metadata) == null ? void 0 : _a2.holder) == null ? void 0 : _b.type) === "custom";
|
|
328
|
+
};
|
|
329
|
+
const isGoodPass = (discount) => discount.tag === "good_pass";
|
|
330
|
+
const isOrderLevelDiscount = (discount) => {
|
|
331
|
+
var _a2;
|
|
332
|
+
return discount.tag === "product_discount_card" && ((_a2 = discount.metadata) == null ? void 0 : _a2.discount_calculation_mode) === "order_level";
|
|
333
|
+
};
|
|
334
|
+
const isItemLevelDiscount = (discount) => {
|
|
335
|
+
var _a2;
|
|
336
|
+
return discount.tag === "product_discount_card" && ((_a2 = discount.metadata) == null ? void 0 : _a2.discount_calculation_mode) !== "order_level";
|
|
337
|
+
};
|
|
338
|
+
const getPriority = (discount) => {
|
|
335
339
|
const isHolder = isHolderDiscount(discount);
|
|
336
340
|
if (isHolder) {
|
|
337
|
-
if (isGoodPass(discount))
|
|
338
|
-
|
|
339
|
-
if (
|
|
341
|
+
if (isGoodPass(discount))
|
|
342
|
+
return 1;
|
|
343
|
+
if (isItemLevelDiscount(discount))
|
|
344
|
+
return 2;
|
|
345
|
+
if (isOrderLevelDiscount(discount))
|
|
346
|
+
return 3;
|
|
340
347
|
} else {
|
|
341
|
-
if (isGoodPass(discount))
|
|
342
|
-
|
|
343
|
-
if (
|
|
348
|
+
if (isGoodPass(discount))
|
|
349
|
+
return 4;
|
|
350
|
+
if (isItemLevelDiscount(discount))
|
|
351
|
+
return 5;
|
|
352
|
+
if (isOrderLevelDiscount(discount))
|
|
353
|
+
return 6;
|
|
344
354
|
}
|
|
345
|
-
return 7;
|
|
355
|
+
return 7;
|
|
346
356
|
};
|
|
347
|
-
|
|
348
|
-
// 辅助函数:按过期时间比较
|
|
349
357
|
function compareByExpireTime(itemA, itemB) {
|
|
350
358
|
if (itemA.expire_time && itemB.expire_time) {
|
|
351
359
|
const timeA = new Date(itemA.expire_time).getTime();
|
|
352
360
|
const timeB = new Date(itemB.expire_time).getTime();
|
|
353
361
|
return timeA - timeB;
|
|
354
362
|
}
|
|
355
|
-
// 有过期时间的优先级高于永久的
|
|
356
363
|
return itemA.expire_time ? -1 : itemB.expire_time ? 1 : 0;
|
|
357
364
|
}
|
|
358
|
-
|
|
359
|
-
// 辅助函数:同类型折扣卡内部排序(固定金额优先于百分比,金额/折扣力度排序)
|
|
360
365
|
function compareDiscountCardValue(itemA, itemB) {
|
|
361
|
-
|
|
362
|
-
const
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
if (typeA ===
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
if (typeA === 'fixed_amount' && typeB === 'fixed_amount') {
|
|
366
|
+
var _a2, _b;
|
|
367
|
+
const typeA = ((_a2 = itemA.metadata) == null ? void 0 : _a2.discount_card_type) || "percent";
|
|
368
|
+
const typeB = ((_b = itemB.metadata) == null ? void 0 : _b.discount_card_type) || "percent";
|
|
369
|
+
if (typeA === "fixed_amount" && typeB === "percent")
|
|
370
|
+
return -1;
|
|
371
|
+
if (typeA === "percent" && typeB === "fixed_amount")
|
|
372
|
+
return 1;
|
|
373
|
+
if (typeA === "fixed_amount" && typeB === "fixed_amount") {
|
|
370
374
|
if (itemA.par_value !== itemB.par_value) {
|
|
371
|
-
const valueA = new
|
|
372
|
-
const valueB = new
|
|
373
|
-
return valueB.minus(valueA).toNumber();
|
|
375
|
+
const valueA = new import_decimal.default(itemA.par_value || 0);
|
|
376
|
+
const valueB = new import_decimal.default(itemB.par_value || 0);
|
|
377
|
+
return valueB.minus(valueA).toNumber();
|
|
374
378
|
}
|
|
375
379
|
}
|
|
376
|
-
|
|
377
|
-
// 3. 都是百分比时,折扣越大越优先(par_value越大越优先)
|
|
378
|
-
if (typeA === 'percent' && typeB === 'percent') {
|
|
380
|
+
if (typeA === "percent" && typeB === "percent") {
|
|
379
381
|
if (itemA.par_value !== itemB.par_value) {
|
|
380
|
-
const valueA = new
|
|
381
|
-
const valueB = new
|
|
382
|
-
return valueA.minus(valueB).toNumber();
|
|
382
|
+
const valueA = new import_decimal.default(100).minus(itemA.par_value || 0);
|
|
383
|
+
const valueB = new import_decimal.default(100).minus(itemB.par_value || 0);
|
|
384
|
+
return valueA.minus(valueB).toNumber();
|
|
383
385
|
}
|
|
384
386
|
}
|
|
385
387
|
return 0;
|
|
386
388
|
}
|
|
387
|
-
|
|
388
|
-
// 1. 先按优先级排序
|
|
389
389
|
const priorityA = getPriority(a);
|
|
390
390
|
const priorityB = getPriority(b);
|
|
391
391
|
if (priorityA !== priorityB) {
|
|
392
392
|
return priorityA - priorityB;
|
|
393
393
|
}
|
|
394
|
-
|
|
395
|
-
// 2. 同一优先级内部排序
|
|
396
|
-
// 如果是商品券(优先级1或4),按过期时间排序
|
|
397
394
|
if (isGoodPass(a) && isGoodPass(b)) {
|
|
398
395
|
return compareByExpireTime(a, b);
|
|
399
396
|
}
|
|
400
|
-
|
|
401
|
-
// 如果是折扣卡(优先级2、3、5、6),按折扣力度排序,然后按过期时间
|
|
402
|
-
if (a.tag === 'product_discount_card' && b.tag === 'product_discount_card') {
|
|
397
|
+
if (a.tag === "product_discount_card" && b.tag === "product_discount_card") {
|
|
403
398
|
const valueCompare = compareDiscountCardValue(a, b);
|
|
404
|
-
if (valueCompare !== 0)
|
|
399
|
+
if (valueCompare !== 0)
|
|
400
|
+
return valueCompare;
|
|
405
401
|
return compareByExpireTime(a, b);
|
|
406
402
|
}
|
|
407
|
-
|
|
408
|
-
// 3. 其他情况按照过期时间排序
|
|
409
403
|
return compareByExpireTime(a, b);
|
|
410
404
|
});
|
|
411
|
-
|
|
412
|
-
// const newProductList = [];
|
|
413
|
-
//
|
|
414
|
-
// productList.forEach(item => {
|
|
415
|
-
// const product = this.hooks.getProduct(item);
|
|
416
|
-
// if (product.quantity > 1) {
|
|
417
|
-
// for (let i = 1; i < product.quantity; i++) {
|
|
418
|
-
// newProductList.push(product)
|
|
419
|
-
// }
|
|
420
|
-
// } else {
|
|
421
|
-
// newProductList.push(item)
|
|
422
|
-
// }
|
|
423
|
-
// })
|
|
424
|
-
|
|
425
|
-
// 🔥 扁平化商品列表(包含主商品和bundle子商品)
|
|
426
405
|
const flattenedList = flattenProductsWithBundle(productList);
|
|
427
|
-
|
|
428
|
-
// 对扁平化后的列表按价格降序排序(用于应用优惠券时优先选择高价商品)
|
|
429
406
|
const sortedFlattenedList = flattenedList.sort((a, b) => {
|
|
430
|
-
|
|
431
|
-
const priceA = new
|
|
432
|
-
|
|
407
|
+
var _a2, _b;
|
|
408
|
+
const priceA = new import_decimal.default(
|
|
409
|
+
a.type === "bundle" ? a.original_price ?? a.price ?? "0" : a.price || "0"
|
|
410
|
+
);
|
|
411
|
+
const priceB = new import_decimal.default(
|
|
412
|
+
b.type === "bundle" ? b.original_price ?? b.price ?? "0" : b.price || "0"
|
|
413
|
+
);
|
|
433
414
|
if (priceA.equals(priceB)) {
|
|
434
|
-
// 价格相同时,主商品优先
|
|
435
415
|
if (a.type !== b.type) {
|
|
436
|
-
return a.type ===
|
|
416
|
+
return a.type === "main" ? -1 : 1;
|
|
437
417
|
}
|
|
438
|
-
|
|
439
|
-
if (a.type === 'main' && b.type === 'main') {
|
|
418
|
+
if (a.type === "main" && b.type === "main") {
|
|
440
419
|
if (a.product.quantity === b.product.quantity) {
|
|
441
|
-
return (b.product.discount_list
|
|
420
|
+
return (((_a2 = b.product.discount_list) == null ? void 0 : _a2.length) || 0) - (((_b = a.product.discount_list) == null ? void 0 : _b.length) || 0);
|
|
442
421
|
}
|
|
443
422
|
return a.product.quantity - b.product.quantity;
|
|
444
423
|
}
|
|
445
|
-
|
|
446
|
-
if (a.type === 'bundle' && b.type === 'bundle') {
|
|
424
|
+
if (a.type === "bundle" && b.type === "bundle") {
|
|
447
425
|
return (a.num || 1) - (b.num || 1);
|
|
448
426
|
}
|
|
449
427
|
}
|
|
450
428
|
return priceB.minus(priceA).toNumber();
|
|
451
429
|
});
|
|
452
|
-
|
|
453
|
-
// 🔥 为每个折扣卡/商品券执行策略检查并附加config
|
|
454
430
|
const evaluator = this.getWalletPassEvaluator();
|
|
455
431
|
if (evaluator) {
|
|
456
|
-
addModeDiscount.forEach(discount => {
|
|
432
|
+
addModeDiscount.forEach((discount) => {
|
|
433
|
+
var _a2, _b;
|
|
457
434
|
const discountType = discount.tag || discount.type;
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
435
|
+
if (["good_pass", "discount_card", "product_discount_card"].includes(
|
|
436
|
+
discountType
|
|
437
|
+
)) {
|
|
461
438
|
const voucher = {
|
|
462
439
|
id: discount.id,
|
|
463
440
|
amount: Number(discount.par_value || 0),
|
|
@@ -465,27 +442,24 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
465
442
|
type: discountType,
|
|
466
443
|
product_id: discount.product_id,
|
|
467
444
|
unified_available_status: 1,
|
|
468
|
-
available_product_type: discount.limited_relation_product_data
|
|
469
|
-
available_product_ids: discount.limited_relation_product_data
|
|
445
|
+
available_product_type: (_a2 = discount.limited_relation_product_data) == null ? void 0 : _a2.type,
|
|
446
|
+
available_product_ids: (_b = discount.limited_relation_product_data) == null ? void 0 : _b.product_ids
|
|
470
447
|
};
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
// 调用策略检查
|
|
448
|
+
const productsForEvaluate = sortedFlattenedList.map((item) => {
|
|
449
|
+
var _a3;
|
|
450
|
+
return {
|
|
451
|
+
product_id: item.id,
|
|
452
|
+
price: item.price || 0,
|
|
453
|
+
quantity: item.quantity || item.num || 1,
|
|
454
|
+
selling_price: item.price || 0,
|
|
455
|
+
product_options: item.type === "main" ? (_a3 = item.product) == null ? void 0 : _a3.options : void 0
|
|
456
|
+
};
|
|
457
|
+
});
|
|
482
458
|
const result = evaluator.checkVoucherAvailability({
|
|
483
|
-
orderTotalAmount
|
|
459
|
+
orderTotalAmount,
|
|
484
460
|
products: productsForEvaluate,
|
|
485
461
|
vouchers: [voucher]
|
|
486
462
|
});
|
|
487
|
-
|
|
488
|
-
// 将 config 附加到 discount 对象
|
|
489
463
|
if (result.isAvailable) {
|
|
490
464
|
discount.config = {
|
|
491
465
|
...result.config,
|
|
@@ -499,74 +473,21 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
499
473
|
}
|
|
500
474
|
});
|
|
501
475
|
}
|
|
502
|
-
|
|
503
|
-
const
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
};
|
|
508
|
-
|
|
509
|
-
/**
|
|
510
|
-
// 对productList按价格降序排序(用于应用优惠券时优先选择高价商品) 价格相同时使用quantity 排序
|
|
511
|
-
const sortedProductList = [...productList].sort((a, b) => {
|
|
512
|
-
const aProduct = this.hooks.getProduct(a);
|
|
513
|
-
const bProduct = this.hooks.getProduct(b);
|
|
514
|
-
const priceA = new Decimal((aProduct.price as string) || '0');
|
|
515
|
-
const priceB = new Decimal((bProduct.price as string) || '0');
|
|
516
|
-
if (priceA.toNumber() === priceB.toNumber()) {
|
|
517
|
-
if (aProduct.quantity === bProduct.quantity) {
|
|
518
|
-
return bProduct.discount_list?.length - aProduct.discount_list?.length;
|
|
519
|
-
}
|
|
520
|
-
return aProduct.quantity - bProduct.quantity;
|
|
521
|
-
}
|
|
522
|
-
return priceB.toNumber() - priceA.toNumber();
|
|
523
|
-
});
|
|
524
|
-
*/
|
|
525
|
-
|
|
526
|
-
// 标记已使用的优惠券
|
|
527
|
-
const usedDiscounts = new Map();
|
|
528
|
-
|
|
529
|
-
// 🔥 统计每个 product_id(商品券商品id)已使用的数量,用于 maxUsagePerOrder 限制
|
|
530
|
-
const usedProductIdCounts = new Map();
|
|
531
|
-
|
|
532
|
-
// 🔥 统计每张折扣卡的 applicableProductLimit 已使用次数(跨商品全局计数)
|
|
533
|
-
const usedDiscountCardLimitCounts = new Map();
|
|
534
|
-
|
|
535
|
-
// 🔥 预先将 editModeDiscount 中的折扣卡计入 applicableProductLimit 已使用次数
|
|
536
|
-
editModeDiscount.forEach(discount => {
|
|
537
|
-
const discountType = discount.tag || discount.type;
|
|
538
|
-
if (['discount_card', 'product_discount_card'].includes(discountType)) {
|
|
539
|
-
const currentCount = usedDiscountCardLimitCounts.get(discount.id) || 0;
|
|
540
|
-
usedDiscountCardLimitCounts.set(discount.id, currentCount + (discount.metadata?.num || 1));
|
|
541
|
-
}
|
|
542
|
-
});
|
|
543
|
-
|
|
544
|
-
// 记录每个优惠券适用的商品ID
|
|
545
|
-
const discountApplicability = new Map();
|
|
546
|
-
|
|
547
|
-
// 记录每个优惠券适用的商品详细信息
|
|
548
|
-
const discountApplicableProducts = new Map();
|
|
549
|
-
|
|
550
|
-
// 初始化每个优惠券的适用性和可抵扣商品
|
|
551
|
-
addModeDiscount.forEach(discount => {
|
|
476
|
+
const usedDiscounts = /* @__PURE__ */ new Map();
|
|
477
|
+
const usedProductIdCounts = /* @__PURE__ */ new Map();
|
|
478
|
+
const discountApplicability = /* @__PURE__ */ new Map();
|
|
479
|
+
const discountApplicableProducts = /* @__PURE__ */ new Map();
|
|
480
|
+
addModeDiscount.forEach((discount) => {
|
|
552
481
|
discountApplicability.set(discount.id, []);
|
|
553
482
|
discountApplicableProducts.set(discount.id, []);
|
|
554
483
|
});
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
const orderLevelDiscountAllocations = new Map();
|
|
559
|
-
|
|
560
|
-
// 第一步:收集所有被勾选的 order_level 折扣卡及其适用商品
|
|
561
|
-
// Map<discountId, Set<flatItemId>> - 记录每个折扣卡适用的商品
|
|
562
|
-
const orderLevelDiscountApplicableItems = new Map();
|
|
563
|
-
// Map<flatItemId, Set<discountId>> - 记录每个商品可以被哪些折扣卡使用
|
|
564
|
-
const itemApplicableDiscounts = new Map();
|
|
565
|
-
|
|
566
|
-
// 辅助函数:检查商品是否对某个折扣卡可用
|
|
484
|
+
const orderLevelDiscountAllocations = /* @__PURE__ */ new Map();
|
|
485
|
+
const orderLevelDiscountApplicableItems = /* @__PURE__ */ new Map();
|
|
486
|
+
const itemApplicableDiscounts = /* @__PURE__ */ new Map();
|
|
567
487
|
const checkItemApplicableForDiscount = (flatItem, discount) => {
|
|
488
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h;
|
|
568
489
|
let product;
|
|
569
|
-
if (flatItem.type ===
|
|
490
|
+
if (flatItem.type === "main") {
|
|
570
491
|
product = flatItem.product;
|
|
571
492
|
} else {
|
|
572
493
|
product = {
|
|
@@ -577,38 +498,27 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
577
498
|
num: flatItem.num,
|
|
578
499
|
booking_id: flatItem.booking_id,
|
|
579
500
|
discount_list: flatItem.discount_list || [],
|
|
580
|
-
startDate: flatItem.parentProduct
|
|
501
|
+
startDate: (_a2 = flatItem.parentProduct) == null ? void 0 : _a2.startDate
|
|
581
502
|
};
|
|
582
503
|
}
|
|
583
|
-
|
|
584
|
-
// 编辑的商品使用了优惠券不可用
|
|
585
|
-
const isAvailableProduct = flatItem.type === 'main' ? !(product?.booking_id && product?.discount_list?.length && product?.discount_list?.every(d => d.id && ['good_pass', 'discount_card', 'product_discount_card'].includes(d.tag || d.type))) : !(flatItem?.booking_id && !!flatItem?.bundleItem?.discount_list?.length && flatItem?.bundleItem?.discount_list?.every(d => d.id));
|
|
504
|
+
const isAvailableProduct = flatItem.type === "main" ? !((product == null ? void 0 : product.booking_id) && ((_b = product == null ? void 0 : product.discount_list) == null ? void 0 : _b.length) && ((_c = product == null ? void 0 : product.discount_list) == null ? void 0 : _c.every((d) => d.id && ["good_pass", "discount_card", "product_discount_card"].includes(d.tag || d.type)))) : !((flatItem == null ? void 0 : flatItem.booking_id) && !!((_e = (_d = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _d.discount_list) == null ? void 0 : _e.length) && ((_g = (_f = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _f.discount_list) == null ? void 0 : _g.every((d) => d.id)));
|
|
586
505
|
if (!isAvailableProduct) {
|
|
587
506
|
return false;
|
|
588
507
|
}
|
|
589
|
-
|
|
590
|
-
// vouchersApplicable 为 false 的商品不参与订单级别折扣均摊
|
|
591
|
-
if ((0, _lodashEs.isBoolean)(product.vouchersApplicable) && !product.vouchersApplicable) {
|
|
508
|
+
if ((0, import_lodash_es.isBoolean)(product.vouchersApplicable) && !product.vouchersApplicable) {
|
|
592
509
|
return false;
|
|
593
510
|
}
|
|
594
|
-
|
|
595
|
-
// 商品价格为0时不可用
|
|
596
511
|
if (Number(product.price) <= 0 || !product.price) {
|
|
597
512
|
return false;
|
|
598
513
|
}
|
|
599
514
|
const limitedData = discount.limited_relation_product_data;
|
|
600
|
-
|
|
601
|
-
// 时间限制检查
|
|
602
|
-
const timeLimit = !!(0, _utils.filterDiscountListByBookingTime)([discount], (product?.startDate || (0, _dayjs.default)()).format('YYYY-MM-DD HH:mm:ss')).length;
|
|
515
|
+
const timeLimit = !!(0, import_utils.filterDiscountListByBookingTime)([discount], ((product == null ? void 0 : product.startDate) || (0, import_dayjs.default)()).format("YYYY-MM-DD HH:mm:ss")).length;
|
|
603
516
|
if (!timeLimit) {
|
|
604
517
|
return false;
|
|
605
518
|
}
|
|
606
|
-
|
|
607
|
-
// 判断商品是否适用
|
|
608
519
|
let isLimitedProduct = false;
|
|
609
|
-
if (limitedData.type ===
|
|
610
|
-
|
|
611
|
-
if (limitedData.filter === 1 && limitedData.exclude_product_ids?.includes(product.id)) {
|
|
520
|
+
if (limitedData.type === "product_all") {
|
|
521
|
+
if (limitedData.filter === 1 && ((_h = limitedData.exclude_product_ids) == null ? void 0 : _h.includes(product.id))) {
|
|
612
522
|
isLimitedProduct = false;
|
|
613
523
|
} else {
|
|
614
524
|
isLimitedProduct = true;
|
|
@@ -616,51 +526,33 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
616
526
|
} else if (limitedData.product_ids && limitedData.product_ids.includes(product.id)) {
|
|
617
527
|
isLimitedProduct = true;
|
|
618
528
|
}
|
|
619
|
-
|
|
620
|
-
// 套餐规则检查
|
|
621
529
|
const isBundleAvailable = this.checkPackageSubItemUsageRules(discount, flatItem);
|
|
622
530
|
return isLimitedProduct && isBundleAvailable;
|
|
623
531
|
};
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
const selectedOrderLevelDiscounts = sortedDiscountList.filter(discount => {
|
|
627
|
-
return (0, _utils.isOrderLevelFixedAmountDiscount)(discount) && discount.isSelected !== false;
|
|
532
|
+
const selectedOrderLevelDiscounts = sortedDiscountList.filter((discount) => {
|
|
533
|
+
return (0, import_utils3.isOrderLevelFixedAmountDiscount)(discount) && discount.isSelected !== false;
|
|
628
534
|
});
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
const applicableItemIds = new Set();
|
|
633
|
-
sortedFlattenedList.forEach(flatItem => {
|
|
535
|
+
selectedOrderLevelDiscounts.forEach((discount) => {
|
|
536
|
+
const applicableItemIds = /* @__PURE__ */ new Set();
|
|
537
|
+
sortedFlattenedList.forEach((flatItem) => {
|
|
634
538
|
if (checkItemApplicableForDiscount(flatItem, discount)) {
|
|
635
539
|
applicableItemIds.add(flatItem._id);
|
|
636
|
-
|
|
637
|
-
// 记录商品可以被哪些折扣卡使用
|
|
638
540
|
if (!itemApplicableDiscounts.has(flatItem._id)) {
|
|
639
|
-
itemApplicableDiscounts.set(flatItem._id, new Set());
|
|
541
|
+
itemApplicableDiscounts.set(flatItem._id, /* @__PURE__ */ new Set());
|
|
640
542
|
}
|
|
641
543
|
itemApplicableDiscounts.get(flatItem._id).add(discount.id);
|
|
642
544
|
}
|
|
643
545
|
});
|
|
644
546
|
orderLevelDiscountApplicableItems.set(discount.id, applicableItemIds);
|
|
645
547
|
});
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
// 如果专属折扣卡被勾选,它适用的商品会被占用,其他折扣卡均摊时应排除这些商品
|
|
649
|
-
// Map<flatItemId, discountId> - 记录被占用的商品及其对应的折扣卡
|
|
650
|
-
const occupiedItems = new Map();
|
|
651
|
-
|
|
652
|
-
// 按排序顺序遍历折扣卡,判断哪些是专属折扣卡
|
|
653
|
-
selectedOrderLevelDiscounts.forEach(discount => {
|
|
548
|
+
const occupiedItems = /* @__PURE__ */ new Map();
|
|
549
|
+
selectedOrderLevelDiscounts.forEach((discount) => {
|
|
654
550
|
const limitedData = discount.limited_relation_product_data;
|
|
655
|
-
|
|
656
|
-
// 判断是否是专属折扣卡(只能用于特定商品,而不是全品类)
|
|
657
|
-
const isExclusiveDiscount = limitedData.type !== 'product_all';
|
|
551
|
+
const isExclusiveDiscount = limitedData.type !== "product_all";
|
|
658
552
|
if (isExclusiveDiscount) {
|
|
659
|
-
// 专属折扣卡:它适用的所有商品都会被它占用
|
|
660
553
|
const applicableItems = orderLevelDiscountApplicableItems.get(discount.id);
|
|
661
554
|
if (applicableItems) {
|
|
662
|
-
applicableItems.forEach(itemId => {
|
|
663
|
-
// 如果商品还没被占用,则标记为被当前折扣卡占用
|
|
555
|
+
applicableItems.forEach((itemId) => {
|
|
664
556
|
if (!occupiedItems.has(itemId)) {
|
|
665
557
|
occupiedItems.set(itemId, discount.id);
|
|
666
558
|
}
|
|
@@ -668,27 +560,22 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
668
560
|
}
|
|
669
561
|
}
|
|
670
562
|
});
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
sortedDiscountList.forEach(discount => {
|
|
674
|
-
if (!(0, _utils.isOrderLevelFixedAmountDiscount)(discount)) {
|
|
563
|
+
sortedDiscountList.forEach((discount) => {
|
|
564
|
+
if (!(0, import_utils3.isOrderLevelFixedAmountDiscount)(discount)) {
|
|
675
565
|
return;
|
|
676
566
|
}
|
|
677
|
-
|
|
678
|
-
// 收集该折扣卡适用的商品(排除被其他专属折扣卡占用的商品)
|
|
679
567
|
const applicableProducts = [];
|
|
680
|
-
sortedFlattenedList.forEach(flatItem => {
|
|
681
|
-
|
|
568
|
+
sortedFlattenedList.forEach((flatItem) => {
|
|
569
|
+
var _a2, _b, _c;
|
|
682
570
|
const occupyingDiscountId = occupiedItems.get(flatItem._id);
|
|
683
|
-
if (occupyingDiscountId !==
|
|
684
|
-
// 该商品被其他专属折扣卡占用,跳过
|
|
571
|
+
if (occupyingDiscountId !== void 0 && occupyingDiscountId !== discount.id) {
|
|
685
572
|
return;
|
|
686
573
|
}
|
|
687
574
|
if (!checkItemApplicableForDiscount(flatItem, discount)) {
|
|
688
575
|
return;
|
|
689
576
|
}
|
|
690
577
|
let product;
|
|
691
|
-
if (flatItem.type ===
|
|
578
|
+
if (flatItem.type === "main") {
|
|
692
579
|
product = flatItem.product;
|
|
693
580
|
} else {
|
|
694
581
|
product = {
|
|
@@ -699,53 +586,33 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
699
586
|
num: flatItem.num
|
|
700
587
|
};
|
|
701
588
|
}
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
const quantity = flatItem.type === 'main' ? product.num || product.quantity || 1 : (product.num || product.quantity || 1) * (flatItem.parentProduct?.num || flatItem.parentProduct?.quantity || 1);
|
|
705
|
-
|
|
706
|
-
// 对于主商品:使用 price
|
|
707
|
-
// 对于子商品:优先使用 flatItem.original_price,否则使用 flatItem.price
|
|
708
|
-
const originalAmount = flatItem.type === 'main' ? Number(product.price ?? 0) : Number(flatItem.original_price ?? flatItem.price ?? 0);
|
|
709
|
-
|
|
710
|
-
// 传递 parentQuantity 用于差值处理时判断是否是真正的"数量为1"
|
|
589
|
+
const quantity = flatItem.type === "main" ? product.num || product.quantity || 1 : (product.num || product.quantity || 1) * (((_a2 = flatItem.parentProduct) == null ? void 0 : _a2.num) || ((_b = flatItem.parentProduct) == null ? void 0 : _b.quantity) || 1);
|
|
590
|
+
const originalAmount = flatItem.type === "main" ? Number(product.price ?? 0) : Number(flatItem.original_price ?? flatItem.price ?? 0);
|
|
711
591
|
const productData = {
|
|
712
592
|
productId: flatItem._id,
|
|
713
593
|
amount: originalAmount,
|
|
714
|
-
quantity
|
|
594
|
+
quantity
|
|
715
595
|
};
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
if (flatItem.type === 'bundle') {
|
|
719
|
-
productData.parentQuantity = flatItem.parentProduct?.quantity || 1;
|
|
596
|
+
if (flatItem.type === "bundle") {
|
|
597
|
+
productData.parentQuantity = ((_c = flatItem.parentProduct) == null ? void 0 : _c.quantity) || 1;
|
|
720
598
|
}
|
|
721
599
|
applicableProducts.push(productData);
|
|
722
600
|
});
|
|
723
|
-
|
|
724
|
-
// 计算分摊
|
|
725
601
|
if (applicableProducts.length > 0) {
|
|
726
|
-
const allocation = (0,
|
|
602
|
+
const allocation = (0, import_utils4.calculateOrderLevelDiscountAllocation)(discount, applicableProducts);
|
|
727
603
|
orderLevelDiscountAllocations.set(discount.id, allocation);
|
|
728
604
|
}
|
|
729
605
|
});
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
// 记录已应用优惠券的商品信息
|
|
735
|
-
const appliedDiscountProducts = new Map();
|
|
736
|
-
|
|
737
|
-
// 首先遍历所有商品和所有优惠券,确定每个优惠券的适用范围,包括isSelected为false的优惠券
|
|
738
|
-
// 🔥 使用扁平化后的列表,包含主商品和bundle子商品
|
|
739
|
-
sortedFlattenedList.forEach(flatItem => {
|
|
740
|
-
// 获取商品数据
|
|
606
|
+
const processedProductsMap = /* @__PURE__ */ new Map();
|
|
607
|
+
const appliedDiscountProducts = /* @__PURE__ */ new Map();
|
|
608
|
+
sortedFlattenedList.forEach((flatItem) => {
|
|
609
|
+
var _a2;
|
|
741
610
|
let product, originProduct;
|
|
742
|
-
if (flatItem.type ===
|
|
611
|
+
if (flatItem.type === "main") {
|
|
743
612
|
product = flatItem.product;
|
|
744
613
|
originProduct = flatItem.originProduct;
|
|
745
614
|
} else {
|
|
746
|
-
// bundle子商品:构造虚拟商品对象
|
|
747
615
|
product = {
|
|
748
|
-
startDate: flatItem?.parentProduct?.startDate,
|
|
749
616
|
_id: flatItem._id,
|
|
750
617
|
id: flatItem.id,
|
|
751
618
|
price: flatItem.price,
|
|
@@ -754,49 +621,48 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
754
621
|
total: flatItem.total,
|
|
755
622
|
origin_total: flatItem.origin_total,
|
|
756
623
|
booking_id: flatItem.booking_id,
|
|
757
|
-
discount_list: flatItem.discount_list || []
|
|
624
|
+
discount_list: flatItem.discount_list || [],
|
|
625
|
+
startDate: (_a2 = flatItem.parentProduct) == null ? void 0 : _a2.startDate
|
|
758
626
|
};
|
|
759
627
|
originProduct = flatItem.originProduct;
|
|
760
628
|
}
|
|
761
|
-
addModeDiscount.forEach(discount => {
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
const _tempVar = flatItem
|
|
765
|
-
const isHolderMatch = this.checkHolderMatch(
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
629
|
+
addModeDiscount.forEach((discount) => {
|
|
630
|
+
var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
631
|
+
const limitedData = discount == null ? void 0 : discount.limited_relation_product_data;
|
|
632
|
+
const _tempVar = (flatItem == null ? void 0 : flatItem.type) === "bundle" ? flatItem == null ? void 0 : flatItem.parentProduct : flatItem == null ? void 0 : flatItem.product;
|
|
633
|
+
const isHolderMatch = this.checkHolderMatch(
|
|
634
|
+
discount,
|
|
635
|
+
{
|
|
636
|
+
isNeedHolder: resolveIsFormSubject(_tempVar) && !(_tempVar == null ? void 0 : _tempVar.isNormalProduct),
|
|
637
|
+
holder_id: (_tempVar == null ? void 0 : _tempVar.holder_id) || product.holder_id
|
|
638
|
+
},
|
|
639
|
+
holders
|
|
640
|
+
);
|
|
769
641
|
let timeLimit = true;
|
|
770
|
-
timeLimit = !!(0,
|
|
771
|
-
|
|
772
|
-
const
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
642
|
+
timeLimit = !!(0, import_utils.filterDiscountListByBookingTime)([discount], ((product == null ? void 0 : product.startDate) || (0, import_dayjs.default)()).format("YYYY-MM-DD HH:mm:ss")).length;
|
|
643
|
+
const isLimitedProduct = (limitedData.type === "product_all" && limitedData.filter !== 1 || limitedData.type === "product_all" && limitedData.filter === 1 && !limitedData.exclude_product_ids.includes(product.id) || limitedData.product_ids && limitedData.product_ids.includes(product.id)) && isHolderMatch;
|
|
644
|
+
const isAvailableProduct = flatItem.type === "main" ? !((product == null ? void 0 : product.booking_id) && ((_a3 = product == null ? void 0 : product.discount_list) == null ? void 0 : _a3.length) && ((_b = product == null ? void 0 : product.discount_list) == null ? void 0 : _b.every(
|
|
645
|
+
(discount2) => discount2.id && [
|
|
646
|
+
"good_pass",
|
|
647
|
+
"discount_card",
|
|
648
|
+
"product_discount_card"
|
|
649
|
+
].includes(discount2.tag || discount2.type)
|
|
650
|
+
))) : !((flatItem == null ? void 0 : flatItem.booking_id) && !!((_d = (_c = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _c.discount_list) == null ? void 0 : _d.length) && ((_f = (_e = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _e.discount_list) == null ? void 0 : _f.every((discount2) => discount2.id)));
|
|
778
651
|
const isBundleAvailable = this.checkPackageSubItemUsageRules(discount, flatItem);
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
if (isAvailableProduct && isLimitedProduct && timeLimit && isBundleAvailable && discount.config?.isAvailable) {
|
|
782
|
-
// 记录此优惠券适用的商品
|
|
783
|
-
discountApplicability.get(discount.id)?.push(product.id);
|
|
784
|
-
|
|
785
|
-
// 记录可抵扣的商品详情
|
|
652
|
+
if (isAvailableProduct && isLimitedProduct && timeLimit && isBundleAvailable && ((_g = discount.config) == null ? void 0 : _g.isAvailable)) {
|
|
653
|
+
(_h = discountApplicability.get(discount.id)) == null ? void 0 : _h.push(product.id);
|
|
786
654
|
const applicableProducts = discountApplicableProducts.get(discount.id) || [];
|
|
787
655
|
const discountType = discount.tag || discount.type;
|
|
788
|
-
const isGoodPass = discountType ===
|
|
789
|
-
|
|
790
|
-
// 使用数量
|
|
791
|
-
const num = isGoodPass || flatItem?.type === 'main' ? 1 : product.num;
|
|
656
|
+
const isGoodPass = discountType === "good_pass";
|
|
657
|
+
const num = isGoodPass || (flatItem == null ? void 0 : flatItem.type) === "main" ? 1 : product.num;
|
|
792
658
|
const productData = {
|
|
793
659
|
amount: product.price * num,
|
|
794
660
|
type: discountType,
|
|
795
661
|
tag: discountType,
|
|
796
662
|
discount: {
|
|
797
|
-
discount_card_type: discount
|
|
663
|
+
discount_card_type: (_i = discount == null ? void 0 : discount.metadata) == null ? void 0 : _i.discount_card_type,
|
|
798
664
|
fixed_amount: product.price,
|
|
799
|
-
discount_calculation_mode: discount
|
|
665
|
+
discount_calculation_mode: (_j = discount == null ? void 0 : discount.metadata) == null ? void 0 : _j.discount_calculation_mode,
|
|
800
666
|
resource_id: discount.id,
|
|
801
667
|
title: discount.format_title,
|
|
802
668
|
original_amount: product.price || product.origin_total,
|
|
@@ -805,8 +671,8 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
805
671
|
discount_product_id: discount.product_id
|
|
806
672
|
},
|
|
807
673
|
metadata: {
|
|
808
|
-
num
|
|
809
|
-
discount_rule_uncheck_flag: discount
|
|
674
|
+
num,
|
|
675
|
+
discount_rule_uncheck_flag: discount == null ? void 0 : discount.discount_rule_uncheck_flag
|
|
810
676
|
}
|
|
811
677
|
};
|
|
812
678
|
applicableProducts.push(productData);
|
|
@@ -814,145 +680,128 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
814
680
|
}
|
|
815
681
|
});
|
|
816
682
|
});
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
// 🔥 Option 折扣辅助函数
|
|
822
|
-
const applyDiscountToOptions = (options, discount) => {
|
|
823
|
-
if (!options?.length) return {
|
|
824
|
-
discountedOptions: options,
|
|
825
|
-
optionDiscountAmount: 0
|
|
826
|
-
};
|
|
683
|
+
const processedFlatItemsMap = /* @__PURE__ */ new Map();
|
|
684
|
+
const applyDiscountToOptions = (options2, discount) => {
|
|
685
|
+
if (!(options2 == null ? void 0 : options2.length))
|
|
686
|
+
return { discountedOptions: options2, optionDiscountAmount: 0 };
|
|
827
687
|
let optionDiscountAmount = 0;
|
|
828
|
-
const discountedOptions =
|
|
829
|
-
// 折前单价:优先 price,缺失再 add_price;已写回折后价时用 _original_price(或旧字段 _original_add_price)
|
|
688
|
+
const discountedOptions = options2.map((option) => {
|
|
830
689
|
const rawUnit = option._original_price ?? option._original_add_price ?? option.price ?? option.add_price;
|
|
831
690
|
const baseUnitNum = Number(rawUnit ?? 0);
|
|
832
|
-
if (baseUnitNum <= 0)
|
|
833
|
-
|
|
691
|
+
if (baseUnitNum <= 0)
|
|
692
|
+
return option;
|
|
693
|
+
const discountedPrice = (0, import_utils.getDiscountAmount)(discount, baseUnitNum, baseUnitNum);
|
|
834
694
|
const optQty = Number(option.num ?? option.quantity ?? 1);
|
|
835
|
-
optionDiscountAmount = new
|
|
836
|
-
const {
|
|
837
|
-
_original_add_price,
|
|
838
|
-
...rest
|
|
839
|
-
} = option;
|
|
695
|
+
optionDiscountAmount = new import_decimal.default(optionDiscountAmount).plus(new import_decimal.default(baseUnitNum).minus(discountedPrice).mul(optQty)).toNumber();
|
|
696
|
+
const { _original_add_price, ...rest } = option;
|
|
840
697
|
const tmpl = rest.price ?? rest.add_price;
|
|
841
|
-
const nextPrice = typeof tmpl ===
|
|
698
|
+
const nextPrice = typeof tmpl === "string" ? String(discountedPrice) : discountedPrice;
|
|
842
699
|
return {
|
|
843
700
|
...rest,
|
|
844
|
-
_original_price: option._original_price ?? (_original_add_price !==
|
|
701
|
+
_original_price: option._original_price ?? (_original_add_price !== void 0 ? _original_add_price : rawUnit),
|
|
845
702
|
price: nextPrice
|
|
846
703
|
};
|
|
847
704
|
});
|
|
848
|
-
return {
|
|
849
|
-
discountedOptions,
|
|
850
|
-
optionDiscountAmount
|
|
851
|
-
};
|
|
705
|
+
return { discountedOptions, optionDiscountAmount };
|
|
852
706
|
};
|
|
853
|
-
const restoreOptionPrices =
|
|
854
|
-
if (!
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
...rest
|
|
862
|
-
} = option;
|
|
863
|
-
return {
|
|
864
|
-
...rest,
|
|
865
|
-
price: orig
|
|
866
|
-
};
|
|
707
|
+
const restoreOptionPrices = (options2) => {
|
|
708
|
+
if (!(options2 == null ? void 0 : options2.length))
|
|
709
|
+
return options2;
|
|
710
|
+
return options2.map((option) => {
|
|
711
|
+
const orig = option._original_price !== void 0 ? option._original_price : option._original_add_price;
|
|
712
|
+
if (orig !== void 0) {
|
|
713
|
+
const { _original_price, _original_add_price, ...rest } = option;
|
|
714
|
+
return { ...rest, price: orig };
|
|
867
715
|
}
|
|
868
716
|
return option;
|
|
869
717
|
});
|
|
870
718
|
};
|
|
871
|
-
const getOptionTotal =
|
|
872
|
-
if (!
|
|
873
|
-
|
|
719
|
+
const getOptionTotal = (options2) => {
|
|
720
|
+
if (!(options2 == null ? void 0 : options2.length))
|
|
721
|
+
return 0;
|
|
722
|
+
return options2.reduce((sum, opt) => {
|
|
874
723
|
const unit = Number(opt.price ?? opt.add_price ?? 0);
|
|
875
724
|
const n = Number(opt.num ?? opt.quantity ?? 1);
|
|
876
|
-
return new
|
|
725
|
+
return new import_decimal.default(sum).plus(new import_decimal.default(unit).mul(n)).toNumber();
|
|
877
726
|
}, 0);
|
|
878
727
|
};
|
|
879
|
-
|
|
880
|
-
// 然后再处理应用哪些优惠券,此时只考虑filteredDiscountList中的优惠券
|
|
881
|
-
// 🔥 使用扁平化后的列表进行处理
|
|
882
728
|
sortedFlattenedList.forEach((flatItem, index) => {
|
|
883
|
-
|
|
729
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I;
|
|
884
730
|
let product, originProduct;
|
|
885
|
-
if (flatItem.type ===
|
|
731
|
+
if (flatItem.type === "main") {
|
|
886
732
|
product = flatItem.product;
|
|
887
733
|
originProduct = flatItem.originProduct;
|
|
888
734
|
} else {
|
|
889
|
-
// bundle子商品
|
|
890
735
|
product = {
|
|
891
|
-
startDate: flatItem?.parentProduct?.startDate,
|
|
892
736
|
_id: flatItem._id,
|
|
893
737
|
id: flatItem.id,
|
|
894
738
|
price: flatItem.price,
|
|
895
739
|
quantity: flatItem.quantity,
|
|
896
740
|
num: flatItem.num,
|
|
897
741
|
total: flatItem.total,
|
|
898
|
-
original_price: flatItem
|
|
899
|
-
origin_total: flatItem
|
|
742
|
+
original_price: (_a2 = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _a2.original_price,
|
|
743
|
+
origin_total: (_b = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _b.original_price,
|
|
900
744
|
booking_id: flatItem.booking_id,
|
|
901
|
-
discount_list: flatItem
|
|
745
|
+
discount_list: ((_c = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _c.discount_list) || [],
|
|
746
|
+
startDate: (_d = flatItem.parentProduct) == null ? void 0 : _d.startDate
|
|
902
747
|
};
|
|
903
748
|
originProduct = flatItem.originProduct;
|
|
904
749
|
}
|
|
905
|
-
const isPersistedProduct = product
|
|
906
|
-
const hasExistingWalletDiscount = product.discount_list
|
|
907
|
-
|
|
750
|
+
const isPersistedProduct = (product == null ? void 0 : product.booking_id) || (originProduct == null ? void 0 : originProduct.order_detail_id) || (originProduct == null ? void 0 : originProduct.orderDetailId) || (originProduct == null ? void 0 : originProduct.booking_id);
|
|
751
|
+
const hasExistingWalletDiscount = ((_e = product.discount_list) == null ? void 0 : _e.length) && ((_f = product == null ? void 0 : product.discount_list) == null ? void 0 : _f.every((discount) => {
|
|
752
|
+
var _a3;
|
|
753
|
+
const discountIdentity = discount.id ?? ((_a3 = discount.discount) == null ? void 0 : _a3.resource_id);
|
|
908
754
|
const discountType = discount.tag || discount.type;
|
|
909
|
-
return Boolean(
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
755
|
+
return Boolean(
|
|
756
|
+
discountIdentity && ["good_pass", "discount_card", "product_discount_card"].includes(
|
|
757
|
+
discountType
|
|
758
|
+
)
|
|
759
|
+
);
|
|
760
|
+
}));
|
|
913
761
|
if (isPersistedProduct && hasExistingWalletDiscount) {
|
|
914
|
-
if (flatItem.type ===
|
|
762
|
+
if (flatItem.type === "main") {
|
|
915
763
|
processedProductsMap.set(product._id, [originProduct]);
|
|
916
764
|
} else {
|
|
917
|
-
processedFlatItemsMap.set(flatItem._id, [
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
765
|
+
processedFlatItemsMap.set(flatItem._id, [
|
|
766
|
+
{
|
|
767
|
+
...flatItem,
|
|
768
|
+
processed: true
|
|
769
|
+
}
|
|
770
|
+
]);
|
|
921
771
|
}
|
|
922
772
|
return;
|
|
923
773
|
}
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
const applicableDiscounts = sortedDiscountList.filter(discount => {
|
|
927
|
-
// 🔥 检查策略可用性(针对 good_pass 和折扣卡)
|
|
774
|
+
const applicableDiscounts = sortedDiscountList.filter((discount) => {
|
|
775
|
+
var _a3, _b2, _c2, _d2;
|
|
928
776
|
const discountType = discount.tag || discount.type;
|
|
929
777
|
const currentOriginUid = getOriginProductUid(originProduct);
|
|
930
778
|
const isReapplyEditModeDiscountForProduct = discount.isEditMode && reapplyBookingDiscountProductUids.size > 0 && currentOriginUid && reapplyBookingDiscountProductUids.has(String(currentOriginUid)) && discount.isSelected === true;
|
|
931
779
|
if (discount.isEditMode && reapplyBookingDiscountProductUids.size > 0) {
|
|
932
780
|
const uid = currentOriginUid;
|
|
933
|
-
if (!uid || !reapplyBookingDiscountProductUids.has(uid))
|
|
934
|
-
|
|
781
|
+
if (!uid || !reapplyBookingDiscountProductUids.has(uid))
|
|
782
|
+
return false;
|
|
783
|
+
if (!discount.isSelected)
|
|
784
|
+
return false;
|
|
935
785
|
}
|
|
936
|
-
if ([
|
|
937
|
-
|
|
938
|
-
|
|
786
|
+
if (["good_pass", "discount_card", "product_discount_card"].includes(
|
|
787
|
+
discountType
|
|
788
|
+
) && !isReapplyEditModeDiscountForProduct) {
|
|
789
|
+
if (discount.config === void 0 || !((_a3 = discount == null ? void 0 : discount.config) == null ? void 0 : _a3.isAvailable)) {
|
|
939
790
|
return false;
|
|
940
791
|
}
|
|
941
792
|
}
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
// 如果优惠券已被使用,则跳过
|
|
793
|
+
if ((Number(product.price) <= 0 || !product.price) && !((_b2 = product.discount_list) == null ? void 0 : _b2.length) && (discount.tag || discount.type) === "good_pass")
|
|
794
|
+
return false;
|
|
795
|
+
if ((Number(product.price) <= 0 || !product.price) && !((_c2 = product.discount_list) == null ? void 0 : _c2.find((n) => {
|
|
796
|
+
var _a4;
|
|
797
|
+
return ((_a4 = n.discount) == null ? void 0 : _a4.resource_id) === discount.id;
|
|
798
|
+
})) && (discount.tag || discount.type) !== "good_pass")
|
|
799
|
+
return false;
|
|
950
800
|
const targetUsedDiscounts = usedDiscounts.get(discount.id);
|
|
951
|
-
if (targetUsedDiscounts && (discount.tag || discount.type) ===
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
const maxUsagePerOrder = discount.config?.maxUsagePerOrder;
|
|
801
|
+
if (targetUsedDiscounts && (discount.tag || discount.type) === "good_pass")
|
|
802
|
+
return false;
|
|
803
|
+
if ((discount.tag || discount.type) === "good_pass") {
|
|
804
|
+
const maxUsagePerOrder = (_d2 = discount.config) == null ? void 0 : _d2.maxUsagePerOrder;
|
|
956
805
|
if (maxUsagePerOrder && maxUsagePerOrder > 0) {
|
|
957
806
|
const currentUsedCount = usedProductIdCounts.get(discount.product_id) || 0;
|
|
958
807
|
if (currentUsedCount >= maxUsagePerOrder) {
|
|
@@ -960,47 +809,32 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
960
809
|
}
|
|
961
810
|
}
|
|
962
811
|
}
|
|
963
|
-
|
|
964
|
-
// 🔥 检查折扣卡的 applicableProductLimit 限制:折扣卡可使用的最大次数(跨商品全局)
|
|
965
|
-
const discountTypeForLimit = discount.tag || discount.type;
|
|
966
|
-
if (['discount_card', 'product_discount_card'].includes(discountTypeForLimit)) {
|
|
967
|
-
const applicableProductLimitConfig = discount.config?.applicableProductLimit || 0;
|
|
968
|
-
if (applicableProductLimitConfig > 0) {
|
|
969
|
-
const currentUsedLimitCount = usedDiscountCardLimitCounts.get(discount.id) || 0;
|
|
970
|
-
if (currentUsedLimitCount >= applicableProductLimitConfig) {
|
|
971
|
-
return false;
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
}
|
|
975
812
|
const limitedData = discount.limited_relation_product_data;
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
813
|
+
const _tempVar = (flatItem == null ? void 0 : flatItem.type) === "bundle" ? flatItem == null ? void 0 : flatItem.parentProduct : flatItem == null ? void 0 : flatItem.product;
|
|
814
|
+
const isHolderMatch = this.checkHolderMatch(
|
|
815
|
+
discount,
|
|
816
|
+
{
|
|
817
|
+
isNeedHolder: resolveIsFormSubject(_tempVar) && !(_tempVar == null ? void 0 : _tempVar.isNormalProduct),
|
|
818
|
+
holder_id: (_tempVar == null ? void 0 : _tempVar.holder_id) || product.holder_id
|
|
819
|
+
},
|
|
820
|
+
holders
|
|
821
|
+
);
|
|
822
|
+
if (!isHolderMatch)
|
|
823
|
+
return false;
|
|
985
824
|
let timeLimit = true;
|
|
986
|
-
timeLimit = !!(0,
|
|
825
|
+
timeLimit = !!(0, import_utils.filterDiscountListByBookingTime)([discount], (product.startDate || (0, import_dayjs.default)()).format("YYYY-MM-DD HH:mm:ss")).length;
|
|
987
826
|
if (!timeLimit) {
|
|
988
827
|
return false;
|
|
989
828
|
}
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
if (limitedData.type === 'product_all') {
|
|
993
|
-
if (!isProductIncludedByLimitedData(limitedData, product.id)) {
|
|
829
|
+
if (limitedData.type === "product_all") {
|
|
830
|
+
if (limitedData.filter === 1 && limitedData.exclude_product_ids.includes(product.id)) {
|
|
994
831
|
return false;
|
|
995
832
|
}
|
|
996
|
-
|
|
997
|
-
// 检查 package_sub_item_usage_rules
|
|
998
833
|
if (!this.checkPackageSubItemUsageRules(discount, flatItem)) {
|
|
999
834
|
return false;
|
|
1000
835
|
}
|
|
1001
836
|
return true;
|
|
1002
837
|
} else if (limitedData.product_ids && limitedData.product_ids.includes(product.id)) {
|
|
1003
|
-
// 检查 package_sub_item_usage_rules
|
|
1004
838
|
if (!this.checkPackageSubItemUsageRules(discount, flatItem)) {
|
|
1005
839
|
return false;
|
|
1006
840
|
}
|
|
@@ -1008,109 +842,158 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
1008
842
|
}
|
|
1009
843
|
return false;
|
|
1010
844
|
});
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
// 用于处理:先手动扫描了一张折扣卡,扫描完以后带入客户信息,但是之前那张折扣卡不是最优惠的情况
|
|
1015
|
-
const selectedDiscountCard = applicableDiscounts.find(n => n.isScan && n.isSelected && (n.tag || n.type) !== 'good_pass');
|
|
845
|
+
const selectedDiscountCard = applicableDiscounts.find(
|
|
846
|
+
(n) => n.isScan && n.isSelected && (n.tag || n.type) !== "good_pass"
|
|
847
|
+
);
|
|
1016
848
|
const selectedDiscount = selectedDiscountCard || applicableDiscounts[0];
|
|
1017
|
-
|
|
1018
|
-
// 如果是手动折扣,则不适用优惠券
|
|
1019
849
|
let isManualDiscount = false;
|
|
1020
|
-
if (flatItem.type ===
|
|
1021
|
-
|
|
1022
|
-
|
|
850
|
+
if (flatItem.type === "main") {
|
|
851
|
+
isManualDiscount = typeof product.isManualDiscount === "boolean" ? product.isManualDiscount : ((_g = product.discount_list) == null ? void 0 : _g.some((item) => item.type === "product")) || product.total != product.origin_total && (product.bundle || []).every(
|
|
852
|
+
(item) => {
|
|
853
|
+
var _a3;
|
|
854
|
+
return !((_a3 = item.discount_list || []) == null ? void 0 : _a3.length);
|
|
855
|
+
}
|
|
856
|
+
) && (!((_h = product.discount_list) == null ? void 0 : _h.length) || ((_j = (_i = product == null ? void 0 : product.discount_list) == null ? void 0 : _i.every) == null ? void 0 : _j.call(
|
|
857
|
+
_i,
|
|
858
|
+
(item) => item.type === "product"
|
|
859
|
+
)));
|
|
1023
860
|
if (product.inPromotion) {
|
|
1024
861
|
isManualDiscount = false;
|
|
1025
862
|
}
|
|
1026
863
|
} else {
|
|
1027
|
-
// bundle子商品:判断父主商品是否手动折扣
|
|
1028
864
|
const parentProduct = flatItem.parentProduct;
|
|
1029
865
|
if (parentProduct) {
|
|
1030
|
-
isManualDiscount = typeof parentProduct.isManualDiscount ===
|
|
866
|
+
isManualDiscount = typeof parentProduct.isManualDiscount === "boolean" ? parentProduct.isManualDiscount : ((_k = parentProduct.discount_list) == null ? void 0 : _k.some((item) => item.type === "product")) || parentProduct.total != parentProduct.origin_total && (parentProduct.bundle || []).every(
|
|
867
|
+
(item) => {
|
|
868
|
+
var _a3;
|
|
869
|
+
return !((_a3 = item.discount_list || []) == null ? void 0 : _a3.length);
|
|
870
|
+
}
|
|
871
|
+
) && (!((_l = parentProduct.discount_list) == null ? void 0 : _l.length) || ((_n = (_m = parentProduct == null ? void 0 : parentProduct.discount_list) == null ? void 0 : _m.every) == null ? void 0 : _n.call(
|
|
872
|
+
_m,
|
|
873
|
+
(item) => item.type === "product"
|
|
874
|
+
)));
|
|
1031
875
|
}
|
|
1032
876
|
}
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
877
|
+
if (options == null ? void 0 : options.discountId) {
|
|
878
|
+
if (flatItem.type === "main" && ((_o = product.discount_list) == null ? void 0 : _o.some(
|
|
879
|
+
(item) => {
|
|
880
|
+
var _a3;
|
|
881
|
+
return ((_a3 = item.discount) == null ? void 0 : _a3.resource_id) === options.discountId;
|
|
882
|
+
}
|
|
883
|
+
))) {
|
|
1038
884
|
isManualDiscount = false;
|
|
1039
885
|
}
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
886
|
+
if (flatItem.type === "bundle") {
|
|
887
|
+
if (((_p = product.discount_list) == null ? void 0 : _p.some(
|
|
888
|
+
(item) => {
|
|
889
|
+
var _a3;
|
|
890
|
+
return ((_a3 = item.discount) == null ? void 0 : _a3.resource_id) === options.discountId;
|
|
891
|
+
}
|
|
892
|
+
)) || ((_r = (_q = flatItem.parentProduct) == null ? void 0 : _q.discount_list) == null ? void 0 : _r.some(
|
|
893
|
+
(item) => {
|
|
894
|
+
var _a3;
|
|
895
|
+
return ((_a3 = item.discount) == null ? void 0 : _a3.resource_id) === options.discountId;
|
|
896
|
+
}
|
|
897
|
+
))) {
|
|
1043
898
|
isManualDiscount = false;
|
|
1044
899
|
}
|
|
1045
900
|
}
|
|
1046
901
|
}
|
|
1047
|
-
if (options
|
|
1048
|
-
|
|
1049
|
-
|
|
902
|
+
if (options == null ? void 0 : options.selectedList) {
|
|
903
|
+
if (flatItem.type === "main" && ((_s = product.discount_list) == null ? void 0 : _s.some(
|
|
904
|
+
(item) => {
|
|
905
|
+
var _a3;
|
|
906
|
+
return (_a3 = options == null ? void 0 : options.selectedList) == null ? void 0 : _a3.some(
|
|
907
|
+
(n) => {
|
|
908
|
+
var _a4;
|
|
909
|
+
return n.discountId === ((_a4 = item.discount) == null ? void 0 : _a4.resource_id);
|
|
910
|
+
}
|
|
911
|
+
);
|
|
912
|
+
}
|
|
913
|
+
))) {
|
|
1050
914
|
isManualDiscount = false;
|
|
1051
915
|
}
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
916
|
+
if (flatItem.type === "bundle") {
|
|
917
|
+
if (((_t = product.discount_list) == null ? void 0 : _t.some(
|
|
918
|
+
(item) => {
|
|
919
|
+
var _a3;
|
|
920
|
+
return (_a3 = options == null ? void 0 : options.selectedList) == null ? void 0 : _a3.some(
|
|
921
|
+
(n) => {
|
|
922
|
+
var _a4;
|
|
923
|
+
return n.discountId === ((_a4 = item.discount) == null ? void 0 : _a4.resource_id);
|
|
924
|
+
}
|
|
925
|
+
);
|
|
926
|
+
}
|
|
927
|
+
)) || ((_v = (_u = flatItem.parentProduct) == null ? void 0 : _u.discount_list) == null ? void 0 : _v.some(
|
|
928
|
+
(item) => {
|
|
929
|
+
var _a3;
|
|
930
|
+
return (_a3 = options == null ? void 0 : options.selectedList) == null ? void 0 : _a3.some(
|
|
931
|
+
(n) => {
|
|
932
|
+
var _a4;
|
|
933
|
+
return n.discountId === ((_a4 = item.discount) == null ? void 0 : _a4.resource_id);
|
|
934
|
+
}
|
|
935
|
+
);
|
|
936
|
+
}
|
|
937
|
+
))) {
|
|
1055
938
|
isManualDiscount = false;
|
|
1056
939
|
}
|
|
1057
940
|
}
|
|
1058
941
|
}
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
if (applicableDiscounts.length === 0 || isManualDiscount || (0, _lodashEs.isBoolean)(product.vouchersApplicable) && !product.vouchersApplicable) {
|
|
1062
|
-
if (flatItem.type === 'main') {
|
|
1063
|
-
// 主商品:保持原有逻辑,还原 option 价格
|
|
942
|
+
if (applicableDiscounts.length === 0 || isManualDiscount || (0, import_lodash_es.isBoolean)(product.vouchersApplicable) && !product.vouchersApplicable) {
|
|
943
|
+
if (flatItem.type === "main") {
|
|
1064
944
|
const restoredOptions = restoreOptionPrices(product.options);
|
|
1065
945
|
if (product.isClient) {
|
|
1066
|
-
processedProductsMap.set(product._id, [
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
946
|
+
processedProductsMap.set(product._id, [
|
|
947
|
+
this.hooks.setProduct(originProduct, {
|
|
948
|
+
...isManualDiscount ? {} : {
|
|
949
|
+
origin_total: (0, import_utils2.getProductOriginTotalPrice)({
|
|
950
|
+
product: {
|
|
951
|
+
original_price: product.original_price
|
|
952
|
+
},
|
|
953
|
+
bundle: product.bundle,
|
|
954
|
+
options: restoredOptions
|
|
955
|
+
}),
|
|
956
|
+
variant: originProduct._productInit.variant,
|
|
957
|
+
original_price: originProduct._productInit.original_price,
|
|
958
|
+
total: (0, import_utils2.getProductTotalPrice)({
|
|
959
|
+
product: {
|
|
960
|
+
price: product.price
|
|
961
|
+
},
|
|
962
|
+
bundle: product.bundle,
|
|
963
|
+
options: restoredOptions
|
|
964
|
+
}),
|
|
965
|
+
price: product.price,
|
|
1082
966
|
options: restoredOptions
|
|
1083
|
-
}
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
discount_list: isManualDiscount ? this.resolveDiscountListForManualOverride(product.discount_list) : this.filterDiscountListByType(product.discount_list, 'promotion')
|
|
1088
|
-
})]);
|
|
967
|
+
},
|
|
968
|
+
discount_list: isManualDiscount ? this.resolveDiscountListForManualOverride(product.discount_list) : this.filterDiscountListByType(product.discount_list, "promotion")
|
|
969
|
+
})
|
|
970
|
+
]);
|
|
1089
971
|
} else {
|
|
1090
|
-
let total = product.inPromotion ? product
|
|
1091
|
-
let main_product_selling_price = product.price
|
|
1092
|
-
if ((product.discount_list || []).some(item => item.type ===
|
|
972
|
+
let total = product.inPromotion ? ((_w = product == null ? void 0 : product._promotion) == null ? void 0 : _w.finalPrice) ?? product.origin_total ?? product.total : product.origin_total ?? product.total;
|
|
973
|
+
let main_product_selling_price = product.price;
|
|
974
|
+
if ((product.discount_list || []).some((item) => item.type === "promotion") || (0, import_lodash_es.isBoolean)(product.vouchersApplicable) && !product.vouchersApplicable) {
|
|
1093
975
|
total = product.total ?? product.origin_total;
|
|
1094
976
|
main_product_selling_price = product.main_product_selling_price ?? main_product_selling_price;
|
|
1095
977
|
}
|
|
1096
|
-
processedProductsMap.set(product._id, [
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
978
|
+
processedProductsMap.set(product._id, [
|
|
979
|
+
this.hooks.setProduct(originProduct, {
|
|
980
|
+
...isManualDiscount ? {
|
|
981
|
+
price: product.price
|
|
982
|
+
} : {
|
|
983
|
+
_id: product._id.split("___")[0] + "___" + index,
|
|
984
|
+
total,
|
|
985
|
+
price: product.price,
|
|
986
|
+
main_product_selling_price,
|
|
987
|
+
options: restoredOptions
|
|
988
|
+
},
|
|
989
|
+
discount_list: isManualDiscount ? this.resolveDiscountListForManualOverride(product.discount_list) : this.filterDiscountListByType(product.discount_list, "promotion")
|
|
990
|
+
})
|
|
991
|
+
]);
|
|
1108
992
|
}
|
|
1109
993
|
} else {
|
|
1110
|
-
// bundle子商品:保存到扁平化Map
|
|
1111
994
|
processedFlatItemsMap.set(flatItem._id, [{
|
|
1112
995
|
...flatItem,
|
|
1113
|
-
discount_list: isManualDiscount ? this.resolveDiscountListForManualOverride(flatItem.bundleItem
|
|
996
|
+
discount_list: isManualDiscount ? this.resolveDiscountListForManualOverride(((_x = flatItem.bundleItem) == null ? void 0 : _x.discount_list) || []) : this.filterDiscountListByType(((_y = flatItem.bundleItem) == null ? void 0 : _y.discount_list) || [], "promotion"),
|
|
1114
997
|
price: isManualDiscount ? flatItem.bundleItem.price : flatItem.bundleItem.original_price,
|
|
1115
998
|
processed: true
|
|
1116
999
|
}]);
|
|
@@ -1118,98 +1001,57 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
1118
1001
|
return;
|
|
1119
1002
|
}
|
|
1120
1003
|
const shouldReapplyBookingDiscountForProduct = shouldReapplyBookingDiscount(originProduct, selectedDiscount);
|
|
1121
|
-
if (applicableDiscounts.length && product.booking_id && typeof selectedDiscount.isManualSelect ===
|
|
1004
|
+
if (applicableDiscounts.length && product.booking_id && typeof selectedDiscount.isManualSelect === "undefined" && !(options == null ? void 0 : options.scan) && !isEditModeAddNewProduct && !shouldReapplyBookingDiscountForProduct) {
|
|
1122
1005
|
return;
|
|
1123
1006
|
}
|
|
1124
|
-
|
|
1125
|
-
// 是否需要拆分(商品券需要拆分,折扣卡在 applicableProductLimit > 0 时也需要拆分)
|
|
1126
|
-
const discountType = selectedDiscount.tag || selectedDiscount.type;
|
|
1127
|
-
const isGoodPass = discountType === 'good_pass';
|
|
1128
|
-
const isDiscountCard = ['discount_card', 'product_discount_card'].includes(discountType);
|
|
1129
|
-
const applicableProductLimit = selectedDiscount.config?.applicableProductLimit || 0;
|
|
1130
|
-
|
|
1131
|
-
// 商品券始终需要拆分,折扣卡在 applicableProductLimit > 0 时需要拆分
|
|
1132
|
-
const isNeedSplit = isGoodPass || isDiscountCard && applicableProductLimit > 0;
|
|
1133
|
-
|
|
1134
|
-
// 需要拆分出来的数量
|
|
1007
|
+
const isNeedSplit = (selectedDiscount.tag || selectedDiscount.type) === "good_pass";
|
|
1135
1008
|
const totalQuantity = product.quantity || product.num || 1;
|
|
1136
|
-
const availableGoodPassCount = applicableDiscounts.filter(
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
let maxUsageLimit;
|
|
1140
|
-
if (
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
}
|
|
1146
|
-
} else if (isDiscountCard && applicableProductLimit > 0) {
|
|
1147
|
-
// 折扣卡:使用 applicableProductLimit 限制(一个商品使用一次折扣卡算1次)
|
|
1148
|
-
// 需要减去已使用次数(跨商品全局计数)
|
|
1149
|
-
const usedLimitCount = usedDiscountCardLimitCounts.get(selectedDiscount.id) || 0;
|
|
1150
|
-
maxUsageLimit = Math.max(0, applicableProductLimit - usedLimitCount);
|
|
1151
|
-
} else {
|
|
1152
|
-
// 其他情况不拆分
|
|
1153
|
-
maxUsageLimit = 1;
|
|
1009
|
+
const availableGoodPassCount = applicableDiscounts.filter(
|
|
1010
|
+
(item) => (item.tag || item.type) === "good_pass"
|
|
1011
|
+
).length;
|
|
1012
|
+
let maxUsageLimit = availableGoodPassCount;
|
|
1013
|
+
if (selectedDiscount.config && selectedDiscount.config.maxUsagePerOrder) {
|
|
1014
|
+
maxUsageLimit = Math.min(
|
|
1015
|
+
availableGoodPassCount,
|
|
1016
|
+
selectedDiscount.config.maxUsagePerOrder
|
|
1017
|
+
);
|
|
1154
1018
|
}
|
|
1155
1019
|
const splitCount = isNeedSplit ? Math.min(product.quantity || product.num || 1, maxUsageLimit) : 1;
|
|
1156
1020
|
const arr = [];
|
|
1157
|
-
|
|
1158
|
-
// 🔥 主商品和bundle子商品分别处理
|
|
1159
|
-
if (flatItem.type === 'main') {
|
|
1160
|
-
// 主商品:保持原有逻辑
|
|
1021
|
+
if (flatItem.type === "main") {
|
|
1161
1022
|
if (splitCount < totalQuantity && isNeedSplit) {
|
|
1162
1023
|
let total = product.origin_total ?? product.total;
|
|
1163
|
-
if ((product.discount_list || []).some(item => item.type ===
|
|
1024
|
+
if ((product.discount_list || []).some((item) => item.type === "promotion")) {
|
|
1164
1025
|
total = product.total ?? product.origin_total;
|
|
1165
1026
|
}
|
|
1166
|
-
arr.push(
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1027
|
+
arr.push(
|
|
1028
|
+
this.hooks.setProduct(originProduct, {
|
|
1029
|
+
discount_list: this.filterDiscountListByType(product.discount_list, "promotion"),
|
|
1030
|
+
quantity: totalQuantity - splitCount,
|
|
1031
|
+
_id: product._id.split("___")[0],
|
|
1032
|
+
total
|
|
1033
|
+
})
|
|
1034
|
+
);
|
|
1172
1035
|
}
|
|
1173
1036
|
for (let i = 0; i < splitCount; i++) {
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
// 🔥 更新 product_id 使用计数
|
|
1180
|
-
if ((currentSelectedDiscount.tag || currentSelectedDiscount.type) === 'good_pass') {
|
|
1181
|
-
const currentCount = usedProductIdCounts.get(currentSelectedDiscount.product_id) || 0;
|
|
1182
|
-
usedProductIdCounts.set(currentSelectedDiscount.product_id, currentCount + 1);
|
|
1183
|
-
}
|
|
1184
|
-
// 🔥 更新折扣卡 applicableProductLimit 使用计数(跨商品全局)
|
|
1185
|
-
const currentDiscountTypeForCount = currentSelectedDiscount.tag || currentSelectedDiscount.type;
|
|
1186
|
-
if (['discount_card', 'product_discount_card'].includes(currentDiscountTypeForCount)) {
|
|
1187
|
-
const currentLimitCount = usedDiscountCardLimitCounts.get(currentSelectedDiscount.id) || 0;
|
|
1188
|
-
usedDiscountCardLimitCounts.set(currentSelectedDiscount.id, currentLimitCount + 1);
|
|
1037
|
+
const selectedDiscount2 = selectedDiscountCard || applicableDiscounts[i];
|
|
1038
|
+
usedDiscounts.set(selectedDiscount2.id, true);
|
|
1039
|
+
if ((selectedDiscount2.tag || selectedDiscount2.type) === "good_pass") {
|
|
1040
|
+
const currentCount = usedProductIdCounts.get(selectedDiscount2.product_id) || 0;
|
|
1041
|
+
usedProductIdCounts.set(selectedDiscount2.product_id, currentCount + 1);
|
|
1189
1042
|
}
|
|
1190
|
-
|
|
1191
|
-
// 记录实际应用了优惠券的商品信息
|
|
1192
|
-
const appliedProducts = appliedDiscountProducts.get(currentSelectedDiscount.id) || [];
|
|
1193
|
-
|
|
1194
|
-
// 优先从 origin_total拿,可能会拿不到(比如用户端预约在没有配置 original_price 的情况下)
|
|
1043
|
+
const appliedProducts = appliedDiscountProducts.get(selectedDiscount2.id) || [];
|
|
1195
1044
|
let productOriginTotal = product.origin_total || product.total || 0;
|
|
1196
|
-
|
|
1197
|
-
if (this.filterDiscountListByType(product.discount_list, 'promotion').length && product.origin_total) {
|
|
1045
|
+
if (this.filterDiscountListByType(product.discount_list, "promotion").length && product.origin_total) {
|
|
1198
1046
|
productOriginTotal = product.origin_total;
|
|
1199
1047
|
}
|
|
1200
|
-
|
|
1201
|
-
if (Number(originProduct?._productInit?.original_price || 0) > 0 && product.origin_total && product.total && product.origin_total !== product.total) {
|
|
1048
|
+
if (Number(((_z = originProduct == null ? void 0 : originProduct._productInit) == null ? void 0 : _z.original_price) || 0) > 0 && product.origin_total && product.total && product.origin_total !== product.total) {
|
|
1202
1049
|
productOriginTotal = product.total;
|
|
1203
1050
|
}
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
const
|
|
1208
|
-
const orderLevelAllocation = isOrderLevel ? orderLevelDiscountAllocations.get(selectedDiscount.id) : null;
|
|
1209
|
-
const productAllocation = orderLevelAllocation?.get(flatItem._id);
|
|
1210
|
-
const isDeductOptionPrice = !!selectedDiscount.config?.deductOptionPrice;
|
|
1211
|
-
|
|
1212
|
-
// 主商品折后价(不含 option);勿与 option 合计混在同一变量,否则 main_product_selling_price 错误
|
|
1051
|
+
const isOrderLevel = (0, import_utils3.isOrderLevelFixedAmountDiscount)(selectedDiscount2);
|
|
1052
|
+
const orderLevelAllocation = isOrderLevel ? orderLevelDiscountAllocations.get(selectedDiscount2.id) : null;
|
|
1053
|
+
const productAllocation = orderLevelAllocation == null ? void 0 : orderLevelAllocation.get(flatItem._id);
|
|
1054
|
+
const isDeductOptionPrice = !!((_A = selectedDiscount2.config) == null ? void 0 : _A.deductOptionPrice);
|
|
1213
1055
|
let mainProductSellingPrice;
|
|
1214
1056
|
let amount;
|
|
1215
1057
|
let productDiscountDifference;
|
|
@@ -1217,166 +1059,146 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
1217
1059
|
let optionDiscountAmount = 0;
|
|
1218
1060
|
let reapplyDiscountPercent;
|
|
1219
1061
|
if (isOrderLevel && productAllocation) {
|
|
1220
|
-
// order_level:使用预计算的分摊金额
|
|
1221
1062
|
amount = productAllocation.discountAmount;
|
|
1222
1063
|
productDiscountDifference = productAllocation.difference;
|
|
1223
|
-
mainProductSellingPrice = Math.max(new
|
|
1224
|
-
} else if (resolveReapplyEditModeDiscountPercent(originProduct,
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
amount = new _decimal.default(product.price).minus(mainProductSellingPrice).toNumber();
|
|
1064
|
+
mainProductSellingPrice = Math.max(new import_decimal.default(product.price).minus(amount).toNumber(), 0);
|
|
1065
|
+
} else if (resolveReapplyEditModeDiscountPercent(originProduct, selectedDiscount2) !== void 0) {
|
|
1066
|
+
const percent = resolveReapplyEditModeDiscountPercent(originProduct, selectedDiscount2);
|
|
1067
|
+
reapplyDiscountPercent = new import_decimal.default(percent).toFixed(2);
|
|
1068
|
+
mainProductSellingPrice = new import_decimal.default(product.price || 0).mul(new import_decimal.default(100).minus(percent)).div(100).toDecimalPlaces(2).toNumber();
|
|
1069
|
+
amount = new import_decimal.default(product.price).minus(mainProductSellingPrice).toNumber();
|
|
1230
1070
|
} else {
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1071
|
+
mainProductSellingPrice = (0, import_utils.getDiscountAmount)(
|
|
1072
|
+
selectedDiscount2,
|
|
1073
|
+
product.price,
|
|
1074
|
+
product.price
|
|
1075
|
+
);
|
|
1076
|
+
amount = new import_decimal.default(product.price).minus(new import_decimal.default(mainProductSellingPrice)).toNumber();
|
|
1234
1077
|
}
|
|
1235
|
-
if (isDeductOptionPrice && product.options
|
|
1236
|
-
const optionResult = applyDiscountToOptions(
|
|
1078
|
+
if (isDeductOptionPrice && ((_B = product.options) == null ? void 0 : _B.length)) {
|
|
1079
|
+
const optionResult = applyDiscountToOptions(
|
|
1080
|
+
product.options,
|
|
1081
|
+
selectedDiscount2
|
|
1082
|
+
);
|
|
1237
1083
|
discountedOptions = optionResult.discountedOptions;
|
|
1238
1084
|
optionDiscountAmount = optionResult.optionDiscountAmount;
|
|
1239
1085
|
}
|
|
1240
|
-
|
|
1241
|
-
// total = 主商品折后 + option 行合计;开启 option 抵扣时必须用 discountedOptions,不能用未折扣的 product.options 再算一遍
|
|
1242
|
-
const optionsForLineTotal = isDeductOptionPrice && product.options?.length ? discountedOptions : product.options;
|
|
1086
|
+
const optionsForLineTotal = isDeductOptionPrice && ((_C = product.options) == null ? void 0 : _C.length) ? discountedOptions : product.options;
|
|
1243
1087
|
const optionsLineTotal = getOptionTotal(optionsForLineTotal || []);
|
|
1244
|
-
const total = new
|
|
1245
|
-
|
|
1246
|
-
// discount_list.amount / fixed_amount:行级总优惠 = 主商品优惠 + option 优惠(与 total 变化一致)
|
|
1088
|
+
const total = new import_decimal.default(mainProductSellingPrice).plus(optionsLineTotal).toNumber();
|
|
1247
1089
|
const mainProductDiscountAmount = amount;
|
|
1248
|
-
const lineDiscountAmount = new
|
|
1249
|
-
const discountType =
|
|
1250
|
-
const
|
|
1090
|
+
const lineDiscountAmount = new import_decimal.default(mainProductDiscountAmount).plus(optionDiscountAmount).toNumber();
|
|
1091
|
+
const discountType = selectedDiscount2.tag || selectedDiscount2.type;
|
|
1092
|
+
const isGoodPass = discountType === "good_pass";
|
|
1251
1093
|
const discountDetail = {
|
|
1252
1094
|
amount: lineDiscountAmount,
|
|
1253
|
-
type:
|
|
1095
|
+
type: selectedDiscount2.tag === "product_discount_card" ? "discount_card" : discountType,
|
|
1254
1096
|
discount: {
|
|
1255
|
-
discount_card_type:
|
|
1097
|
+
discount_card_type: (_D = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _D.discount_card_type,
|
|
1256
1098
|
fixed_amount: lineDiscountAmount,
|
|
1257
|
-
discount_calculation_mode:
|
|
1258
|
-
resource_id:
|
|
1259
|
-
title:
|
|
1099
|
+
discount_calculation_mode: (_E = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _E.discount_calculation_mode,
|
|
1100
|
+
resource_id: selectedDiscount2.id,
|
|
1101
|
+
title: selectedDiscount2.format_title,
|
|
1260
1102
|
original_amount: product.price,
|
|
1261
1103
|
product_id: originProduct.id || originProduct.product_id,
|
|
1262
|
-
percent: reapplyDiscountPercent ??
|
|
1263
|
-
discount_product_id:
|
|
1104
|
+
percent: reapplyDiscountPercent ?? selectedDiscount2.par_value,
|
|
1105
|
+
discount_product_id: selectedDiscount2.product_id
|
|
1264
1106
|
},
|
|
1265
|
-
// 前端使用的num
|
|
1266
|
-
_num:
|
|
1267
|
-
config:
|
|
1107
|
+
// 前端使用的num数量,为了计算优惠金额
|
|
1108
|
+
_num: isGoodPass ? 1 : product.num,
|
|
1109
|
+
config: selectedDiscount2 == null ? void 0 : selectedDiscount2.config,
|
|
1268
1110
|
metadata: {
|
|
1269
1111
|
num: 1,
|
|
1270
|
-
discount_rule_uncheck_flag:
|
|
1112
|
+
discount_rule_uncheck_flag: selectedDiscount2 == null ? void 0 : selectedDiscount2.discount_rule_uncheck_flag,
|
|
1271
1113
|
// 🔥 order_level 分摊差值
|
|
1272
|
-
...
|
|
1273
|
-
product_discount_difference: productDiscountDifference
|
|
1274
|
-
}),
|
|
1114
|
+
...productDiscountDifference !== void 0 && { product_discount_difference: productDiscountDifference },
|
|
1275
1115
|
/** 仅主商品上的优惠金额(不含 option) */
|
|
1276
1116
|
mainProductDiscountAmount,
|
|
1277
1117
|
optionDiscountAmount
|
|
1278
1118
|
}
|
|
1279
1119
|
};
|
|
1280
1120
|
appliedProducts.push(discountDetail);
|
|
1281
|
-
appliedDiscountProducts.set(
|
|
1282
|
-
|
|
1283
|
-
// 记录应用了优惠券的商品
|
|
1284
|
-
// 后续更新价格改为 getProductTotalPrice getProductOriginTotalPrice逻辑
|
|
1121
|
+
appliedDiscountProducts.set(selectedDiscount2.id, appliedProducts);
|
|
1285
1122
|
if (product.isClient) {
|
|
1286
|
-
arr.push(
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1123
|
+
arr.push(
|
|
1124
|
+
this.hooks.setProduct(originProduct, {
|
|
1125
|
+
discount_list: [discountDetail],
|
|
1126
|
+
// good_pass:主商品价以折后价为准;勿用 product.price - amount(amount 含 option 优惠时会算错)
|
|
1127
|
+
price: isGoodPass ? mainProductSellingPrice : product.price,
|
|
1128
|
+
quantity: isNeedSplit ? 1 : product.quantity,
|
|
1129
|
+
origin_total: (0, import_utils2.getProductOriginTotalPrice)({
|
|
1130
|
+
product: {
|
|
1131
|
+
original_price: product.original_price
|
|
1132
|
+
},
|
|
1133
|
+
bundle: product.bundle,
|
|
1134
|
+
options: restoreOptionPrices(product.options)
|
|
1135
|
+
}),
|
|
1136
|
+
variant: originProduct._productInit.variant,
|
|
1137
|
+
original_price: new import_decimal.default(product.price || 0).toNumber(),
|
|
1138
|
+
total,
|
|
1139
|
+
options: discountedOptions
|
|
1140
|
+
})
|
|
1141
|
+
);
|
|
1303
1142
|
} else {
|
|
1304
|
-
arr.push(
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1143
|
+
arr.push(
|
|
1144
|
+
this.hooks.setProduct(originProduct, {
|
|
1145
|
+
discount_list: this.filterDiscountListByType(product.discount_list, "promotion").concat([discountDetail]),
|
|
1146
|
+
_id: product._id.split("___")[0] + "___" + selectedDiscount2.id + index,
|
|
1147
|
+
price: selectedDiscount2.tag === "good_pass" ? 0 : product.price,
|
|
1148
|
+
quantity: isNeedSplit ? 1 : product.quantity,
|
|
1149
|
+
total,
|
|
1150
|
+
origin_total: productOriginTotal,
|
|
1151
|
+
main_product_selling_price: mainProductSellingPrice,
|
|
1152
|
+
options: discountedOptions
|
|
1153
|
+
})
|
|
1154
|
+
);
|
|
1314
1155
|
}
|
|
1315
1156
|
}
|
|
1316
1157
|
processedProductsMap.set(product._id, arr);
|
|
1317
1158
|
} else {
|
|
1318
|
-
// 🔥 bundle子商品:支持拆分(商品券和折扣卡在 applicableProductLimit > 0 时都需要拆分)
|
|
1319
1159
|
const processedItems = [];
|
|
1320
1160
|
if (isNeedSplit) {
|
|
1321
|
-
// 需要拆分数量(商品券或折扣卡有 applicableProductLimit 限制)
|
|
1322
1161
|
const discountNum = splitCount;
|
|
1323
1162
|
const normalNum = totalQuantity - discountNum;
|
|
1324
|
-
|
|
1325
|
-
// 生成有折扣的商品(每个拆分商品 num: 1)
|
|
1326
1163
|
for (let i = 0; i < discountNum; i++) {
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
if ((currentBundleDiscount.tag || currentBundleDiscount.type) === 'good_pass') {
|
|
1333
|
-
const currentCount = usedProductIdCounts.get(currentBundleDiscount.product_id) || 0;
|
|
1334
|
-
usedProductIdCounts.set(currentBundleDiscount.product_id, currentCount + 1);
|
|
1164
|
+
const selectedDiscount2 = applicableDiscounts[i];
|
|
1165
|
+
usedDiscounts.set(selectedDiscount2.id, true);
|
|
1166
|
+
if ((selectedDiscount2.tag || selectedDiscount2.type) === "good_pass") {
|
|
1167
|
+
const currentCount = usedProductIdCounts.get(selectedDiscount2.product_id) || 0;
|
|
1168
|
+
usedProductIdCounts.set(selectedDiscount2.product_id, currentCount + 1);
|
|
1335
1169
|
}
|
|
1336
|
-
// 🔥 更新折扣卡 applicableProductLimit 使用计数(跨商品全局)
|
|
1337
|
-
const bundleDiscountTypeForCount = currentBundleDiscount.tag || currentBundleDiscount.type;
|
|
1338
|
-
if (['discount_card', 'product_discount_card'].includes(bundleDiscountTypeForCount)) {
|
|
1339
|
-
const currentBundleLimitCount = usedDiscountCardLimitCounts.get(currentBundleDiscount.id) || 0;
|
|
1340
|
-
usedDiscountCardLimitCounts.set(currentBundleDiscount.id, currentBundleLimitCount + 1);
|
|
1341
|
-
}
|
|
1342
|
-
|
|
1343
|
-
// 🔥 生成唯一的 _id
|
|
1344
1170
|
const uniqueId = `${flatItem._id}_split_${i}`;
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1171
|
+
const discountedPrice = (0, import_utils.getDiscountAmount)(
|
|
1172
|
+
selectedDiscount2,
|
|
1173
|
+
product.origin_total,
|
|
1174
|
+
product.origin_total
|
|
1175
|
+
);
|
|
1176
|
+
const bundleDiscountAmount = new import_decimal.default(product.origin_total || 0).minus(discountedPrice).toNumber();
|
|
1349
1177
|
debugger;
|
|
1350
|
-
|
|
1351
|
-
// 确定折扣类型
|
|
1352
|
-
const bundleDiscountType = currentBundleDiscount.tag === 'product_discount_card' ? 'discount_card' : currentBundleDiscount.tag;
|
|
1353
1178
|
const discountDetail = {
|
|
1354
1179
|
amount: bundleDiscountAmount,
|
|
1355
|
-
type:
|
|
1180
|
+
type: "good_pass",
|
|
1356
1181
|
discount: {
|
|
1357
|
-
|
|
1358
|
-
discount_calculation_mode:
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
title: currentBundleDiscount.format_title,
|
|
1182
|
+
fixed_amount: product.origin_total,
|
|
1183
|
+
discount_calculation_mode: (_F = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _F.discount_calculation_mode,
|
|
1184
|
+
resource_id: selectedDiscount2.id,
|
|
1185
|
+
title: selectedDiscount2.format_title,
|
|
1362
1186
|
original_amount: product.origin_total,
|
|
1363
1187
|
product_id: product.id || product.product_id,
|
|
1364
|
-
discount_product_id:
|
|
1188
|
+
discount_product_id: selectedDiscount2.product_id
|
|
1365
1189
|
},
|
|
1366
1190
|
metadata: {
|
|
1367
1191
|
// 🔥 使用拆分后的唯一 _id
|
|
1368
1192
|
custom_product_bundle_map_id: uniqueId,
|
|
1369
|
-
discount_rule_uncheck_flag:
|
|
1193
|
+
discount_rule_uncheck_flag: selectedDiscount2 == null ? void 0 : selectedDiscount2.discount_rule_uncheck_flag,
|
|
1370
1194
|
num: 1
|
|
1371
1195
|
},
|
|
1372
1196
|
_num: 1,
|
|
1373
|
-
config:
|
|
1197
|
+
config: selectedDiscount2 == null ? void 0 : selectedDiscount2.config
|
|
1374
1198
|
};
|
|
1375
|
-
|
|
1376
|
-
// 记录实际应用的折扣
|
|
1377
|
-
const appliedProducts = appliedDiscountProducts.get(currentBundleDiscount.id) || [];
|
|
1199
|
+
const appliedProducts = appliedDiscountProducts.get(selectedDiscount2.id) || [];
|
|
1378
1200
|
appliedProducts.push(discountDetail);
|
|
1379
|
-
appliedDiscountProducts.set(
|
|
1201
|
+
appliedDiscountProducts.set(selectedDiscount2.id, appliedProducts);
|
|
1380
1202
|
processedItems.push({
|
|
1381
1203
|
...flatItem,
|
|
1382
1204
|
// 🔥 使用唯一的 _id
|
|
@@ -1388,333 +1210,100 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
1388
1210
|
total: discountedPrice,
|
|
1389
1211
|
discount_list: [discountDetail],
|
|
1390
1212
|
processed: true,
|
|
1391
|
-
_discountId:
|
|
1213
|
+
_discountId: selectedDiscount2.id
|
|
1392
1214
|
});
|
|
1393
1215
|
}
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
if (['good_pass', 'discount_card', 'product_discount_card'].includes(nextDiscountType)) {
|
|
1404
|
-
if (nextDiscount.config === undefined || !nextDiscount?.config?.isAvailable) {
|
|
1405
|
-
return false;
|
|
1406
|
-
}
|
|
1407
|
-
}
|
|
1408
|
-
// 折扣卡时总价为0时不可用
|
|
1409
|
-
if ((Number(product.total) <= 0 || !product.total) && !product.discount_list?.find(n => n.discount?.resource_id === nextDiscount.id) && nextDiscountType !== 'good_pass') return false;
|
|
1410
|
-
|
|
1411
|
-
// 商品券已被使用则跳过
|
|
1412
|
-
if (usedDiscounts.get(nextDiscount.id) && nextDiscountType === 'good_pass') return false;
|
|
1413
|
-
|
|
1414
|
-
// 检查 maxUsagePerOrder 限制
|
|
1415
|
-
if (nextDiscountType === 'good_pass') {
|
|
1416
|
-
const maxUsagePerOrder = nextDiscount.config?.maxUsagePerOrder;
|
|
1417
|
-
if (maxUsagePerOrder && maxUsagePerOrder > 0) {
|
|
1418
|
-
const currentUsedCount = usedProductIdCounts.get(nextDiscount.product_id) || 0;
|
|
1419
|
-
if (currentUsedCount >= maxUsagePerOrder) {
|
|
1420
|
-
return false;
|
|
1421
|
-
}
|
|
1422
|
-
}
|
|
1423
|
-
}
|
|
1424
|
-
|
|
1425
|
-
// 检查折扣卡的 applicableProductLimit 限制
|
|
1426
|
-
if (['discount_card', 'product_discount_card'].includes(nextDiscountType)) {
|
|
1427
|
-
const limitConfig = nextDiscount.config?.applicableProductLimit || 0;
|
|
1428
|
-
if (limitConfig > 0) {
|
|
1429
|
-
const currentUsedLimitCount = usedDiscountCardLimitCounts.get(nextDiscount.id) || 0;
|
|
1430
|
-
if (currentUsedLimitCount >= limitConfig) {
|
|
1431
|
-
return false;
|
|
1432
|
-
}
|
|
1433
|
-
}
|
|
1434
|
-
}
|
|
1435
|
-
const limitedData = nextDiscount.limited_relation_product_data;
|
|
1436
|
-
if (limitedData.type === 'product_all') {
|
|
1437
|
-
if (limitedData.filter === 1 && limitedData.exclude_product_ids.includes(product.id)) {
|
|
1438
|
-
return false;
|
|
1439
|
-
}
|
|
1440
|
-
if (!this.checkPackageSubItemUsageRules(nextDiscount, flatItem)) {
|
|
1441
|
-
return false;
|
|
1442
|
-
}
|
|
1443
|
-
return true;
|
|
1444
|
-
} else if (limitedData.product_ids && limitedData.product_ids.includes(product.id)) {
|
|
1445
|
-
if (!this.checkPackageSubItemUsageRules(nextDiscount, flatItem)) {
|
|
1446
|
-
return false;
|
|
1447
|
-
}
|
|
1448
|
-
return true;
|
|
1449
|
-
}
|
|
1450
|
-
return false;
|
|
1216
|
+
if (normalNum > 0) {
|
|
1217
|
+
processedItems.push({
|
|
1218
|
+
...flatItem,
|
|
1219
|
+
// 🔥 为剩余商品生成唯一的 _id
|
|
1220
|
+
_id: `${flatItem._id}_split_rest`,
|
|
1221
|
+
num: normalNum,
|
|
1222
|
+
quantity: normalNum,
|
|
1223
|
+
discount_list: this.filterDiscountListByType(flatItem.discount_list, "promotion"),
|
|
1224
|
+
processed: true
|
|
1451
1225
|
});
|
|
1452
|
-
|
|
1453
|
-
// 没有更多可用折扣,剩余商品无折扣存储
|
|
1454
|
-
if (nextApplicableDiscounts.length === 0) {
|
|
1455
|
-
processedItems.push({
|
|
1456
|
-
...flatItem,
|
|
1457
|
-
_id: `${flatItem._id}_split_rest`,
|
|
1458
|
-
num: remainingNum,
|
|
1459
|
-
quantity: remainingNum,
|
|
1460
|
-
discount_list: [],
|
|
1461
|
-
processed: true
|
|
1462
|
-
});
|
|
1463
|
-
break;
|
|
1464
|
-
}
|
|
1465
|
-
|
|
1466
|
-
// 选择最优折扣
|
|
1467
|
-
const nextSelectedDiscountCard = nextApplicableDiscounts.find(n => n.isScan && n.isSelected && (n.tag || n.type) !== 'good_pass');
|
|
1468
|
-
const nextSelectedDiscount = nextSelectedDiscountCard || nextApplicableDiscounts[0];
|
|
1469
|
-
|
|
1470
|
-
// 判断新折扣是否需要拆分
|
|
1471
|
-
const nextDiscType = nextSelectedDiscount.tag || nextSelectedDiscount.type;
|
|
1472
|
-
const nextIsGoodPass = nextDiscType === 'good_pass';
|
|
1473
|
-
const nextIsDiscountCard = ['discount_card', 'product_discount_card'].includes(nextDiscType);
|
|
1474
|
-
const nextApplicableProductLimit = nextSelectedDiscount.config?.applicableProductLimit || 0;
|
|
1475
|
-
const nextIsNeedSplit = nextIsGoodPass || nextIsDiscountCard && nextApplicableProductLimit > 0;
|
|
1476
|
-
if (!nextIsNeedSplit) {
|
|
1477
|
-
// 🔥 不需要拆分:直接应用折扣到所有剩余商品
|
|
1478
|
-
const nextBundleDiscount = nextSelectedDiscountCard || nextApplicableDiscounts[0];
|
|
1479
|
-
usedDiscounts.set(nextBundleDiscount.id, true);
|
|
1480
|
-
if ((nextBundleDiscount.tag || nextBundleDiscount.type) === 'good_pass') {
|
|
1481
|
-
const curCount = usedProductIdCounts.get(nextBundleDiscount.product_id) || 0;
|
|
1482
|
-
usedProductIdCounts.set(nextBundleDiscount.product_id, curCount + 1);
|
|
1483
|
-
}
|
|
1484
|
-
const nextNoSplitType = nextBundleDiscount.tag || nextBundleDiscount.type;
|
|
1485
|
-
if (['discount_card', 'product_discount_card'].includes(nextNoSplitType)) {
|
|
1486
|
-
const curCount = usedDiscountCardLimitCounts.get(nextBundleDiscount.id) || 0;
|
|
1487
|
-
usedDiscountCardLimitCounts.set(nextBundleDiscount.id, curCount + remainingNum);
|
|
1488
|
-
}
|
|
1489
|
-
const nextOriginTotal = product.original_price || product.price || 0;
|
|
1490
|
-
const nextTargetTotal = (0, _utils.getDiscountAmount)(nextBundleDiscount, nextOriginTotal, nextOriginTotal);
|
|
1491
|
-
const nextDiscountAmount = new _decimal.default(nextOriginTotal).minus(nextTargetTotal).toNumber();
|
|
1492
|
-
const nextUniqueId = `${flatItem._id}_split_${continueSplitIndex}`;
|
|
1493
|
-
const nextBundleDiscType = nextBundleDiscount.tag === 'product_discount_card' ? 'discount_card' : nextBundleDiscount.tag;
|
|
1494
|
-
const nextDiscountDetail = {
|
|
1495
|
-
amount: nextDiscountAmount * remainingNum,
|
|
1496
|
-
type: nextBundleDiscType,
|
|
1497
|
-
discount: {
|
|
1498
|
-
discount_card_type: nextBundleDiscount?.metadata?.discount_card_type,
|
|
1499
|
-
fixed_amount: nextDiscountAmount,
|
|
1500
|
-
resource_id: nextBundleDiscount.id,
|
|
1501
|
-
title: nextBundleDiscount.format_title,
|
|
1502
|
-
original_amount: product.original_price,
|
|
1503
|
-
product_id: product.id,
|
|
1504
|
-
percent: nextBundleDiscount.par_value,
|
|
1505
|
-
discount_product_id: nextBundleDiscount.product_id
|
|
1506
|
-
},
|
|
1507
|
-
metadata: {
|
|
1508
|
-
custom_product_bundle_map_id: nextUniqueId,
|
|
1509
|
-
num: remainingNum
|
|
1510
|
-
},
|
|
1511
|
-
config: nextBundleDiscount?.config,
|
|
1512
|
-
_num: remainingNum * (flatItem?.parentProduct?.num || 1)
|
|
1513
|
-
};
|
|
1514
|
-
const nextAppliedProducts = appliedDiscountProducts.get(nextBundleDiscount.id) || [];
|
|
1515
|
-
nextAppliedProducts.push(nextDiscountDetail);
|
|
1516
|
-
appliedDiscountProducts.set(nextBundleDiscount.id, nextAppliedProducts);
|
|
1517
|
-
processedItems.push({
|
|
1518
|
-
...flatItem,
|
|
1519
|
-
_id: nextUniqueId,
|
|
1520
|
-
num: remainingNum,
|
|
1521
|
-
quantity: remainingNum,
|
|
1522
|
-
total: nextTargetTotal,
|
|
1523
|
-
price: new _decimal.default(nextOriginTotal || 0).minus(nextDiscountDetail.discount.fixed_amount).toNumber(),
|
|
1524
|
-
discount_list: [nextDiscountDetail],
|
|
1525
|
-
processed: true
|
|
1526
|
-
});
|
|
1527
|
-
remainingNum = 0;
|
|
1528
|
-
break;
|
|
1529
|
-
}
|
|
1530
|
-
|
|
1531
|
-
// 🔥 需要拆分:计算最大使用次数
|
|
1532
|
-
let nextMaxUsageLimit;
|
|
1533
|
-
if (nextIsGoodPass) {
|
|
1534
|
-
const nextGoodPassCount = nextApplicableDiscounts.filter(item => (item.tag || item.type) === 'good_pass').length;
|
|
1535
|
-
nextMaxUsageLimit = nextGoodPassCount;
|
|
1536
|
-
if (nextSelectedDiscount.config?.maxUsagePerOrder) {
|
|
1537
|
-
const usedCount = usedProductIdCounts.get(nextSelectedDiscount.product_id) || 0;
|
|
1538
|
-
nextMaxUsageLimit = Math.min(nextGoodPassCount, Math.max(0, nextSelectedDiscount.config.maxUsagePerOrder - usedCount));
|
|
1539
|
-
}
|
|
1540
|
-
} else if (nextIsDiscountCard && nextApplicableProductLimit > 0) {
|
|
1541
|
-
const usedLimitCount = usedDiscountCardLimitCounts.get(nextSelectedDiscount.id) || 0;
|
|
1542
|
-
nextMaxUsageLimit = Math.max(0, nextApplicableProductLimit - usedLimitCount);
|
|
1543
|
-
} else {
|
|
1544
|
-
nextMaxUsageLimit = 1;
|
|
1545
|
-
}
|
|
1546
|
-
const nextSplitCount = Math.min(remainingNum, nextMaxUsageLimit);
|
|
1547
|
-
if (nextSplitCount === 0) {
|
|
1548
|
-
// 已达使用上限,剩余商品无折扣存储
|
|
1549
|
-
processedItems.push({
|
|
1550
|
-
...flatItem,
|
|
1551
|
-
_id: `${flatItem._id}_split_rest`,
|
|
1552
|
-
num: remainingNum,
|
|
1553
|
-
quantity: remainingNum,
|
|
1554
|
-
discount_list: [],
|
|
1555
|
-
processed: true
|
|
1556
|
-
});
|
|
1557
|
-
break;
|
|
1558
|
-
}
|
|
1559
|
-
|
|
1560
|
-
// 生成有折扣的商品
|
|
1561
|
-
for (let j = 0; j < nextSplitCount; j++) {
|
|
1562
|
-
const nextBundleDiscount = nextIsGoodPass ? nextSelectedDiscountCard || nextApplicableDiscounts[j] : nextSelectedDiscountCard || nextApplicableDiscounts[0];
|
|
1563
|
-
usedDiscounts.set(nextBundleDiscount.id, true);
|
|
1564
|
-
if ((nextBundleDiscount.tag || nextBundleDiscount.type) === 'good_pass') {
|
|
1565
|
-
const curCount = usedProductIdCounts.get(nextBundleDiscount.product_id) || 0;
|
|
1566
|
-
usedProductIdCounts.set(nextBundleDiscount.product_id, curCount + 1);
|
|
1567
|
-
}
|
|
1568
|
-
const nextBundleDiscTypeForCount = nextBundleDiscount.tag || nextBundleDiscount.type;
|
|
1569
|
-
if (['discount_card', 'product_discount_card'].includes(nextBundleDiscTypeForCount)) {
|
|
1570
|
-
const curLimitCount = usedDiscountCardLimitCounts.get(nextBundleDiscount.id) || 0;
|
|
1571
|
-
usedDiscountCardLimitCounts.set(nextBundleDiscount.id, curLimitCount + 1);
|
|
1572
|
-
}
|
|
1573
|
-
const nextUniqueId = `${flatItem._id}_split_${continueSplitIndex}`;
|
|
1574
|
-
const nextDiscountedPrice = (0, _utils.getDiscountAmount)(nextBundleDiscount, product.origin_total, product.origin_total);
|
|
1575
|
-
const nextBundleDiscAmount = new _decimal.default(product.origin_total || 0).minus(nextDiscountedPrice).toNumber();
|
|
1576
|
-
const nextBundleDiscTypeStr = nextBundleDiscount.tag === 'product_discount_card' ? 'discount_card' : nextBundleDiscount.tag;
|
|
1577
|
-
const nextDiscountDetail = {
|
|
1578
|
-
amount: nextBundleDiscAmount,
|
|
1579
|
-
type: nextBundleDiscTypeStr,
|
|
1580
|
-
discount: {
|
|
1581
|
-
discount_card_type: nextBundleDiscount?.metadata?.discount_card_type,
|
|
1582
|
-
fixed_amount: nextBundleDiscAmount,
|
|
1583
|
-
resource_id: nextBundleDiscount.id,
|
|
1584
|
-
title: nextBundleDiscount.format_title,
|
|
1585
|
-
original_amount: product.origin_total,
|
|
1586
|
-
product_id: product.id,
|
|
1587
|
-
percent: nextBundleDiscount.par_value,
|
|
1588
|
-
discount_product_id: nextBundleDiscount.product_id
|
|
1589
|
-
},
|
|
1590
|
-
metadata: {
|
|
1591
|
-
custom_product_bundle_map_id: nextUniqueId,
|
|
1592
|
-
num: 1
|
|
1593
|
-
},
|
|
1594
|
-
_num: 1,
|
|
1595
|
-
config: nextBundleDiscount?.config
|
|
1596
|
-
};
|
|
1597
|
-
const nextAppliedProducts = appliedDiscountProducts.get(nextBundleDiscount.id) || [];
|
|
1598
|
-
nextAppliedProducts.push(nextDiscountDetail);
|
|
1599
|
-
appliedDiscountProducts.set(nextBundleDiscount.id, nextAppliedProducts);
|
|
1600
|
-
processedItems.push({
|
|
1601
|
-
...flatItem,
|
|
1602
|
-
_id: nextUniqueId,
|
|
1603
|
-
num: 1,
|
|
1604
|
-
quantity: 1,
|
|
1605
|
-
price: nextDiscountedPrice,
|
|
1606
|
-
total: nextDiscountedPrice,
|
|
1607
|
-
discount_list: [nextDiscountDetail],
|
|
1608
|
-
processed: true,
|
|
1609
|
-
_discountId: nextBundleDiscount.id
|
|
1610
|
-
});
|
|
1611
|
-
continueSplitIndex++;
|
|
1612
|
-
}
|
|
1613
|
-
remainingNum -= nextSplitCount;
|
|
1614
1226
|
}
|
|
1615
1227
|
} else {
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
const currentCount = usedProductIdCounts.get(currentBundleDiscount.product_id) || 0;
|
|
1622
|
-
usedProductIdCounts.set(currentBundleDiscount.product_id, currentCount + 1);
|
|
1623
|
-
}
|
|
1624
|
-
// 🔥 更新折扣卡 applicableProductLimit 使用计数(不拆分时按商品数量计数)
|
|
1625
|
-
const noSplitDiscountType = currentBundleDiscount.tag || currentBundleDiscount.type;
|
|
1626
|
-
if (['discount_card', 'product_discount_card'].includes(noSplitDiscountType)) {
|
|
1627
|
-
const bundleQuantity = product.num || 1;
|
|
1628
|
-
const currentNoSplitCount = usedDiscountCardLimitCounts.get(currentBundleDiscount.id) || 0;
|
|
1629
|
-
usedDiscountCardLimitCounts.set(currentBundleDiscount.id, currentNoSplitCount + bundleQuantity);
|
|
1228
|
+
const selectedDiscount2 = selectedDiscountCard || applicableDiscounts[0];
|
|
1229
|
+
usedDiscounts.set(selectedDiscount2.id, true);
|
|
1230
|
+
if ((selectedDiscount2.tag || selectedDiscount2.type) === "good_pass") {
|
|
1231
|
+
const currentCount = usedProductIdCounts.get(selectedDiscount2.product_id) || 0;
|
|
1232
|
+
usedProductIdCounts.set(selectedDiscount2.product_id, currentCount + 1);
|
|
1630
1233
|
}
|
|
1631
1234
|
const productOriginTotal = product.original_price || product.price || 0;
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
const
|
|
1635
|
-
const orderLevelAllocation = isOrderLevel ? orderLevelDiscountAllocations.get(selectedDiscount.id) : null;
|
|
1636
|
-
const productAllocation = orderLevelAllocation?.get(flatItem._id);
|
|
1235
|
+
const isOrderLevel = (0, import_utils3.isOrderLevelFixedAmountDiscount)(selectedDiscount2);
|
|
1236
|
+
const orderLevelAllocation = isOrderLevel ? orderLevelDiscountAllocations.get(selectedDiscount2.id) : null;
|
|
1237
|
+
const productAllocation = orderLevelAllocation == null ? void 0 : orderLevelAllocation.get(flatItem._id);
|
|
1637
1238
|
let targetProductTotal;
|
|
1638
1239
|
let fixedAmountPerItem;
|
|
1639
1240
|
let productDiscountDifference;
|
|
1640
1241
|
if (isOrderLevel && productAllocation) {
|
|
1641
|
-
// order_level:使用预计算的单价折扣金额(已经是单价,无需再除以数量)
|
|
1642
1242
|
fixedAmountPerItem = productAllocation.discountAmount;
|
|
1643
1243
|
productDiscountDifference = productAllocation.difference;
|
|
1644
|
-
targetProductTotal = Math.max(new
|
|
1244
|
+
targetProductTotal = Math.max(new import_decimal.default(productOriginTotal).minus(fixedAmountPerItem).toNumber(), 0);
|
|
1645
1245
|
} else {
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1246
|
+
targetProductTotal = (0, import_utils.getDiscountAmount)(
|
|
1247
|
+
selectedDiscount2,
|
|
1248
|
+
productOriginTotal,
|
|
1249
|
+
productOriginTotal
|
|
1250
|
+
);
|
|
1251
|
+
fixedAmountPerItem = new import_decimal.default(productOriginTotal).minus(targetProductTotal).toNumber();
|
|
1649
1252
|
}
|
|
1650
|
-
|
|
1651
|
-
// 计算实际折扣金额
|
|
1652
|
-
const bundleActualDiscountAmount = new _decimal.default(productOriginTotal).minus(targetProductTotal).toNumber();
|
|
1653
|
-
|
|
1654
|
-
// 🔥 使用当前的 _id 作为唯一标识
|
|
1655
1253
|
const uniqueId = flatItem._id;
|
|
1656
1254
|
debugger;
|
|
1657
1255
|
const discountDetail = {
|
|
1658
|
-
amount:
|
|
1659
|
-
type:
|
|
1256
|
+
amount: fixedAmountPerItem * (product.num || 1),
|
|
1257
|
+
type: selectedDiscount2.tag === "product_discount_card" ? "discount_card" : selectedDiscount2.tag,
|
|
1660
1258
|
discount: {
|
|
1661
|
-
discount_card_type:
|
|
1662
|
-
fixed_amount:
|
|
1663
|
-
discount_calculation_mode:
|
|
1664
|
-
resource_id:
|
|
1665
|
-
title:
|
|
1259
|
+
discount_card_type: (_G = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _G.discount_card_type,
|
|
1260
|
+
fixed_amount: fixedAmountPerItem,
|
|
1261
|
+
discount_calculation_mode: (_H = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _H.discount_calculation_mode,
|
|
1262
|
+
resource_id: selectedDiscount2.id,
|
|
1263
|
+
title: selectedDiscount2.format_title,
|
|
1666
1264
|
original_amount: product.original_price,
|
|
1667
1265
|
product_id: product.id || product.product_id,
|
|
1668
|
-
percent:
|
|
1669
|
-
discount_product_id:
|
|
1266
|
+
percent: selectedDiscount2.par_value,
|
|
1267
|
+
discount_product_id: selectedDiscount2.product_id
|
|
1670
1268
|
},
|
|
1671
1269
|
metadata: {
|
|
1672
1270
|
// 🔥 使用唯一的 _id
|
|
1673
1271
|
custom_product_bundle_map_id: uniqueId,
|
|
1674
|
-
discount_rule_uncheck_flag:
|
|
1272
|
+
discount_rule_uncheck_flag: selectedDiscount2 == null ? void 0 : selectedDiscount2.discount_rule_uncheck_flag,
|
|
1675
1273
|
num: product.num || 1,
|
|
1676
1274
|
// 🔥 order_level 分摊差值
|
|
1677
|
-
...
|
|
1678
|
-
product_discount_difference: productDiscountDifference
|
|
1679
|
-
})
|
|
1275
|
+
...productDiscountDifference !== void 0 && { product_discount_difference: productDiscountDifference }
|
|
1680
1276
|
},
|
|
1681
|
-
config:
|
|
1682
|
-
_num: (product.num || 1) * (flatItem
|
|
1277
|
+
config: selectedDiscount2 == null ? void 0 : selectedDiscount2.config,
|
|
1278
|
+
_num: (product.num || 1) * (((_I = flatItem == null ? void 0 : flatItem.parentProduct) == null ? void 0 : _I.num) || 1)
|
|
1683
1279
|
};
|
|
1684
|
-
|
|
1685
|
-
// 记录实际应用的折扣
|
|
1686
|
-
const appliedProducts = appliedDiscountProducts.get(currentBundleDiscount.id) || [];
|
|
1280
|
+
const appliedProducts = appliedDiscountProducts.get(selectedDiscount2.id) || [];
|
|
1687
1281
|
appliedProducts.push(discountDetail);
|
|
1688
|
-
appliedDiscountProducts.set(
|
|
1282
|
+
appliedDiscountProducts.set(selectedDiscount2.id, appliedProducts);
|
|
1689
1283
|
processedItems.push({
|
|
1690
1284
|
...flatItem,
|
|
1691
1285
|
total: targetProductTotal,
|
|
1692
|
-
price: new
|
|
1693
|
-
discount_list: this.filterDiscountListByType(flatItem.discount_list,
|
|
1286
|
+
price: new import_decimal.default(productOriginTotal || 0).minus(fixedAmountPerItem).toNumber(),
|
|
1287
|
+
discount_list: this.filterDiscountListByType(flatItem.discount_list, "promotion").concat([discountDetail]),
|
|
1694
1288
|
processed: true
|
|
1695
1289
|
});
|
|
1696
1290
|
}
|
|
1697
1291
|
processedFlatItemsMap.set(flatItem._id, processedItems);
|
|
1698
1292
|
}
|
|
1699
1293
|
});
|
|
1700
|
-
|
|
1701
|
-
// 🔥 重组:将处理后的bundle子商品重新组装回主商品
|
|
1702
|
-
const reconstructProductsWithBundle = (processedProductsMap, processedFlatItemsMap, originalProductList) => {
|
|
1294
|
+
const reconstructProductsWithBundle = (processedProductsMap2, processedFlatItemsMap2, originalProductList) => {
|
|
1703
1295
|
const result = [];
|
|
1704
|
-
originalProductList.forEach(originProduct => {
|
|
1296
|
+
originalProductList.forEach((originProduct) => {
|
|
1705
1297
|
const product = this.hooks.getProduct(originProduct);
|
|
1706
|
-
|
|
1707
|
-
// 获取主商品处理结果
|
|
1708
|
-
const mainProductArr = processedProductsMap.get(product._id);
|
|
1298
|
+
const mainProductArr = processedProductsMap2.get(product._id);
|
|
1709
1299
|
if (!mainProductArr || mainProductArr.length === 0) {
|
|
1710
|
-
// 如果没有处理结果,返回默认商品(还原 option 价格)
|
|
1711
1300
|
const getDefaultProduct = () => {
|
|
1712
1301
|
const restoredOptions = restoreOptionPrices(product.options);
|
|
1713
1302
|
if (product.isClient) {
|
|
1714
1303
|
return this.hooks.setProduct(originProduct, {
|
|
1715
|
-
discount_list: this.filterDiscountListByType(product.discount_list,
|
|
1304
|
+
discount_list: this.filterDiscountListByType(product.discount_list, "promotion"),
|
|
1716
1305
|
price: product.price,
|
|
1717
|
-
origin_total: (0,
|
|
1306
|
+
origin_total: (0, import_utils2.getProductOriginTotalPrice)({
|
|
1718
1307
|
product: {
|
|
1719
1308
|
original_price: product.original_price
|
|
1720
1309
|
},
|
|
@@ -1723,7 +1312,7 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
1723
1312
|
}),
|
|
1724
1313
|
variant: originProduct._productInit.variant,
|
|
1725
1314
|
original_price: originProduct._productInit.original_price,
|
|
1726
|
-
total: (0,
|
|
1315
|
+
total: (0, import_utils2.getProductTotalPrice)({
|
|
1727
1316
|
product: {
|
|
1728
1317
|
price: product.price
|
|
1729
1318
|
},
|
|
@@ -1734,7 +1323,7 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
1734
1323
|
});
|
|
1735
1324
|
} else {
|
|
1736
1325
|
return this.hooks.setProduct(originProduct, {
|
|
1737
|
-
discount_list: this.filterDiscountListByType(product.discount_list,
|
|
1326
|
+
discount_list: this.filterDiscountListByType(product.discount_list, "promotion"),
|
|
1738
1327
|
total: product.total,
|
|
1739
1328
|
origin_total: product.origin_total,
|
|
1740
1329
|
price: product.price,
|
|
@@ -1745,359 +1334,325 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
1745
1334
|
result.push(getDefaultProduct());
|
|
1746
1335
|
return;
|
|
1747
1336
|
}
|
|
1748
|
-
|
|
1749
|
-
// 检查是否有bundle子商品需要重组
|
|
1750
1337
|
const hasBundle = product.bundle && Array.isArray(product.bundle) && product.bundle.length > 0;
|
|
1751
1338
|
if (!hasBundle) {
|
|
1752
|
-
// 没有bundle,直接使用主商品处理结果
|
|
1753
1339
|
result.push(...mainProductArr);
|
|
1754
1340
|
} else {
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
const bundleProcessingInfo = new Map();
|
|
1758
|
-
let hasGoodPassApplied = false; // 标记是否有子商品应用了商品券
|
|
1759
|
-
|
|
1341
|
+
const bundleProcessingInfo = /* @__PURE__ */ new Map();
|
|
1342
|
+
let hasGoodPassApplied = false;
|
|
1760
1343
|
if (product.bundle && Array.isArray(product.bundle)) {
|
|
1761
1344
|
product.bundle.forEach((bundleItem, bundleIndex) => {
|
|
1762
1345
|
const bundleItemId = `${product._id}_bundle_${bundleIndex}`;
|
|
1763
|
-
const processedBundleItems =
|
|
1346
|
+
const processedBundleItems = processedFlatItemsMap2.get(bundleItemId);
|
|
1764
1347
|
if (!processedBundleItems || processedBundleItems.length === 0) {
|
|
1765
|
-
// 未处理的bundle item,保持原样
|
|
1766
1348
|
bundleProcessingInfo.set(bundleIndex, [bundleItem]);
|
|
1767
1349
|
} else {
|
|
1768
|
-
// 处理过的bundle item
|
|
1769
1350
|
bundleProcessingInfo.set(bundleIndex, processedBundleItems);
|
|
1770
|
-
|
|
1771
|
-
|
|
1351
|
+
const hasGoodPass = processedBundleItems.some(
|
|
1352
|
+
(item) => {
|
|
1353
|
+
var _a2;
|
|
1354
|
+
return (_a2 = item.discount_list) == null ? void 0 : _a2.some(
|
|
1355
|
+
(discount) => discount.type === "good_pass" || discount.tag === "good_pass"
|
|
1356
|
+
);
|
|
1357
|
+
}
|
|
1358
|
+
);
|
|
1772
1359
|
if (hasGoodPass) {
|
|
1773
1360
|
hasGoodPassApplied = true;
|
|
1774
1361
|
}
|
|
1775
1362
|
}
|
|
1776
1363
|
});
|
|
1777
1364
|
}
|
|
1778
|
-
|
|
1779
|
-
// 🔥 2. 如果有子商品应用了商品券,且主商品数量大于1,需要拆分主商品
|
|
1780
1365
|
const mainProductQuantity = mainProductArr[0] ? this.hooks.getProduct(mainProductArr[0]).quantity : 1;
|
|
1781
1366
|
if (hasGoodPassApplied && mainProductArr.length === 1 && mainProductQuantity > 1) {
|
|
1782
1367
|
const mainProduct = mainProductArr[0];
|
|
1783
1368
|
const mainProductData = this.hooks.getProduct(mainProduct);
|
|
1784
|
-
|
|
1785
|
-
// 🔥 方案:拆分成2个主商品
|
|
1786
|
-
// 1. 一个主商品(qty=1)包含拆分后的bundle
|
|
1787
|
-
// 2. 一个主商品(qty=原quantity-1)包含原始未拆分的bundle
|
|
1788
|
-
|
|
1789
|
-
// 第一个:包含拆分后的bundle (qty=1)
|
|
1790
1369
|
const newBundleWithDiscount = [];
|
|
1791
|
-
(product.bundle || []).forEach(
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
});
|
|
1816
|
-
} else {
|
|
1817
|
-
// 未拆分的子商品,保持原样
|
|
1818
|
-
const item = processedItems[0];
|
|
1819
|
-
if (item.processed) {
|
|
1820
|
-
// 🔥 同样需要更新 discount_list 中的 num
|
|
1821
|
-
const updatedDiscountList = (item.discount_list || []).map(discount => ({
|
|
1822
|
-
...discount,
|
|
1823
|
-
metadata: {
|
|
1824
|
-
...discount.metadata,
|
|
1370
|
+
(product.bundle || []).forEach(
|
|
1371
|
+
(bundleItem, bundleIndex) => {
|
|
1372
|
+
const processedItems = bundleProcessingInfo.get(
|
|
1373
|
+
bundleIndex
|
|
1374
|
+
) || [bundleItem];
|
|
1375
|
+
if (processedItems.length > 1) {
|
|
1376
|
+
processedItems.forEach((item) => {
|
|
1377
|
+
const updatedDiscountList2 = (item.discount_list || []).map((discount) => {
|
|
1378
|
+
var _a2;
|
|
1379
|
+
return {
|
|
1380
|
+
...discount,
|
|
1381
|
+
metadata: {
|
|
1382
|
+
...discount.metadata,
|
|
1383
|
+
num: item.num,
|
|
1384
|
+
custom_product_bundle_map_id: (_a2 = item.metadata) == null ? void 0 : _a2.custom_product_bundle_map_id
|
|
1385
|
+
}
|
|
1386
|
+
// num: item.num, // 使用拆分后的 num
|
|
1387
|
+
};
|
|
1388
|
+
});
|
|
1389
|
+
newBundleWithDiscount.push({
|
|
1390
|
+
...bundleItem,
|
|
1391
|
+
_id: item._id,
|
|
1392
|
+
product_id: bundleItem.product_id,
|
|
1393
|
+
price: item.price,
|
|
1825
1394
|
num: item.num,
|
|
1826
|
-
|
|
1827
|
-
}
|
|
1828
|
-
// num: item.num, // 使用当前的 num
|
|
1829
|
-
}));
|
|
1830
|
-
newBundleWithDiscount.push({
|
|
1831
|
-
...bundleItem,
|
|
1832
|
-
_id: item._id,
|
|
1833
|
-
product_id: bundleItem.product_id,
|
|
1834
|
-
price: item.price,
|
|
1835
|
-
num: item.num,
|
|
1836
|
-
quantity: item.num,
|
|
1837
|
-
discount_list: updatedDiscountList
|
|
1395
|
+
discount_list: updatedDiscountList2
|
|
1396
|
+
});
|
|
1838
1397
|
});
|
|
1839
1398
|
} else {
|
|
1840
|
-
|
|
1399
|
+
const item = processedItems[0];
|
|
1400
|
+
if (item.processed) {
|
|
1401
|
+
const updatedDiscountList2 = (item.discount_list || []).map((discount) => {
|
|
1402
|
+
var _a2;
|
|
1403
|
+
return {
|
|
1404
|
+
...discount,
|
|
1405
|
+
metadata: {
|
|
1406
|
+
...discount.metadata,
|
|
1407
|
+
num: item.num,
|
|
1408
|
+
custom_product_bundle_map_id: (_a2 = item.metadata) == null ? void 0 : _a2.custom_product_bundle_map_id
|
|
1409
|
+
}
|
|
1410
|
+
// num: item.num, // 使用当前的 num
|
|
1411
|
+
};
|
|
1412
|
+
});
|
|
1413
|
+
newBundleWithDiscount.push({
|
|
1414
|
+
...bundleItem,
|
|
1415
|
+
_id: item._id,
|
|
1416
|
+
product_id: bundleItem.product_id,
|
|
1417
|
+
price: item.price,
|
|
1418
|
+
num: item.num,
|
|
1419
|
+
discount_list: updatedDiscountList2
|
|
1420
|
+
});
|
|
1421
|
+
} else {
|
|
1422
|
+
newBundleWithDiscount.push(item);
|
|
1423
|
+
}
|
|
1841
1424
|
}
|
|
1842
1425
|
}
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
// 计算第一个主商品的总价(包含拆分后的bundle)
|
|
1426
|
+
);
|
|
1846
1427
|
let newTotalWithDiscount = Number(mainProductData.price || 0);
|
|
1847
|
-
let newOriginTotalWithDiscount = Number(
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
const updatedMainDiscountList = mainProductData.discount_list.map(discount => {
|
|
1851
|
-
|
|
1852
|
-
|
|
1428
|
+
let newOriginTotalWithDiscount = Number(
|
|
1429
|
+
mainProductData.original_price || mainProductData.price || 0
|
|
1430
|
+
);
|
|
1431
|
+
const updatedMainDiscountList = mainProductData.discount_list.map((discount) => {
|
|
1432
|
+
var _a2, _b;
|
|
1433
|
+
if ((_a2 = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a2.custom_product_bundle_map_id) {
|
|
1853
1434
|
return discount;
|
|
1854
1435
|
}
|
|
1855
|
-
// 主商品自己的discount,更新num为1
|
|
1856
1436
|
return {
|
|
1857
1437
|
...discount,
|
|
1858
1438
|
// num: 1,
|
|
1859
1439
|
metadata: {
|
|
1860
1440
|
...discount.metadata,
|
|
1861
|
-
custom_product_bundle_map_id: discount
|
|
1441
|
+
custom_product_bundle_map_id: (_b = discount == null ? void 0 : discount.metadata) == null ? void 0 : _b.custom_product_bundle_map_id,
|
|
1862
1442
|
num: 1
|
|
1863
1443
|
}
|
|
1864
1444
|
};
|
|
1865
1445
|
});
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1446
|
+
const mainDiscountList = updatedMainDiscountList.filter(
|
|
1447
|
+
(item) => {
|
|
1448
|
+
var _a2;
|
|
1449
|
+
return !((_a2 = item == null ? void 0 : item.metadata) == null ? void 0 : _a2.custom_product_bundle_map_id);
|
|
1450
|
+
}
|
|
1451
|
+
);
|
|
1869
1452
|
if (mainDiscountList && mainDiscountList.length > 0) {
|
|
1870
|
-
const allDiscountAmount = (0,
|
|
1871
|
-
newTotalWithDiscount = new
|
|
1453
|
+
const allDiscountAmount = (0, import_utils.getDiscountListAmountTotal)(mainDiscountList);
|
|
1454
|
+
newTotalWithDiscount = new import_decimal.default(mainProductData.price || 0).minus(allDiscountAmount).toNumber() ?? newTotalWithDiscount;
|
|
1872
1455
|
newOriginTotalWithDiscount = mainProductData.origin_total ?? newOriginTotalWithDiscount;
|
|
1873
1456
|
}
|
|
1874
|
-
|
|
1875
|
-
// 累加bundle的价格(只累加一次)
|
|
1876
1457
|
if (newBundleWithDiscount.length > 0) {
|
|
1877
|
-
newBundleWithDiscount.forEach(item => {
|
|
1458
|
+
newBundleWithDiscount.forEach((item) => {
|
|
1878
1459
|
newTotalWithDiscount += Number(item.price) * Number(item.num);
|
|
1879
1460
|
});
|
|
1880
|
-
newBundleWithDiscount.forEach(item => {
|
|
1881
|
-
|
|
1461
|
+
newBundleWithDiscount.forEach((item) => {
|
|
1462
|
+
var _a2, _b, _c;
|
|
1463
|
+
const originalPrice = ((_c = (_b = (_a2 = item.discount_list) == null ? void 0 : _a2[0]) == null ? void 0 : _b.discount) == null ? void 0 : _c.original_amount) || item.price;
|
|
1882
1464
|
newOriginTotalWithDiscount += Number(originalPrice) * Number(item.num);
|
|
1883
1465
|
});
|
|
1884
1466
|
}
|
|
1885
|
-
|
|
1886
|
-
// 累加options的价格(options不参与折扣,在最终设置total时处理)
|
|
1887
|
-
if (product?.options) {
|
|
1467
|
+
if (product == null ? void 0 : product.options) {
|
|
1888
1468
|
newTotalWithDiscount = product.options.reduce((accumulator, currentValue) => {
|
|
1889
|
-
const currentPrice = new
|
|
1890
|
-
const currentNum = new
|
|
1469
|
+
const currentPrice = new import_decimal.default(currentValue.price || 0);
|
|
1470
|
+
const currentNum = new import_decimal.default(currentValue.num || 0);
|
|
1891
1471
|
return accumulator.add(currentPrice.mul(currentNum));
|
|
1892
|
-
}, new
|
|
1472
|
+
}, new import_decimal.default(newTotalWithDiscount)).toNumber();
|
|
1893
1473
|
}
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
// 第二个:包含原始bundle (qty=原quantity-1)
|
|
1474
|
+
result.push(
|
|
1475
|
+
this.hooks.setProduct(mainProduct, {
|
|
1476
|
+
...mainProductData,
|
|
1477
|
+
_id: `${mainProductData._id.split("___")[0]}___split_discount`,
|
|
1478
|
+
quantity: 1,
|
|
1479
|
+
discount_list: updatedMainDiscountList,
|
|
1480
|
+
bundle: newBundleWithDiscount,
|
|
1481
|
+
total: new import_decimal.default(newTotalWithDiscount).toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP).toNumber(),
|
|
1482
|
+
origin_total: new import_decimal.default(newOriginTotalWithDiscount).toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP).toNumber()
|
|
1483
|
+
})
|
|
1484
|
+
);
|
|
1907
1485
|
if (mainProductQuantity > 1) {
|
|
1908
1486
|
const newBundleOriginal = [];
|
|
1909
|
-
(product.bundle || []).forEach(
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
// 计算第二个主商品的总价
|
|
1487
|
+
(product.bundle || []).forEach(
|
|
1488
|
+
(bundleItem, bundleIndex) => {
|
|
1489
|
+
newBundleOriginal.push({
|
|
1490
|
+
...bundleItem,
|
|
1491
|
+
discount_list: []
|
|
1492
|
+
});
|
|
1493
|
+
}
|
|
1494
|
+
);
|
|
1918
1495
|
let newTotalOriginal = Number(mainProductData.price || 0);
|
|
1919
|
-
let newOriginTotalOriginal = Number(
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
const updatedMainDiscountListOriginal = mainProductData.discount_list.map(discount => {
|
|
1923
|
-
|
|
1924
|
-
|
|
1496
|
+
let newOriginTotalOriginal = Number(
|
|
1497
|
+
mainProductData.original_price || mainProductData.price || 0
|
|
1498
|
+
);
|
|
1499
|
+
const updatedMainDiscountListOriginal = mainProductData.discount_list.map((discount) => {
|
|
1500
|
+
var _a2, _b;
|
|
1501
|
+
if ((_a2 = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a2.custom_product_bundle_map_id) {
|
|
1925
1502
|
return discount;
|
|
1926
1503
|
}
|
|
1927
|
-
// 主商品自己的discount,更新num为 mainProductQuantity - 1
|
|
1928
1504
|
return {
|
|
1929
1505
|
...discount,
|
|
1930
1506
|
metadata: {
|
|
1931
1507
|
...discount.metadata,
|
|
1932
1508
|
num: mainProductQuantity - 1,
|
|
1933
|
-
custom_product_bundle_map_id: discount
|
|
1509
|
+
custom_product_bundle_map_id: (_b = discount == null ? void 0 : discount.metadata) == null ? void 0 : _b.custom_product_bundle_map_id
|
|
1934
1510
|
}
|
|
1935
1511
|
// num: mainProductQuantity - 1,
|
|
1936
1512
|
};
|
|
1937
1513
|
});
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1514
|
+
const mainDiscountListOriginal = updatedMainDiscountListOriginal.filter(
|
|
1515
|
+
(item) => {
|
|
1516
|
+
var _a2;
|
|
1517
|
+
return !((_a2 = item == null ? void 0 : item.metadata) == null ? void 0 : _a2.custom_product_bundle_map_id);
|
|
1518
|
+
}
|
|
1519
|
+
);
|
|
1941
1520
|
if (mainDiscountListOriginal && mainDiscountListOriginal.length > 0) {
|
|
1942
|
-
const allDiscountAmount = (0,
|
|
1943
|
-
|
|
1521
|
+
const allDiscountAmount = (0, import_utils.getDiscountListAmount)(
|
|
1522
|
+
mainDiscountListOriginal
|
|
1523
|
+
);
|
|
1524
|
+
newTotalOriginal = new import_decimal.default(mainProductData.price || 0).minus(allDiscountAmount).toNumber() ?? newTotalOriginal;
|
|
1944
1525
|
newOriginTotalOriginal = mainProductData.origin_total ?? newOriginTotalOriginal;
|
|
1945
1526
|
}
|
|
1946
|
-
|
|
1947
|
-
// 累加bundle的价格(只累加一次)
|
|
1948
1527
|
if (newBundleOriginal.length > 0) {
|
|
1949
|
-
newBundleOriginal.forEach(item => {
|
|
1528
|
+
newBundleOriginal.forEach((item) => {
|
|
1950
1529
|
newTotalOriginal += Number(item.price) * Number(item.num);
|
|
1951
1530
|
newOriginTotalOriginal += Number(item.price) * Number(item.num);
|
|
1952
1531
|
});
|
|
1953
1532
|
}
|
|
1954
|
-
|
|
1955
|
-
// 累加options的价格(options不参与折扣,在最终设置total时处理)
|
|
1956
|
-
if (product?.options) {
|
|
1533
|
+
if (product == null ? void 0 : product.options) {
|
|
1957
1534
|
newTotalOriginal = product.options.reduce((accumulator, currentValue) => {
|
|
1958
|
-
const currentPrice = new
|
|
1959
|
-
const currentNum = new
|
|
1535
|
+
const currentPrice = new import_decimal.default(currentValue.price || 0);
|
|
1536
|
+
const currentNum = new import_decimal.default(currentValue.num || 0);
|
|
1960
1537
|
return accumulator.add(currentPrice.mul(currentNum));
|
|
1961
|
-
}, new
|
|
1538
|
+
}, new import_decimal.default(newTotalOriginal)).toNumber();
|
|
1962
1539
|
}
|
|
1963
|
-
newTotalOriginal = new
|
|
1964
|
-
newOriginTotalOriginal = new
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1540
|
+
newTotalOriginal = new import_decimal.default(newTotalOriginal).toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP).toNumber();
|
|
1541
|
+
newOriginTotalOriginal = new import_decimal.default(newOriginTotalOriginal).toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP).toNumber();
|
|
1542
|
+
result.push(
|
|
1543
|
+
this.hooks.setProduct(mainProduct, {
|
|
1544
|
+
...mainProductData,
|
|
1545
|
+
_id: `${mainProductData._id.split("___")[0]}___split_normal`,
|
|
1546
|
+
quantity: mainProductQuantity - 1,
|
|
1547
|
+
discount_list: updatedMainDiscountListOriginal,
|
|
1548
|
+
bundle: newBundleOriginal,
|
|
1549
|
+
total: newTotalOriginal,
|
|
1550
|
+
origin_total: newOriginTotalOriginal
|
|
1551
|
+
})
|
|
1552
|
+
);
|
|
1976
1553
|
}
|
|
1977
1554
|
} else {
|
|
1978
|
-
|
|
1979
|
-
|
|
1555
|
+
mainProductArr.forEach((mainProduct) => {
|
|
1556
|
+
var _a2, _b, _c;
|
|
1980
1557
|
const mainProductData = this.hooks.getProduct(mainProduct);
|
|
1981
|
-
|
|
1982
|
-
// 重组bundle
|
|
1983
1558
|
const newBundle = [];
|
|
1984
1559
|
if (product.bundle && Array.isArray(product.bundle)) {
|
|
1985
1560
|
product.bundle.forEach((bundleItem, bundleIndex) => {
|
|
1986
1561
|
const bundleItemId = `${product._id}_bundle_${bundleIndex}`;
|
|
1987
|
-
const processedBundleItems =
|
|
1562
|
+
const processedBundleItems = processedFlatItemsMap2.get(bundleItemId);
|
|
1988
1563
|
if (!processedBundleItems || processedBundleItems.length === 0) {
|
|
1989
|
-
// 未处理的bundle item,保持原样
|
|
1990
1564
|
newBundle.push(bundleItem);
|
|
1991
1565
|
} else {
|
|
1992
|
-
|
|
1993
|
-
processedBundleItems.forEach(item => {
|
|
1566
|
+
processedBundleItems.forEach((item) => {
|
|
1994
1567
|
const nextBundlePrice = item.price ?? bundleItem.price;
|
|
1995
1568
|
const nextBundleSellingPrice = item.bundle_selling_price ?? item.price ?? bundleItem.bundle_selling_price;
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
1569
|
+
const updatedDiscountList2 = (item.discount_list || []).map((discount) => {
|
|
1570
|
+
var _a3;
|
|
1571
|
+
return {
|
|
1572
|
+
...discount,
|
|
1573
|
+
metadata: {
|
|
1574
|
+
...discount.metadata,
|
|
1575
|
+
num: item.num,
|
|
1576
|
+
custom_product_bundle_map_id: (_a3 = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a3.custom_product_bundle_map_id
|
|
1577
|
+
}
|
|
1578
|
+
// num: item.num, // 使用拆分后的 num
|
|
1579
|
+
};
|
|
1580
|
+
});
|
|
2006
1581
|
newBundle.push({
|
|
2007
1582
|
...bundleItem,
|
|
2008
1583
|
_id: item._id,
|
|
2009
1584
|
product_id: bundleItem.product_id,
|
|
2010
1585
|
price: nextBundlePrice,
|
|
2011
1586
|
num: item.num,
|
|
2012
|
-
discount_list:
|
|
2013
|
-
bundle_selling_price: bundleItem.bundle_selling_price !==
|
|
1587
|
+
discount_list: updatedDiscountList2,
|
|
1588
|
+
bundle_selling_price: bundleItem.bundle_selling_price !== void 0 ? nextBundleSellingPrice : void 0
|
|
2014
1589
|
});
|
|
2015
1590
|
});
|
|
2016
1591
|
}
|
|
2017
1592
|
});
|
|
2018
1593
|
}
|
|
2019
|
-
|
|
2020
|
-
// 主商品已经在前面的 setProduct 中应用过折扣;这里只替换 bundle,
|
|
2021
|
-
// 避免把主商品 discount_list 再扣一次。
|
|
2022
1594
|
const mainSellingPrice = mainProductData.main_product_selling_price ?? mainProductData.price ?? 0;
|
|
2023
1595
|
let newTotal = Number(mainSellingPrice || 0);
|
|
2024
1596
|
let newOriginTotal = Number(mainProductData.original_price || mainProductData.price || 0);
|
|
2025
|
-
|
|
2026
|
-
// 判断是否是手动折扣
|
|
2027
|
-
const isManualDiscount = typeof mainProductData.isManualDiscount === 'boolean' ? mainProductData.isManualDiscount : mainProductData.total != mainProductData.origin_total && (!mainProductData.discount_list?.length || mainProductData?.discount_list?.every?.(item => item.type === 'product'));
|
|
2028
|
-
|
|
2029
|
-
// 如果是手动折扣,使用原有的total和origin_total,不重新计算
|
|
1597
|
+
const isManualDiscount = typeof mainProductData.isManualDiscount === "boolean" ? mainProductData.isManualDiscount : mainProductData.total != mainProductData.origin_total && (!((_a2 = mainProductData.discount_list) == null ? void 0 : _a2.length) || ((_c = (_b = mainProductData == null ? void 0 : mainProductData.discount_list) == null ? void 0 : _b.every) == null ? void 0 : _c.call(_b, (item) => item.type === "product")));
|
|
2030
1598
|
if (isManualDiscount) {
|
|
2031
1599
|
newTotal = mainProductData.total ?? newTotal;
|
|
2032
1600
|
newOriginTotal = mainProductData.origin_total ?? newOriginTotal;
|
|
2033
1601
|
} else {
|
|
2034
|
-
// 累加bundle的折后价格(只累加一次)
|
|
2035
1602
|
if (newBundle.length > 0) {
|
|
2036
|
-
newBundle.forEach(item => {
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
newOriginTotal += Number(originalPrice) * Number(item.num);
|
|
1603
|
+
newBundle.forEach((item) => {
|
|
1604
|
+
const bundleSellingPrice = item.bundle_selling_price ?? item.price;
|
|
1605
|
+
newTotal += Number(bundleSellingPrice) * Number(item.num);
|
|
2040
1606
|
});
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
const originalPrice = item.discount_list
|
|
1607
|
+
newBundle.forEach((item) => {
|
|
1608
|
+
var _a3, _b2, _c2;
|
|
1609
|
+
const originalPrice = ((_c2 = (_b2 = (_a3 = item.discount_list) == null ? void 0 : _a3[0]) == null ? void 0 : _b2.discount) == null ? void 0 : _c2.original_amount) || item.price;
|
|
2044
1610
|
newOriginTotal += Number(originalPrice) * Number(item.num);
|
|
2045
1611
|
});
|
|
2046
1612
|
}
|
|
2047
1613
|
}
|
|
2048
|
-
|
|
2049
|
-
// 累加options的价格(options不参与折扣,在最终设置total时处理)
|
|
2050
|
-
if (product?.options) {
|
|
1614
|
+
if (product == null ? void 0 : product.options) {
|
|
2051
1615
|
newTotal = product.options.reduce((accumulator, currentValue) => {
|
|
2052
|
-
const currentPrice = new
|
|
2053
|
-
const currentNum = new
|
|
1616
|
+
const currentPrice = new import_decimal.default(currentValue.price || 0);
|
|
1617
|
+
const currentNum = new import_decimal.default(currentValue.num || 0);
|
|
2054
1618
|
return accumulator.add(currentPrice.mul(currentNum));
|
|
2055
|
-
}, new
|
|
1619
|
+
}, new import_decimal.default(newTotal)).toNumber();
|
|
2056
1620
|
}
|
|
2057
|
-
newTotal = new
|
|
2058
|
-
newOriginTotal = new
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
1621
|
+
newTotal = new import_decimal.default(newTotal).toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP).toNumber();
|
|
1622
|
+
newOriginTotal = new import_decimal.default(newOriginTotal).toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP).toNumber();
|
|
1623
|
+
result.push(
|
|
1624
|
+
this.hooks.setProduct(mainProduct, {
|
|
1625
|
+
...mainProductData,
|
|
1626
|
+
bundle: newBundle,
|
|
1627
|
+
total: newTotal,
|
|
1628
|
+
origin_total: newOriginTotal
|
|
1629
|
+
})
|
|
1630
|
+
);
|
|
2067
1631
|
});
|
|
2068
1632
|
}
|
|
2069
1633
|
}
|
|
2070
1634
|
});
|
|
2071
1635
|
return result;
|
|
2072
1636
|
};
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
const updatedDiscountList = addModeDiscount.map(discount => {
|
|
2079
|
-
// 获取此优惠券适用的商品列表
|
|
1637
|
+
const processedProductList = reconstructProductsWithBundle(
|
|
1638
|
+
processedProductsMap,
|
|
1639
|
+
processedFlatItemsMap,
|
|
1640
|
+
productList
|
|
1641
|
+
);
|
|
1642
|
+
const updatedDiscountList = addModeDiscount.map((discount) => {
|
|
2080
1643
|
const applicableProducts = discountApplicability.get(discount.id) || [];
|
|
2081
|
-
|
|
2082
|
-
// 获取此优惠券适用的商品详情
|
|
2083
1644
|
const applicableProductDetails = discountApplicableProducts.get(discount.id) || [];
|
|
2084
|
-
|
|
2085
|
-
// 获取此优惠券实际应用的商品详情
|
|
2086
1645
|
const appliedProductDetails = appliedDiscountProducts.get(discount.id) || [];
|
|
2087
|
-
|
|
2088
|
-
// 根据是否有适用商品决定isAvailable
|
|
2089
1646
|
const isAvailable = applicableProducts.length > 0;
|
|
2090
|
-
|
|
2091
|
-
// 如果此优惠券被明确设置为不选中,保持其状态,但正确设置isAvailable
|
|
2092
|
-
if (typeof discount.isSelected === 'boolean' && discount.isSelected === false && discount.isManualSelect) {
|
|
1647
|
+
if (typeof discount.isSelected === "boolean" && discount.isSelected === false && discount.isManualSelect) {
|
|
2093
1648
|
return {
|
|
2094
1649
|
...discount,
|
|
2095
1650
|
isSelected: false,
|
|
2096
|
-
isAvailable
|
|
1651
|
+
isAvailable,
|
|
2097
1652
|
// 正确设置可用性
|
|
2098
1653
|
applicableProductIds: applicableProducts,
|
|
2099
1654
|
// 添加可抵扣的商品详情
|
|
2100
|
-
applicableProductDetails
|
|
1655
|
+
applicableProductDetails,
|
|
2101
1656
|
// 添加实际抵扣的商品详情(对于未选中的优惠券,为空数组)
|
|
2102
1657
|
appliedProductDetails: []
|
|
2103
1658
|
};
|
|
@@ -2106,20 +1661,18 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
2106
1661
|
return {
|
|
2107
1662
|
...discount,
|
|
2108
1663
|
isSelected: true,
|
|
2109
|
-
isManualSelect: options
|
|
1664
|
+
isManualSelect: (options == null ? void 0 : options.scan) ? false : discount.isManualSelect,
|
|
2110
1665
|
// 标记为可用,因为它已被应用
|
|
2111
1666
|
isAvailable: true,
|
|
2112
1667
|
// 记录适用的商品IDs
|
|
2113
1668
|
applicableProductIds: applicableProducts,
|
|
2114
1669
|
// 添加可抵扣的商品详情
|
|
2115
|
-
applicableProductDetails
|
|
1670
|
+
applicableProductDetails,
|
|
2116
1671
|
// 添加实际抵扣的商品详情
|
|
2117
|
-
appliedProductDetails
|
|
1672
|
+
appliedProductDetails
|
|
2118
1673
|
};
|
|
2119
1674
|
}
|
|
2120
|
-
let isSelected = typeof discount.isSelected ===
|
|
2121
|
-
|
|
2122
|
-
// 如果是可用的 并且没有手动标记 则设置为选中
|
|
1675
|
+
let isSelected = typeof discount.isSelected === "boolean" ? discount.isSelected : void 0;
|
|
2123
1676
|
if (isAvailable && appliedProductDetails.length && !discount.isManualSelect) {
|
|
2124
1677
|
isSelected = true;
|
|
2125
1678
|
} else if (!appliedProductDetails.length) {
|
|
@@ -2128,14 +1681,14 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
2128
1681
|
return {
|
|
2129
1682
|
...discount,
|
|
2130
1683
|
// 如果有适用的商品,标记为可用
|
|
2131
|
-
isAvailable
|
|
1684
|
+
isAvailable,
|
|
2132
1685
|
isSelected,
|
|
2133
1686
|
// 如果是扫码进来的,要手动设置为手动选择:false
|
|
2134
|
-
isManualSelect: options
|
|
1687
|
+
isManualSelect: (options == null ? void 0 : options.scan) ? false : discount.isManualSelect,
|
|
2135
1688
|
// 记录适用的商品IDs
|
|
2136
1689
|
applicableProductIds: applicableProducts,
|
|
2137
1690
|
// 添加可抵扣的商品详情
|
|
2138
|
-
applicableProductDetails
|
|
1691
|
+
applicableProductDetails,
|
|
2139
1692
|
// 添加实际抵扣的商品详情(对于未使用的优惠券,为空数组)
|
|
2140
1693
|
appliedProductDetails: []
|
|
2141
1694
|
};
|
|
@@ -2145,7 +1698,6 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
2145
1698
|
discountList: [...editModeDiscount, ...updatedDiscountList]
|
|
2146
1699
|
};
|
|
2147
1700
|
}
|
|
2148
|
-
|
|
2149
1701
|
/**
|
|
2150
1702
|
* 检查优惠是否符合 PackageSubItemUsageRules 配置
|
|
2151
1703
|
* @param discount 优惠券
|
|
@@ -2153,229 +1705,105 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
2153
1705
|
* @returns 是否可用
|
|
2154
1706
|
*/
|
|
2155
1707
|
checkPackageSubItemUsageRules(discount, flatItem) {
|
|
1708
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
2156
1709
|
const limitedData = discount.limited_relation_product_data;
|
|
2157
|
-
const usageRules = limitedData
|
|
2158
|
-
const rules = [
|
|
2159
|
-
|
|
2160
|
-
// 如果没有配置 package_sub_item_usage_rules,则默认可用
|
|
1710
|
+
const usageRules = limitedData == null ? void 0 : limitedData.package_sub_item_usage_rules;
|
|
1711
|
+
const rules = ["original_price", ...(usageRules == null ? void 0 : usageRules.rules) || []];
|
|
2161
1712
|
if (!usageRules) {
|
|
2162
1713
|
return true;
|
|
2163
1714
|
}
|
|
2164
1715
|
const ruleType = usageRules.type;
|
|
2165
|
-
|
|
2166
|
-
const
|
|
2167
|
-
const
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
include_bundle_product_ids = [],
|
|
2171
|
-
filter = 0
|
|
2172
|
-
} = packageScope || {};
|
|
2173
|
-
const isMainProduct = flatItem.type === 'main'; // 单独购买
|
|
2174
|
-
const isBundleItem = flatItem.type === 'bundle'; // 套餐中购买
|
|
2175
|
-
const bundleMainProductId = flatItem.product?.product_id;
|
|
2176
|
-
|
|
2177
|
-
// 主商品直接可用
|
|
1716
|
+
const packageScope = usageRules == null ? void 0 : usageRules.package_scope;
|
|
1717
|
+
const { type: scopeType, exclude_bundle_product_ids = [], include_bundle_product_ids = [], filter = 0 } = packageScope || {};
|
|
1718
|
+
const isMainProduct = flatItem.type === "main";
|
|
1719
|
+
const isBundleItem = flatItem.type === "bundle";
|
|
1720
|
+
const bundleMainProductId = (_a = flatItem.product) == null ? void 0 : _a.product_id;
|
|
2178
1721
|
if (isMainProduct) {
|
|
2179
1722
|
return true;
|
|
2180
1723
|
}
|
|
2181
|
-
|
|
2182
|
-
// universal_discount: 单独购买和套餐中(子商品为原价)均可使用
|
|
2183
|
-
if (ruleType === 'universal_discount') {
|
|
1724
|
+
if (ruleType === "universal_discount") {
|
|
2184
1725
|
if (isMainProduct) {
|
|
2185
|
-
return true;
|
|
1726
|
+
return true;
|
|
2186
1727
|
}
|
|
2187
1728
|
if (isBundleItem) {
|
|
2188
|
-
|
|
2189
|
-
const
|
|
2190
|
-
const
|
|
2191
|
-
|
|
2192
|
-
const
|
|
2193
|
-
// original_price 对应:
|
|
2194
|
-
// 1. price_type: "markup" && price_type_ext: "product_price"
|
|
2195
|
-
// markup_price 对应:
|
|
2196
|
-
// price_type: "markup" && price_type_ext: ""
|
|
2197
|
-
/** 原价 */
|
|
2198
|
-
const isOriginalPrice = priceType === 'markup' && priceTypeExt === 'product_price';
|
|
2199
|
-
/** 加价 */
|
|
2200
|
-
const isMarkupPrice = priceType === 'markup' && (priceTypeExt === '' || !priceTypeExt);
|
|
2201
|
-
|
|
2202
|
-
// 检查 rules
|
|
1729
|
+
const priceType = (_b = flatItem.bundleItem) == null ? void 0 : _b.price_type;
|
|
1730
|
+
const priceTypeExt = (_c = flatItem.bundleItem) == null ? void 0 : _c.price_type_ext;
|
|
1731
|
+
const mainProductId = ((_e = (_d = flatItem == null ? void 0 : flatItem.originProduct) == null ? void 0 : _d._productOrigin) == null ? void 0 : _e.id) || ((_f = flatItem == null ? void 0 : flatItem.parentProduct) == null ? void 0 : _f.id) || 0;
|
|
1732
|
+
const isOriginalPrice = priceType === "markup" && priceTypeExt === "product_price";
|
|
1733
|
+
const isMarkupPrice = priceType === "markup" && (priceTypeExt === "" || !priceTypeExt);
|
|
2203
1734
|
if (rules.length > 0) {
|
|
2204
|
-
const _isOriginalPrice = isOriginalPrice && rules.includes(
|
|
2205
|
-
const _isMarkupPrice = isMarkupPrice && rules.includes(
|
|
2206
|
-
// 价格是否符合规则:原价或加价
|
|
1735
|
+
const _isOriginalPrice = isOriginalPrice && rules.includes("original_price");
|
|
1736
|
+
const _isMarkupPrice = isMarkupPrice && rules.includes("markup_price");
|
|
2207
1737
|
const isPriceValid = _isOriginalPrice || _isMarkupPrice;
|
|
2208
|
-
// 套餐适用范围校验
|
|
2209
1738
|
let isScopeValid = false;
|
|
2210
|
-
|
|
2211
|
-
// 排除套餐判断, product_all值兼容旧数据
|
|
2212
|
-
if (scopeType === 'all_packages' || scopeType === 'product_all') {
|
|
2213
|
-
// 所有套餐可用
|
|
1739
|
+
if (scopeType === "all_packages" || scopeType === "product_all") {
|
|
2214
1740
|
if (!filter) {
|
|
2215
1741
|
isScopeValid = true;
|
|
2216
1742
|
} else {
|
|
2217
1743
|
isScopeValid = !exclude_bundle_product_ids.includes(Number(bundleMainProductId));
|
|
2218
1744
|
}
|
|
2219
1745
|
}
|
|
2220
|
-
|
|
2221
|
-
// 包含套餐判断, products值兼容旧数据
|
|
2222
|
-
if (scopeType === 'specific_packages' || scopeType === 'products') {
|
|
1746
|
+
if (scopeType === "specific_packages" || scopeType === "products") {
|
|
2223
1747
|
isScopeValid = include_bundle_product_ids.includes(Number(bundleMainProductId));
|
|
2224
1748
|
}
|
|
2225
|
-
|
|
2226
|
-
// 价格和套餐适用范围都符合,则可用
|
|
2227
1749
|
if (isPriceValid && isScopeValid) {
|
|
2228
1750
|
return true;
|
|
2229
1751
|
}
|
|
2230
|
-
|
|
2231
|
-
// 检查原价
|
|
2232
|
-
// if (isOriginalPrice && rules.includes('original_price')) {
|
|
2233
|
-
// return true;
|
|
2234
|
-
// }
|
|
2235
|
-
|
|
2236
|
-
// 检查加价
|
|
2237
|
-
// if (isMarkupPrice && rules.includes('markup_price')) {
|
|
2238
|
-
// return true;
|
|
2239
|
-
// }
|
|
2240
|
-
|
|
2241
|
-
// 如果都不匹配,则不可用
|
|
2242
1752
|
return false;
|
|
2243
1753
|
}
|
|
2244
|
-
|
|
2245
|
-
// 原价包括:price_type: "markup" && price_type_ext: "product_price"
|
|
2246
1754
|
return isOriginalPrice;
|
|
2247
1755
|
}
|
|
2248
1756
|
return true;
|
|
2249
1757
|
}
|
|
2250
|
-
|
|
2251
|
-
// package_exclusive: 仅在套餐中(子商品为原价)时可使用
|
|
2252
|
-
if (ruleType === 'package_exclusive') {
|
|
1758
|
+
if (ruleType === "package_exclusive") {
|
|
2253
1759
|
if (isMainProduct) {
|
|
2254
|
-
return false;
|
|
1760
|
+
return false;
|
|
2255
1761
|
}
|
|
2256
1762
|
if (isBundleItem) {
|
|
2257
|
-
|
|
2258
|
-
const
|
|
2259
|
-
const
|
|
2260
|
-
|
|
2261
|
-
// original_price 对应:
|
|
2262
|
-
// 1. price_type: "markup" && price_type_ext: "product_price"
|
|
2263
|
-
// markup_price 对应:
|
|
2264
|
-
// price_type: "markup" && price_type_ext: ""
|
|
2265
|
-
/** 原价 */
|
|
2266
|
-
const isOriginalPrice = priceType === 'markup' && priceTypeExt === 'product_price';
|
|
2267
|
-
/** 加价 */
|
|
2268
|
-
const isMarkupPrice = priceType === 'markup' && (priceTypeExt === '' || !priceTypeExt);
|
|
2269
|
-
|
|
2270
|
-
// 检查 rules
|
|
1763
|
+
const priceType = (_g = flatItem.bundleItem) == null ? void 0 : _g.price_type;
|
|
1764
|
+
const priceTypeExt = (_h = flatItem.bundleItem) == null ? void 0 : _h.price_type_ext;
|
|
1765
|
+
const isOriginalPrice = priceType === "markup" && priceTypeExt === "product_price";
|
|
1766
|
+
const isMarkupPrice = priceType === "markup" && (priceTypeExt === "" || !priceTypeExt);
|
|
2271
1767
|
if (rules.length > 0) {
|
|
2272
|
-
const _isOriginalPrice = isOriginalPrice && rules.includes(
|
|
2273
|
-
const _isMarkupPrice = isMarkupPrice && rules.includes(
|
|
2274
|
-
// 价格是否符合规则:原价或加价
|
|
1768
|
+
const _isOriginalPrice = isOriginalPrice && rules.includes("original_price");
|
|
1769
|
+
const _isMarkupPrice = isMarkupPrice && rules.includes("markup_price");
|
|
2275
1770
|
const isPriceValid = _isOriginalPrice || _isMarkupPrice;
|
|
2276
|
-
// 套餐适用范围校验
|
|
2277
1771
|
let isScopeValid = false;
|
|
2278
|
-
|
|
2279
|
-
// 排除套餐判断, product_all值兼容旧数据
|
|
2280
|
-
if (scopeType === 'all_packages' || scopeType === 'product_all') {
|
|
2281
|
-
// 所有套餐可用
|
|
1772
|
+
if (scopeType === "all_packages" || scopeType === "product_all") {
|
|
2282
1773
|
if (!filter) {
|
|
2283
1774
|
isScopeValid = true;
|
|
2284
1775
|
} else {
|
|
2285
1776
|
isScopeValid = !exclude_bundle_product_ids.includes(Number(bundleMainProductId));
|
|
2286
1777
|
}
|
|
2287
1778
|
}
|
|
2288
|
-
|
|
2289
|
-
// 包含套餐判断, products值兼容旧数据
|
|
2290
|
-
if (scopeType === 'specific_packages' || scopeType === 'products') {
|
|
1779
|
+
if (scopeType === "specific_packages" || scopeType === "products") {
|
|
2291
1780
|
isScopeValid = include_bundle_product_ids.includes(Number(bundleMainProductId));
|
|
2292
1781
|
}
|
|
2293
|
-
|
|
2294
|
-
// 价格和套餐适用范围都符合,则可用
|
|
2295
1782
|
if (isPriceValid && isScopeValid) {
|
|
2296
1783
|
return true;
|
|
2297
1784
|
}
|
|
2298
|
-
|
|
2299
|
-
// 检查原价
|
|
2300
|
-
// if (isOriginalPrice && rules.includes('original_price')) {
|
|
2301
|
-
// return true;
|
|
2302
|
-
// }
|
|
2303
|
-
|
|
2304
|
-
// 检查加价
|
|
2305
|
-
// if (isMarkupPrice && rules.includes('markup_price')) {
|
|
2306
|
-
// return true;
|
|
2307
|
-
// }
|
|
2308
|
-
|
|
2309
|
-
// 如果都不匹配,则不可用
|
|
2310
1785
|
return false;
|
|
2311
1786
|
}
|
|
2312
|
-
|
|
2313
|
-
// 原价包括:price_type: "markup" && price_type_ext: "product_price"
|
|
2314
1787
|
return isOriginalPrice;
|
|
2315
1788
|
}
|
|
2316
1789
|
return false;
|
|
2317
1790
|
}
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
if (ruleType === 'single_item_promo') {
|
|
2321
|
-
return isMainProduct; // 只有单独购买时可用
|
|
2322
|
-
}
|
|
2323
|
-
|
|
2324
|
-
/*
|
|
2325
|
-
// custom_usage_rules: 根据自定义规则判断
|
|
2326
|
-
if (ruleType === 'custom_usage_rules') {
|
|
2327
|
-
const customRules = usageRules.custom_usage_rules;
|
|
2328
|
-
if (!customRules) {
|
|
2329
|
-
return true; // 如果没有自定义规则,默认可用
|
|
2330
|
-
}
|
|
2331
|
-
const { types, package_sub_item_rules } = customRules;
|
|
2332
|
-
// 判断商品类型是否在允许的类型中
|
|
2333
|
-
if (isMainProduct) {
|
|
2334
|
-
// 主商品对应 standalone_product
|
|
2335
|
-
if (!types.includes('standalone_product')) {
|
|
2336
|
-
return false;
|
|
2337
|
-
}
|
|
2338
|
-
return true; // 主商品不需要判断 package_sub_item_rules
|
|
2339
|
-
}
|
|
2340
|
-
if (isBundleItem) {
|
|
2341
|
-
// bundle子商品对应 package_sub_item
|
|
2342
|
-
if (!types.includes('package_sub_item')) {
|
|
2343
|
-
return false;
|
|
2344
|
-
}
|
|
2345
|
-
// 如果包含 package_sub_item,还需要判断 price_type
|
|
2346
|
-
const priceType = flatItem.bundleItem?.price_type;
|
|
2347
|
-
const priceTypeExt = flatItem.bundleItem?.price_type_ext;
|
|
2348
|
-
// 检查 package_sub_item_rules
|
|
2349
|
-
if (package_sub_item_rules && package_sub_item_rules.length > 0) {
|
|
2350
|
-
// original_price 对应:
|
|
2351
|
-
// 1. price_type: "markup" && price_type_ext: "product_price"
|
|
2352
|
-
// markup_price 对应:
|
|
2353
|
-
// price_type: "markup" && price_type_ext: ""
|
|
2354
|
-
const isOriginalPrice = (priceType === 'markup' && priceTypeExt === 'product_price');
|
|
2355
|
-
const isMarkupPrice = priceType === 'markup' && (priceTypeExt === '' || !priceTypeExt);
|
|
2356
|
-
if (isOriginalPrice && package_sub_item_rules.includes('original_price')) {
|
|
2357
|
-
return true;
|
|
2358
|
-
}
|
|
2359
|
-
if (isMarkupPrice && package_sub_item_rules.includes('markup_price')) {
|
|
2360
|
-
return true;
|
|
2361
|
-
}
|
|
2362
|
-
// 如果都不匹配,则不可用
|
|
2363
|
-
return false;
|
|
2364
|
-
}
|
|
2365
|
-
return true; // 如果没有 package_sub_item_rules 配置,默认可用
|
|
2366
|
-
}
|
|
2367
|
-
return true;
|
|
1791
|
+
if (ruleType === "single_item_promo") {
|
|
1792
|
+
return isMainProduct;
|
|
2368
1793
|
}
|
|
2369
|
-
* */
|
|
2370
|
-
|
|
2371
|
-
// 默认可用
|
|
2372
1794
|
return true;
|
|
2373
1795
|
}
|
|
2374
1796
|
async destroy() {
|
|
2375
1797
|
this.core.effects.offByModuleDestroy(this.name);
|
|
2376
1798
|
await this.core.effects.emit(`${this.name}:onDestroy`, {});
|
|
1799
|
+
console.log("[Rules] 已销毁");
|
|
2377
1800
|
super.destroy();
|
|
2378
1801
|
}
|
|
2379
|
-
async clear() {
|
|
2380
|
-
|
|
2381
|
-
|
|
1802
|
+
async clear() {
|
|
1803
|
+
console.log("[Rules] clear");
|
|
1804
|
+
}
|
|
1805
|
+
};
|
|
1806
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1807
|
+
0 && (module.exports = {
|
|
1808
|
+
RulesModule
|
|
1809
|
+
});
|