@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,471 +1,372 @@
|
|
|
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/model/strategy/adapter/walletPass/utils.ts
|
|
30
|
+
var utils_exports = {};
|
|
31
|
+
__export(utils_exports, {
|
|
32
|
+
getApplicableProductIds: () => getApplicableProductIds,
|
|
33
|
+
getBundleItemIsDiscountPrice: () => getBundleItemIsDiscountPrice,
|
|
34
|
+
getBundleItemIsMarkupOrDiscountPrice: () => getBundleItemIsMarkupOrDiscountPrice,
|
|
35
|
+
getBundleItemIsMarkupPrice: () => getBundleItemIsMarkupPrice,
|
|
36
|
+
getBundleItemIsOriginalPrice: () => getBundleItemIsOriginalPrice,
|
|
37
|
+
getBundleItemPrice: () => getBundleItemPrice,
|
|
38
|
+
getMainProductPrice: () => getMainProductPrice,
|
|
39
|
+
getProductQuantity: () => getProductQuantity,
|
|
40
|
+
processVouchers: () => processVouchers,
|
|
41
|
+
recalculateVouchers: () => recalculateVouchers,
|
|
42
|
+
resolveWalletPassLineKey: () => resolveWalletPassLineKey
|
|
5
43
|
});
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
exports.resolveWalletPassLineKey = resolveWalletPassLineKey;
|
|
10
|
-
var _decimal = _interopRequireDefault(require("decimal.js"));
|
|
11
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
12
|
-
/** 订单商品数量 */
|
|
13
|
-
const getProductQuantity = product => {
|
|
44
|
+
module.exports = __toCommonJS(utils_exports);
|
|
45
|
+
var import_decimal = __toESM(require("decimal.js"));
|
|
46
|
+
var getProductQuantity = (product) => {
|
|
14
47
|
return product.quantity || product.product_quantity || 1;
|
|
15
48
|
};
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* 订单商品行唯一键,用于 maxPassesPerItem 按行、按件配额(同 SPU 不同规格视为不同行)。
|
|
19
|
-
*/
|
|
20
|
-
exports.getProductQuantity = getProductQuantity;
|
|
21
49
|
function resolveWalletPassLineKey(product, indexInOrder) {
|
|
22
|
-
const m = product
|
|
50
|
+
const m = (product == null ? void 0 : product.metadata) || {};
|
|
23
51
|
const u1 = m.product_unique;
|
|
24
|
-
if (u1 != null && String(u1).length > 0)
|
|
52
|
+
if (u1 != null && String(u1).length > 0)
|
|
53
|
+
return String(u1);
|
|
25
54
|
const u2 = m.unique_identification_number;
|
|
26
|
-
if (u2 != null && String(u2).length > 0)
|
|
27
|
-
|
|
28
|
-
if (product
|
|
55
|
+
if (u2 != null && String(u2).length > 0)
|
|
56
|
+
return String(u2);
|
|
57
|
+
if ((product == null ? void 0 : product.id) != null && String(product.id).length > 0)
|
|
58
|
+
return `order_item:${product.id}`;
|
|
59
|
+
if ((product == null ? void 0 : product.product_unique_string) != null && String(product.product_unique_string).length > 0) {
|
|
29
60
|
return String(product.product_unique_string);
|
|
30
61
|
}
|
|
31
62
|
return `order_line_${indexInOrder}`;
|
|
32
63
|
}
|
|
33
64
|
function getExpandedOrderLineQuantity(p) {
|
|
34
|
-
if (p
|
|
65
|
+
if ((p == null ? void 0 : p._orderLineQuantity) != null && p._orderLineQuantity > 0)
|
|
66
|
+
return p._orderLineQuantity;
|
|
35
67
|
return getProductQuantity(p);
|
|
36
68
|
}
|
|
37
|
-
|
|
38
|
-
/** 该行允许消耗的「券次」上限:maxPassesPerItem × 订单行件数 */
|
|
39
69
|
function getMaxPassSlotsForExpandedLine(maxPassesPerItem, p) {
|
|
40
|
-
if (maxPassesPerItem <= 0)
|
|
70
|
+
if (maxPassesPerItem <= 0)
|
|
71
|
+
return Infinity;
|
|
41
72
|
return maxPassesPerItem * getExpandedOrderLineQuantity(p);
|
|
42
73
|
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* 本次抵扣占用多少「券次」配额:有抵扣时至少占 1,并与按金额折算的件数挂钩,不超过剩余额度。
|
|
46
|
-
*/
|
|
47
74
|
function computePassSlotsIncrement(deductAmount, deductQty, maxPassesPerItem, orderLineQuantity, currentUsage) {
|
|
48
|
-
if (maxPassesPerItem <= 0 || !deductAmount.greaterThan(0))
|
|
75
|
+
if (maxPassesPerItem <= 0 || !deductAmount.greaterThan(0))
|
|
76
|
+
return 0;
|
|
49
77
|
const cap = maxPassesPerItem * orderLineQuantity;
|
|
50
78
|
const room = Math.max(0, cap - currentUsage);
|
|
51
|
-
if (room <= 0)
|
|
79
|
+
if (room <= 0)
|
|
80
|
+
return 0;
|
|
52
81
|
const raw = Math.max(1, Math.ceil(Number(deductQty)) || 1);
|
|
53
82
|
return Math.min(raw, room);
|
|
54
83
|
}
|
|
55
84
|
function applyMaxPassUsageIncrements(usageMap, walletPassProductId, maxPassesPerItem, deductionDetails) {
|
|
56
|
-
deductionDetails.forEach(detail => {
|
|
85
|
+
deductionDetails.forEach((detail) => {
|
|
86
|
+
var _a;
|
|
57
87
|
const lineKey = detail.lineKey;
|
|
58
|
-
if (!lineKey || maxPassesPerItem <= 0)
|
|
88
|
+
if (!lineKey || maxPassesPerItem <= 0)
|
|
89
|
+
return;
|
|
59
90
|
const orderLineQty = detail.orderLineQuantity != null && detail.orderLineQuantity > 0 ? detail.orderLineQuantity : 1;
|
|
60
|
-
const cur = usageMap.get(walletPassProductId)
|
|
61
|
-
const inc = computePassSlotsIncrement(
|
|
62
|
-
|
|
63
|
-
|
|
91
|
+
const cur = ((_a = usageMap.get(walletPassProductId)) == null ? void 0 : _a.get(lineKey)) || 0;
|
|
92
|
+
const inc = computePassSlotsIncrement(
|
|
93
|
+
new import_decimal.default(detail.deductAmount),
|
|
94
|
+
detail.deductQuantity,
|
|
95
|
+
maxPassesPerItem,
|
|
96
|
+
orderLineQty,
|
|
97
|
+
cur
|
|
98
|
+
);
|
|
99
|
+
if (inc <= 0)
|
|
100
|
+
return;
|
|
101
|
+
if (!usageMap.has(walletPassProductId))
|
|
102
|
+
usageMap.set(walletPassProductId, /* @__PURE__ */ new Map());
|
|
64
103
|
const inner = usageMap.get(walletPassProductId);
|
|
65
104
|
inner.set(lineKey, cur + inc);
|
|
66
105
|
});
|
|
67
106
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const
|
|
71
|
-
const
|
|
72
|
-
config,
|
|
73
|
-
recommended_usage_amount,
|
|
74
|
-
recommended_pure_product_usage_amount
|
|
75
|
-
} = voucher;
|
|
76
|
-
const deductTaxAndFee = config?.deductTaxAndFee ?? true; // 默认开启抵扣税费
|
|
77
|
-
|
|
78
|
-
// 如果开启抵扣税费,使用 recommended_usage_amount(包含税费)
|
|
79
|
-
// 如果关闭抵扣税费,使用 recommended_pure_product_usage_amount(仅商品金额)
|
|
107
|
+
var getRecommendedAmount = (voucher) => {
|
|
108
|
+
console.log("voucher312", voucher);
|
|
109
|
+
const { config, recommended_usage_amount, recommended_pure_product_usage_amount } = voucher;
|
|
110
|
+
const deductTaxAndFee = (config == null ? void 0 : config.deductTaxAndFee) ?? true;
|
|
80
111
|
return deductTaxAndFee ? recommended_usage_amount : recommended_pure_product_usage_amount ?? recommended_usage_amount;
|
|
81
112
|
};
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
available_product_type,
|
|
87
|
-
available_product_ids
|
|
88
|
-
} = voucher;
|
|
89
|
-
|
|
90
|
-
// 如果没有 available_product_type,默认为 product_all
|
|
91
|
-
const productType = available_product_type || 'product_all';
|
|
92
|
-
|
|
93
|
-
// product_all 时,返回 null 表示适用所有商品
|
|
94
|
-
if (productType === 'product_all') {
|
|
113
|
+
var getApplicableProductIds = (voucher) => {
|
|
114
|
+
const { available_product_type, available_product_ids } = voucher;
|
|
115
|
+
const productType = available_product_type || "product_all";
|
|
116
|
+
if (productType === "product_all") {
|
|
95
117
|
return null;
|
|
96
118
|
}
|
|
97
|
-
|
|
98
|
-
// product_collection 或 products 时,返回指定的商品ID列表
|
|
99
|
-
if (productType === 'product_collection' || productType === 'products') {
|
|
119
|
+
if (productType === "product_collection" || productType === "products") {
|
|
100
120
|
return available_product_ids || [];
|
|
101
121
|
}
|
|
102
|
-
|
|
103
|
-
// 其他情况默认返回空数组(不适用任何商品)
|
|
104
122
|
return [];
|
|
105
123
|
};
|
|
106
|
-
|
|
107
|
-
// 辅助函数:计算适用商品的总金额(基于剩余金额)
|
|
108
|
-
exports.getApplicableProductIds = getApplicableProductIds;
|
|
109
|
-
const getApplicableProductsAmount = (voucher, productsData) => {
|
|
124
|
+
var getApplicableProductsAmount = (voucher, productsData) => {
|
|
110
125
|
const applicableProductIds = getApplicableProductIds(voucher);
|
|
111
|
-
const {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
const deductTaxAndFee = config?.deductTaxAndFee ?? true;
|
|
115
|
-
|
|
116
|
-
// 根据券的配置选择使用哪个金额字段
|
|
117
|
-
const amountField = deductTaxAndFee ? 'remainingAmountWithTax' : 'remainingAmountPure';
|
|
118
|
-
|
|
119
|
-
// 如果为 null,适用于所有商品
|
|
126
|
+
const { config } = voucher;
|
|
127
|
+
const deductTaxAndFee = (config == null ? void 0 : config.deductTaxAndFee) ?? true;
|
|
128
|
+
const amountField = deductTaxAndFee ? "remainingAmountWithTax" : "remainingAmountPure";
|
|
120
129
|
if (applicableProductIds === null) {
|
|
121
|
-
return productsData.filter(p => p[amountField].greaterThan(0)).reduce((sum, p) => sum.plus(p[amountField]), new
|
|
130
|
+
return productsData.filter((p) => p[amountField].greaterThan(0)).reduce((sum, p) => sum.plus(p[amountField]), new import_decimal.default(0));
|
|
122
131
|
}
|
|
123
|
-
|
|
124
|
-
// 如果为空数组,不适用任何商品
|
|
125
132
|
if (applicableProductIds.length === 0) {
|
|
126
|
-
return new
|
|
133
|
+
return new import_decimal.default(0);
|
|
127
134
|
}
|
|
128
|
-
|
|
129
|
-
// 计算指定商品的总金额
|
|
130
|
-
return productsData.filter(p => applicableProductIds.includes(p.product_id) && p[amountField].greaterThan(0)).reduce((sum, p) => sum.plus(p[amountField]), new _decimal.default(0));
|
|
135
|
+
return productsData.filter((p) => applicableProductIds.includes(p.product_id) && p[amountField].greaterThan(0)).reduce((sum, p) => sum.plus(p[amountField]), new import_decimal.default(0));
|
|
131
136
|
};
|
|
132
|
-
|
|
133
|
-
// 辅助函数:获取适用的商品列表
|
|
134
|
-
const getApplicableProducts = (voucher, productsData) => {
|
|
137
|
+
var getApplicableProducts = (voucher, productsData) => {
|
|
135
138
|
const applicableProductIds = getApplicableProductIds(voucher);
|
|
136
|
-
|
|
137
|
-
// 如果为 null,适用于所有商品
|
|
138
139
|
if (applicableProductIds === null) {
|
|
139
140
|
return productsData;
|
|
140
141
|
}
|
|
141
|
-
|
|
142
|
-
// 如果为空数组,不适用任何商品
|
|
143
142
|
if (applicableProductIds.length === 0) {
|
|
144
143
|
return [];
|
|
145
144
|
}
|
|
146
|
-
|
|
147
|
-
// 返回指定的商品列表
|
|
148
|
-
return productsData.filter(p => applicableProductIds.includes(p.product_id));
|
|
145
|
+
return productsData.filter((p) => applicableProductIds.includes(p.product_id));
|
|
149
146
|
};
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* 优惠券处理函数
|
|
153
|
-
* @param applicableVouchers 可用的券列表
|
|
154
|
-
* @param orderTotalAmount 订单总金额
|
|
155
|
-
* @param products 订单商品列表
|
|
156
|
-
* @returns 返回推荐券列表和全部列表,每个券包含 _available_max_amount 和 _unified_available_status
|
|
157
|
-
*/
|
|
158
147
|
function processVouchers(applicableVouchers, orderTotalAmount, products) {
|
|
159
|
-
|
|
160
|
-
// remainingAmountWithTax: 含税费的剩余可抵扣金额
|
|
161
|
-
// remainingAmountPure: 纯商品金额(不含税费)的剩余可抵扣金额
|
|
162
|
-
// 在抵扣时,会根据券的 deductTaxAndFee 配置选择从哪个金额池扣除
|
|
148
|
+
console.log(products, "products123");
|
|
163
149
|
const productsCopy = expandProductsWithBundleItems(products, true);
|
|
164
|
-
let remainingOrderAmount = new
|
|
165
|
-
|
|
166
|
-
// ========== 辅助工具:maxPassesPerItem(按订单行 + 件数)追踪 ==========
|
|
150
|
+
let remainingOrderAmount = new import_decimal.default(orderTotalAmount);
|
|
167
151
|
const getItemPassUsage = (usageMap, walletPassProductId, lineKey) => {
|
|
168
|
-
|
|
152
|
+
var _a;
|
|
153
|
+
return ((_a = usageMap.get(walletPassProductId)) == null ? void 0 : _a.get(lineKey)) || 0;
|
|
169
154
|
};
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
return products.filter(p => {
|
|
155
|
+
const filterByMaxPassesPerItem = (products2, usageMap, walletPassProductId, maxPassesPerItem) => {
|
|
156
|
+
if (maxPassesPerItem <= 0)
|
|
157
|
+
return products2;
|
|
158
|
+
return products2.filter((p) => {
|
|
175
159
|
const lineKey = p._walletPassLineKey;
|
|
176
|
-
if (!lineKey)
|
|
160
|
+
if (!lineKey)
|
|
161
|
+
return true;
|
|
177
162
|
return getItemPassUsage(usageMap, walletPassProductId, lineKey) < getMaxPassSlotsForExpandedLine(maxPassesPerItem, p);
|
|
178
163
|
});
|
|
179
164
|
};
|
|
180
|
-
// ================================================================
|
|
181
|
-
|
|
182
|
-
// 辅助函数:计算单张券的 _available_max_amount
|
|
183
165
|
const calculateAvailableMaxAmount = (voucher, productsData, itemPassUsage) => {
|
|
184
|
-
const {
|
|
185
|
-
|
|
186
|
-
} = voucher;
|
|
187
|
-
const {
|
|
188
|
-
maxDeductionAmount = 0,
|
|
189
|
-
allowCrossProduct = true,
|
|
190
|
-
applicableProductLimit = 0,
|
|
191
|
-
deductTaxAndFee = true,
|
|
192
|
-
maxPassesPerItem = 0
|
|
193
|
-
} = config ?? {};
|
|
194
|
-
|
|
195
|
-
// 根据 deductTaxAndFee 配置获取推荐金额
|
|
166
|
+
const { config } = voucher;
|
|
167
|
+
const { maxDeductionAmount = 0, allowCrossProduct = true, applicableProductLimit = 0, deductTaxAndFee = true, maxPassesPerItem = 0 } = config ?? {};
|
|
196
168
|
const recommendedAmount = getRecommendedAmount(voucher);
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
// 获取适用商品列表(只筛选有剩余金额的商品)
|
|
206
|
-
let applicableProducts = getApplicableProducts(voucher, productsData).filter(p => p[amountField].greaterThan(0));
|
|
207
|
-
|
|
208
|
-
// 按 maxPassesPerItem 过滤:排除已达到单商品可用卡券上限的商品
|
|
169
|
+
const baseAmount = import_decimal.default.min(
|
|
170
|
+
new import_decimal.default(recommendedAmount),
|
|
171
|
+
new import_decimal.default(maxDeductionAmount)
|
|
172
|
+
);
|
|
173
|
+
const unitPriceField = deductTaxAndFee ? "unitPriceWithTax" : "unitPricePure";
|
|
174
|
+
const amountField = deductTaxAndFee ? "remainingAmountWithTax" : "remainingAmountPure";
|
|
175
|
+
let applicableProducts = getApplicableProducts(voucher, productsData).filter((p) => p[amountField].greaterThan(0));
|
|
209
176
|
if (itemPassUsage) {
|
|
210
177
|
applicableProducts = filterByMaxPassesPerItem(applicableProducts, itemPassUsage, voucher.product_id, maxPassesPerItem);
|
|
211
178
|
}
|
|
212
179
|
if (applicableProducts.length === 0) {
|
|
213
|
-
return new
|
|
180
|
+
return new import_decimal.default(0);
|
|
214
181
|
}
|
|
215
|
-
|
|
216
|
-
// 根据跨商品配置计算适用商品金额
|
|
217
|
-
let finalApplicableAmount = new _decimal.default(0);
|
|
182
|
+
let finalApplicableAmount = new import_decimal.default(0);
|
|
218
183
|
if (allowCrossProduct) {
|
|
219
|
-
// 跨商品券:可以抵扣多个商品
|
|
220
184
|
if (applicableProductLimit > 0) {
|
|
221
|
-
// 有数量限制:按剩余金额从高到低排序,按动态计算的可抵扣数量累计直到达到 limit
|
|
222
185
|
const sortedProducts = [...applicableProducts].sort((a, b) => a[amountField].comparedTo(b[amountField]) > 0 ? -1 : 1);
|
|
223
186
|
let remainingLimit = applicableProductLimit;
|
|
224
187
|
for (const product of sortedProducts) {
|
|
225
|
-
if (remainingLimit <= 0)
|
|
226
|
-
|
|
188
|
+
if (remainingLimit <= 0)
|
|
189
|
+
break;
|
|
227
190
|
const currentAvailableQty = Math.ceil(product[amountField].dividedBy(product[unitPriceField]).toNumber());
|
|
228
191
|
const deductQty = Math.min(currentAvailableQty, remainingLimit);
|
|
229
|
-
|
|
230
|
-
|
|
192
|
+
const deductAmount = import_decimal.default.min(
|
|
193
|
+
product[unitPriceField].times(deductQty),
|
|
194
|
+
product[amountField]
|
|
195
|
+
);
|
|
231
196
|
finalApplicableAmount = finalApplicableAmount.plus(deductAmount);
|
|
232
197
|
remainingLimit -= deductQty;
|
|
233
198
|
}
|
|
234
199
|
} else {
|
|
235
|
-
|
|
236
|
-
|
|
200
|
+
finalApplicableAmount = applicableProducts.reduce(
|
|
201
|
+
(sum, p) => sum.plus(p[amountField]),
|
|
202
|
+
new import_decimal.default(0)
|
|
203
|
+
);
|
|
237
204
|
}
|
|
238
205
|
} else {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
206
|
+
const maxProduct = applicableProducts.reduce(
|
|
207
|
+
(max, p) => p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max
|
|
208
|
+
);
|
|
242
209
|
if (maxPassesPerItem > 0) {
|
|
243
|
-
finalApplicableAmount =
|
|
210
|
+
finalApplicableAmount = import_decimal.default.min(
|
|
211
|
+
maxProduct[unitPriceField].times(maxPassesPerItem),
|
|
212
|
+
maxProduct[amountField]
|
|
213
|
+
);
|
|
244
214
|
} else {
|
|
245
215
|
finalApplicableAmount = maxProduct[amountField];
|
|
246
216
|
}
|
|
247
217
|
}
|
|
248
|
-
|
|
249
|
-
// 返回最小值
|
|
250
|
-
return _decimal.default.min(baseAmount, finalApplicableAmount, remainingOrderAmount);
|
|
218
|
+
return import_decimal.default.min(baseAmount, finalApplicableAmount, remainingOrderAmount);
|
|
251
219
|
};
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
const isVoucherAvailable = (voucher, productsData, usedVoucherCounts, itemPassUsage) => {
|
|
255
|
-
const {
|
|
256
|
-
config,
|
|
257
|
-
id,
|
|
258
|
-
product_id
|
|
259
|
-
} = voucher;
|
|
260
|
-
|
|
261
|
-
// 根据 deductTaxAndFee 配置获取推荐金额
|
|
220
|
+
const isVoucherAvailable = (voucher, productsData, usedVoucherCounts2, itemPassUsage) => {
|
|
221
|
+
const { config, id, product_id } = voucher;
|
|
262
222
|
const recommendedAmount = getRecommendedAmount(voucher);
|
|
263
|
-
|
|
264
|
-
// 余额为 0
|
|
265
223
|
if (recommendedAmount <= 0) {
|
|
266
|
-
return {
|
|
267
|
-
isAvailable: false,
|
|
268
|
-
reasonCode: 'not_meet_the_required_conditions'
|
|
269
|
-
};
|
|
224
|
+
return { isAvailable: false, reasonCode: "not_meet_the_required_conditions" };
|
|
270
225
|
}
|
|
271
|
-
|
|
272
|
-
// 订单金额已抵扣完
|
|
273
226
|
if (remainingOrderAmount.lessThanOrEqualTo(0)) {
|
|
274
|
-
return {
|
|
275
|
-
isAvailable: false,
|
|
276
|
-
reasonCode: 'exceeds_the_maximum_deduction_limit'
|
|
277
|
-
};
|
|
227
|
+
return { isAvailable: false, reasonCode: "exceeds_the_maximum_deduction_limit" };
|
|
278
228
|
}
|
|
279
|
-
|
|
280
|
-
// 适用商品金额已被抵扣完
|
|
281
229
|
const applicableAmount = getApplicableProductsAmount(voucher, productsData);
|
|
282
230
|
if (applicableAmount.lessThanOrEqualTo(0)) {
|
|
283
|
-
return {
|
|
284
|
-
isAvailable: false,
|
|
285
|
-
reasonCode: 'not_meet_the_required_conditions'
|
|
286
|
-
};
|
|
231
|
+
return { isAvailable: false, reasonCode: "not_meet_the_required_conditions" };
|
|
287
232
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
if (usedCount >= (config?.maxUsagePerOrder || 0)) {
|
|
293
|
-
return {
|
|
294
|
-
isAvailable: false,
|
|
295
|
-
reasonCode: 'usage_limit_reached'
|
|
296
|
-
};
|
|
233
|
+
if (((config == null ? void 0 : config.maxUsagePerOrder) || 0) > 0) {
|
|
234
|
+
const usedCount = usedVoucherCounts2.get(product_id) || 0;
|
|
235
|
+
if (usedCount >= ((config == null ? void 0 : config.maxUsagePerOrder) || 0)) {
|
|
236
|
+
return { isAvailable: false, reasonCode: "usage_limit_reached" };
|
|
297
237
|
}
|
|
298
238
|
}
|
|
299
|
-
|
|
300
|
-
// 检查 maxPassesPerItem:如果所有适用商品都已达到单商品可用卡券上限,则不可用
|
|
301
|
-
const maxPassesPerItem = config?.maxPassesPerItem || 0;
|
|
239
|
+
const maxPassesPerItem = (config == null ? void 0 : config.maxPassesPerItem) || 0;
|
|
302
240
|
if (maxPassesPerItem > 0 && itemPassUsage) {
|
|
303
|
-
const deductTaxAndFee = config
|
|
304
|
-
const amountField = deductTaxAndFee ?
|
|
305
|
-
const availableAfterPassLimit = getApplicableProducts(voucher, productsData).filter(p => p[amountField].greaterThan(0)).filter(p => {
|
|
241
|
+
const deductTaxAndFee = (config == null ? void 0 : config.deductTaxAndFee) ?? true;
|
|
242
|
+
const amountField = deductTaxAndFee ? "remainingAmountWithTax" : "remainingAmountPure";
|
|
243
|
+
const availableAfterPassLimit = getApplicableProducts(voucher, productsData).filter((p) => p[amountField].greaterThan(0)).filter((p) => {
|
|
306
244
|
const lineKey = p._walletPassLineKey;
|
|
307
|
-
if (!lineKey)
|
|
245
|
+
if (!lineKey)
|
|
246
|
+
return true;
|
|
308
247
|
return getItemPassUsage(itemPassUsage, product_id, lineKey) < getMaxPassSlotsForExpandedLine(maxPassesPerItem, p);
|
|
309
248
|
});
|
|
310
249
|
if (availableAfterPassLimit.length === 0) {
|
|
311
|
-
return {
|
|
312
|
-
isAvailable: false,
|
|
313
|
-
reasonCode: 'max_passes_per_item_reached'
|
|
314
|
-
};
|
|
250
|
+
return { isAvailable: false, reasonCode: "max_passes_per_item_reached" };
|
|
315
251
|
}
|
|
316
252
|
}
|
|
317
|
-
return {
|
|
318
|
-
isAvailable: true
|
|
319
|
-
};
|
|
253
|
+
return { isAvailable: true };
|
|
320
254
|
};
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
255
|
+
const usedVoucherCountsForAll = /* @__PURE__ */ new Map();
|
|
256
|
+
const allVouchersWithStatus = applicableVouchers.map((voucher) => {
|
|
257
|
+
const _available_max_amount = calculateAvailableMaxAmount(
|
|
258
|
+
voucher,
|
|
259
|
+
productsCopy
|
|
260
|
+
);
|
|
261
|
+
const availabilityResult = isVoucherAvailable(
|
|
262
|
+
voucher,
|
|
263
|
+
productsCopy,
|
|
264
|
+
usedVoucherCountsForAll
|
|
265
|
+
);
|
|
327
266
|
const _unified_available_status = availabilityResult.isAvailable ? 1 : 0;
|
|
328
267
|
return {
|
|
329
268
|
...voucher,
|
|
330
269
|
_available_max_amount: _available_max_amount.toNumber(),
|
|
331
270
|
// 转换为数字
|
|
332
271
|
_unified_available_status,
|
|
333
|
-
...
|
|
334
|
-
reasonCode: availabilityResult.reasonCode
|
|
335
|
-
})
|
|
272
|
+
...availabilityResult.reasonCode && { reasonCode: availabilityResult.reasonCode }
|
|
336
273
|
};
|
|
337
274
|
});
|
|
338
|
-
|
|
339
|
-
// ========== 第二步:计算推荐券列表 ==========
|
|
340
275
|
const recommendedVouchers = [];
|
|
341
|
-
const usedVoucherCounts = new Map();
|
|
342
|
-
|
|
343
|
-
// 重置商品余额追踪(同时维护含税和不含税两个金额池)
|
|
276
|
+
const usedVoucherCounts = /* @__PURE__ */ new Map();
|
|
344
277
|
const productsForRecommendation = expandProductsWithBundleItems(products, true);
|
|
345
|
-
remainingOrderAmount = new
|
|
346
|
-
|
|
347
|
-
const
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
const crossProductVouchers = applicableVouchers.filter(
|
|
355
|
-
(v) => v.config?.allowCrossProduct,
|
|
356
|
-
);
|
|
357
|
-
// 按 tag 分组
|
|
358
|
-
const groupByType = (vouchers: any[]) => {
|
|
359
|
-
const groups = new Map<string, any[]>();
|
|
360
|
-
vouchers.forEach((v) => {
|
|
361
|
-
const tag = v.tag;
|
|
362
|
-
if (!groups.has(tag)) {
|
|
363
|
-
groups.set(tag, []);
|
|
364
|
-
}
|
|
365
|
-
groups.get(tag)!.push(v);
|
|
366
|
-
});
|
|
367
|
-
return groups;
|
|
368
|
-
};
|
|
369
|
-
// 对每组券按金额(balance)从大到小排序
|
|
370
|
-
const sortVouchersByAmount = (vouchers: Voucher[]) => {
|
|
371
|
-
return [...vouchers].sort((a, b) => getRecommendedAmount(b) - getRecommendedAmount(a));
|
|
372
|
-
};
|
|
373
|
-
*/
|
|
374
|
-
|
|
375
|
-
// 处理单张券的抵扣
|
|
376
|
-
const applyVoucher = voucher => {
|
|
377
|
-
// 检查是否可用
|
|
378
|
-
const availabilityCheck = isVoucherAvailable(voucher, productsForRecommendation, usedVoucherCounts, itemPassUsageMap);
|
|
278
|
+
remainingOrderAmount = new import_decimal.default(orderTotalAmount);
|
|
279
|
+
const itemPassUsageMap = /* @__PURE__ */ new Map();
|
|
280
|
+
const applyVoucher = (voucher) => {
|
|
281
|
+
const availabilityCheck = isVoucherAvailable(
|
|
282
|
+
voucher,
|
|
283
|
+
productsForRecommendation,
|
|
284
|
+
usedVoucherCounts,
|
|
285
|
+
itemPassUsageMap
|
|
286
|
+
);
|
|
379
287
|
if (!availabilityCheck.isAvailable) {
|
|
380
288
|
return false;
|
|
381
289
|
}
|
|
382
|
-
const {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
applicableProductLimit = 0,
|
|
391
|
-
deductTaxAndFee = true,
|
|
392
|
-
maxPassesPerItem = 0
|
|
393
|
-
} = config ?? {};
|
|
394
|
-
|
|
395
|
-
// 根据券的配置选择使用哪个单价字段和金额字段
|
|
396
|
-
const unitPriceField = deductTaxAndFee ? 'unitPriceWithTax' : 'unitPricePure';
|
|
397
|
-
const amountField = deductTaxAndFee ? 'remainingAmountWithTax' : 'remainingAmountPure';
|
|
398
|
-
|
|
399
|
-
// 获取适用商品(只筛选有剩余金额的商品)
|
|
400
|
-
let applicableProducts = getApplicableProducts(voucher, productsForRecommendation).filter(p => p[amountField].greaterThan(0));
|
|
401
|
-
|
|
402
|
-
// 按 maxPassesPerItem 过滤:排除已达到单商品可用卡券上限的商品
|
|
290
|
+
const { config, id, product_id } = voucher;
|
|
291
|
+
const { maxDeductionAmount = 0, allowCrossProduct = true, applicableProductLimit = 0, deductTaxAndFee = true, maxPassesPerItem = 0 } = config ?? {};
|
|
292
|
+
const unitPriceField = deductTaxAndFee ? "unitPriceWithTax" : "unitPricePure";
|
|
293
|
+
const amountField = deductTaxAndFee ? "remainingAmountWithTax" : "remainingAmountPure";
|
|
294
|
+
let applicableProducts = getApplicableProducts(
|
|
295
|
+
voucher,
|
|
296
|
+
productsForRecommendation
|
|
297
|
+
).filter((p) => p[amountField].greaterThan(0));
|
|
403
298
|
applicableProducts = filterByMaxPassesPerItem(applicableProducts, itemPassUsageMap, product_id, maxPassesPerItem);
|
|
404
|
-
if (applicableProducts.length === 0)
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
299
|
+
if (applicableProducts.length === 0)
|
|
300
|
+
return false;
|
|
301
|
+
const usageAmount = typeof voucher.edit_current_amount === "number" ? voucher.edit_current_amount : getRecommendedAmount(voucher);
|
|
302
|
+
const baseAmount = import_decimal.default.min(
|
|
303
|
+
new import_decimal.default(usageAmount),
|
|
304
|
+
new import_decimal.default(maxDeductionAmount)
|
|
305
|
+
);
|
|
306
|
+
let calculatedAvailableMaxAmount = new import_decimal.default(0);
|
|
411
307
|
if (allowCrossProduct) {
|
|
412
|
-
// 跨商品券:按 quantity 限制计算可抵扣金额
|
|
413
308
|
if (applicableProductLimit > 0) {
|
|
414
|
-
// 按剩余金额从高到低排序
|
|
415
309
|
const sortedProducts = [...applicableProducts].sort((a, b) => a[amountField].comparedTo(b[amountField]) > 0 ? -1 : 1);
|
|
416
310
|
let remainingLimit = applicableProductLimit;
|
|
417
311
|
for (const product of sortedProducts) {
|
|
418
|
-
if (remainingLimit <= 0)
|
|
419
|
-
|
|
312
|
+
if (remainingLimit <= 0)
|
|
313
|
+
break;
|
|
420
314
|
const currentAvailableQty = Math.ceil(product[amountField].dividedBy(product[unitPriceField]).toNumber());
|
|
421
315
|
const deductQty = Math.min(currentAvailableQty, remainingLimit);
|
|
422
|
-
|
|
423
|
-
|
|
316
|
+
const deductAmount = import_decimal.default.min(
|
|
317
|
+
product[unitPriceField].times(deductQty),
|
|
318
|
+
product[amountField]
|
|
319
|
+
);
|
|
424
320
|
calculatedAvailableMaxAmount = calculatedAvailableMaxAmount.plus(deductAmount);
|
|
425
321
|
remainingLimit -= deductQty;
|
|
426
322
|
}
|
|
427
323
|
} else {
|
|
428
|
-
|
|
429
|
-
|
|
324
|
+
calculatedAvailableMaxAmount = applicableProducts.reduce(
|
|
325
|
+
(sum, p) => sum.plus(p[amountField]),
|
|
326
|
+
new import_decimal.default(0)
|
|
327
|
+
);
|
|
430
328
|
}
|
|
431
329
|
} else {
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
330
|
+
const maxProduct = applicableProducts.reduce(
|
|
331
|
+
(max, p) => p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max
|
|
332
|
+
);
|
|
435
333
|
if (maxPassesPerItem > 0) {
|
|
436
|
-
calculatedAvailableMaxAmount =
|
|
334
|
+
calculatedAvailableMaxAmount = import_decimal.default.min(
|
|
335
|
+
maxProduct[unitPriceField].times(maxPassesPerItem),
|
|
336
|
+
maxProduct[amountField]
|
|
337
|
+
);
|
|
437
338
|
} else {
|
|
438
339
|
calculatedAvailableMaxAmount = maxProduct[amountField];
|
|
439
340
|
}
|
|
440
341
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
342
|
+
const availableMaxAmount = import_decimal.default.min(
|
|
343
|
+
baseAmount,
|
|
344
|
+
calculatedAvailableMaxAmount,
|
|
345
|
+
remainingOrderAmount
|
|
346
|
+
);
|
|
347
|
+
const maxDeduction = import_decimal.default.min(
|
|
348
|
+
new import_decimal.default(usageAmount),
|
|
349
|
+
new import_decimal.default(maxDeductionAmount),
|
|
350
|
+
remainingOrderAmount
|
|
351
|
+
);
|
|
448
352
|
let deductionLeft = maxDeduction;
|
|
449
353
|
const deductionDetails = [];
|
|
450
354
|
if (allowCrossProduct) {
|
|
451
|
-
|
|
452
|
-
|
|
355
|
+
const sortedProducts = [...applicableProducts].sort(
|
|
356
|
+
(a, b) => a[amountField].comparedTo(b[amountField]) > 0 ? -1 : 1
|
|
357
|
+
);
|
|
453
358
|
let remainingLimit = applicableProductLimit > 0 ? applicableProductLimit : Infinity;
|
|
454
359
|
for (const product of sortedProducts) {
|
|
455
|
-
if (deductionLeft.lessThanOrEqualTo(0) || remainingLimit <= 0)
|
|
456
|
-
|
|
457
|
-
// 动态计算当前可抵扣数量 = ceil(剩余金额 / 单价)
|
|
360
|
+
if (deductionLeft.lessThanOrEqualTo(0) || remainingLimit <= 0)
|
|
361
|
+
break;
|
|
458
362
|
const currentAvailableQty = Math.ceil(product[amountField].dividedBy(product[unitPriceField]).toNumber());
|
|
459
363
|
const availableQty = Math.min(currentAvailableQty, remainingLimit);
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
// 计算实际抵扣的数量(用于记录和配额计算)
|
|
364
|
+
const maxDeductForProduct = import_decimal.default.min(
|
|
365
|
+
product[unitPriceField].times(availableQty),
|
|
366
|
+
product[amountField]
|
|
367
|
+
);
|
|
368
|
+
const actualDeductAmount = import_decimal.default.min(deductionLeft, maxDeductForProduct);
|
|
466
369
|
const actualDeductQty = Math.ceil(actualDeductAmount.dividedBy(product[unitPriceField]).toNumber());
|
|
467
|
-
|
|
468
|
-
// 只更新商品的剩余金额,不更新 remainingQuantity
|
|
469
370
|
product[amountField] = product[amountField].minus(actualDeductAmount);
|
|
470
371
|
deductionLeft = deductionLeft.minus(actualDeductAmount);
|
|
471
372
|
remainingLimit -= actualDeductQty;
|
|
@@ -477,24 +378,23 @@ function processVouchers(applicableVouchers, orderTotalAmount, products) {
|
|
|
477
378
|
orderLineQuantity: getExpandedOrderLineQuantity(product),
|
|
478
379
|
deductAmount: actualDeductAmount.toNumber(),
|
|
479
380
|
// 转换为数字
|
|
480
|
-
deductQuantity: actualDeductQty
|
|
381
|
+
deductQuantity: actualDeductQty
|
|
382
|
+
// 抵扣涉及的数量(用于记录)
|
|
481
383
|
});
|
|
482
384
|
}
|
|
483
385
|
} else {
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
// maxPassesPerItem 限制每张券最多抵扣的单位数
|
|
386
|
+
const targetProduct = applicableProducts.reduce(
|
|
387
|
+
(max, p) => p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max
|
|
388
|
+
);
|
|
488
389
|
let maxDeductForProduct = targetProduct[amountField];
|
|
489
390
|
if (maxPassesPerItem > 0) {
|
|
490
|
-
maxDeductForProduct =
|
|
391
|
+
maxDeductForProduct = import_decimal.default.min(
|
|
392
|
+
targetProduct[unitPriceField].times(maxPassesPerItem),
|
|
393
|
+
targetProduct[amountField]
|
|
394
|
+
);
|
|
491
395
|
}
|
|
492
|
-
const actualDeductAmount =
|
|
493
|
-
|
|
494
|
-
// 计算实际抵扣的数量
|
|
396
|
+
const actualDeductAmount = import_decimal.default.min(deductionLeft, maxDeductForProduct);
|
|
495
397
|
const actualDeductQty = Math.ceil(actualDeductAmount.dividedBy(targetProduct[unitPriceField]).toNumber());
|
|
496
|
-
|
|
497
|
-
// 只更新商品的剩余金额,不更新 remainingQuantity
|
|
498
398
|
targetProduct[amountField] = targetProduct[amountField].minus(actualDeductAmount);
|
|
499
399
|
deductionLeft = deductionLeft.minus(actualDeductAmount);
|
|
500
400
|
deductionDetails.push({
|
|
@@ -509,14 +409,9 @@ function processVouchers(applicableVouchers, orderTotalAmount, products) {
|
|
|
509
409
|
}
|
|
510
410
|
const totalDeducted = maxDeduction.minus(deductionLeft);
|
|
511
411
|
if (totalDeducted.greaterThan(0)) {
|
|
512
|
-
// 更新订单剩余金额
|
|
513
412
|
remainingOrderAmount = remainingOrderAmount.minus(totalDeducted);
|
|
514
|
-
|
|
515
|
-
// 更新券使用次数(按 product_id 统计)
|
|
516
413
|
usedVoucherCounts.set(product_id, (usedVoucherCounts.get(product_id) || 0) + 1);
|
|
517
414
|
applyMaxPassUsageIncrements(itemPassUsageMap, product_id, maxPassesPerItem, deductionDetails);
|
|
518
|
-
|
|
519
|
-
// 添加到推荐列表(包含基于当前剩余金额计算的 available_max_amount)
|
|
520
415
|
recommendedVouchers.push({
|
|
521
416
|
...voucher,
|
|
522
417
|
actualDeduction: totalDeducted.toNumber(),
|
|
@@ -530,47 +425,17 @@ function processVouchers(applicableVouchers, orderTotalAmount, products) {
|
|
|
530
425
|
}
|
|
531
426
|
return false;
|
|
532
427
|
};
|
|
533
|
-
|
|
534
|
-
/**
|
|
535
|
-
// 第一轮:处理未跨商品券
|
|
536
|
-
const nonCrossGroups = groupByType(nonCrossProductVouchers);
|
|
537
|
-
nonCrossGroups.forEach((vouchersInGroup) => {
|
|
538
|
-
const sortedVouchers = sortVouchersByAmount(vouchersInGroup);
|
|
539
|
-
sortedVouchers.forEach((voucher) => {
|
|
540
|
-
applyVoucher(voucher);
|
|
541
|
-
});
|
|
542
|
-
});
|
|
543
|
-
// 第二轮:处理跨商品券
|
|
544
|
-
const crossGroups = groupByType(crossProductVouchers);
|
|
545
|
-
crossGroups.forEach((vouchersInGroup) => {
|
|
546
|
-
const sortedVouchers = sortVouchersByAmount(vouchersInGroup);
|
|
547
|
-
sortedVouchers.forEach((voucher) => {
|
|
548
|
-
applyVoucher(voucher);
|
|
549
|
-
});
|
|
550
|
-
});
|
|
551
|
-
*/
|
|
552
|
-
|
|
553
|
-
// 直接按 applicableVouchers 的顺序处理所有券
|
|
554
|
-
applicableVouchers.forEach(voucher => {
|
|
428
|
+
applicableVouchers.forEach((voucher) => {
|
|
555
429
|
applyVoucher(voucher);
|
|
556
430
|
});
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
// ========== 第三步:构建 all 数组,以 recommended 为基础 ==========
|
|
561
|
-
// 创建 recommended 券的 Map,以 id 为 key
|
|
562
|
-
const recommendedMap = new Map();
|
|
563
|
-
recommendedVouchers.forEach(v => {
|
|
431
|
+
const recommendedMap = /* @__PURE__ */ new Map();
|
|
432
|
+
recommendedVouchers.forEach((v) => {
|
|
564
433
|
recommendedMap.set(v.id, v);
|
|
565
434
|
});
|
|
566
|
-
|
|
567
|
-
// 遍历所有券,如果在 recommended 中则使用增强数据,否则使用基础数据
|
|
568
|
-
const allWithEnhancedData = allVouchersWithStatus.map(voucher => {
|
|
435
|
+
const allWithEnhancedData = allVouchersWithStatus.map((voucher) => {
|
|
569
436
|
if (recommendedMap.has(voucher.id)) {
|
|
570
|
-
// 使用 recommended 中的增强数据
|
|
571
437
|
return recommendedMap.get(voucher.id);
|
|
572
438
|
} else {
|
|
573
|
-
// 不在 recommended 中的券,补充基础字段
|
|
574
439
|
return {
|
|
575
440
|
...voucher,
|
|
576
441
|
actualDeduction: 0,
|
|
@@ -584,98 +449,70 @@ function processVouchers(applicableVouchers, orderTotalAmount, products) {
|
|
|
584
449
|
transformList: allWithEnhancedData
|
|
585
450
|
};
|
|
586
451
|
}
|
|
587
|
-
|
|
588
|
-
/**
|
|
589
|
-
* 重新计算优惠券状态(基于已选券的增量计算)
|
|
590
|
-
* @param allVouchers 所有原始券列表
|
|
591
|
-
* @param selectedVouchers 已选中的券列表(按选中顺序)
|
|
592
|
-
* @param orderTotalAmount 订单总金额
|
|
593
|
-
* @param products 订单商品列表
|
|
594
|
-
* @returns 返回更新后的所有券列表和已选券的详细抵扣信息
|
|
595
|
-
*/
|
|
596
452
|
function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmount, products) {
|
|
597
|
-
// 深拷贝并拆分商品列表(包含主商品和原价子商品,同时维护含税和不含税两个金额池),用于计算
|
|
598
453
|
const productsForCalc = expandProductsWithBundleItems(products, true);
|
|
599
|
-
let remainingOrderAmount = new
|
|
454
|
+
let remainingOrderAmount = new import_decimal.default(orderTotalAmount);
|
|
600
455
|
const selectedWithDetails = [];
|
|
601
|
-
|
|
602
|
-
// 追踪每个 Wallet Pass 商品对每个订单商品行的已使用卡券次数(按行唯一键)
|
|
603
|
-
const itemPassUsageMap = new Map();
|
|
456
|
+
const itemPassUsageMap = /* @__PURE__ */ new Map();
|
|
604
457
|
const getItemPassUsageRecalc = (walletPassProductId, lineKey) => {
|
|
605
|
-
|
|
458
|
+
var _a;
|
|
459
|
+
return ((_a = itemPassUsageMap.get(walletPassProductId)) == null ? void 0 : _a.get(lineKey)) || 0;
|
|
606
460
|
};
|
|
607
|
-
const filterByMaxPassesPerItemRecalc = (
|
|
608
|
-
if (maxPassesPerItem <= 0)
|
|
609
|
-
|
|
461
|
+
const filterByMaxPassesPerItemRecalc = (products2, walletPassProductId, maxPassesPerItem) => {
|
|
462
|
+
if (maxPassesPerItem <= 0)
|
|
463
|
+
return products2;
|
|
464
|
+
return products2.filter((p) => {
|
|
610
465
|
const lineKey = p._walletPassLineKey;
|
|
611
|
-
if (!lineKey)
|
|
466
|
+
if (!lineKey)
|
|
467
|
+
return true;
|
|
612
468
|
return getItemPassUsageRecalc(walletPassProductId, lineKey) < getMaxPassSlotsForExpandedLine(maxPassesPerItem, p);
|
|
613
469
|
});
|
|
614
470
|
};
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
const
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
allowCrossProduct,
|
|
625
|
-
applicableProductLimit,
|
|
626
|
-
deductTaxAndFee = true,
|
|
627
|
-
maxPassesPerItem = 0
|
|
628
|
-
} = config;
|
|
629
|
-
|
|
630
|
-
// 根据券的配置选择使用哪个单价字段和金额字段
|
|
631
|
-
const unitPriceField = deductTaxAndFee ? 'unitPriceWithTax' : 'unitPricePure';
|
|
632
|
-
const amountField = deductTaxAndFee ? 'remainingAmountWithTax' : 'remainingAmountPure';
|
|
633
|
-
|
|
634
|
-
// 获取适用商品(只筛选有剩余金额的商品)
|
|
635
|
-
let applicableProducts = getApplicableProducts(selectedVoucher, productsForCalc).filter(p => p[amountField].greaterThan(0));
|
|
636
|
-
|
|
637
|
-
// 按 maxPassesPerItem 过滤:排除已达到该行券次上限的展开行
|
|
471
|
+
selectedVouchers.forEach((selectedVoucher) => {
|
|
472
|
+
const { config, id } = selectedVoucher;
|
|
473
|
+
const { maxDeductionAmount, allowCrossProduct, applicableProductLimit, deductTaxAndFee = true, maxPassesPerItem = 0 } = config;
|
|
474
|
+
const unitPriceField = deductTaxAndFee ? "unitPriceWithTax" : "unitPricePure";
|
|
475
|
+
const amountField = deductTaxAndFee ? "remainingAmountWithTax" : "remainingAmountPure";
|
|
476
|
+
let applicableProducts = getApplicableProducts(
|
|
477
|
+
selectedVoucher,
|
|
478
|
+
productsForCalc
|
|
479
|
+
).filter((p) => p[amountField].greaterThan(0));
|
|
638
480
|
applicableProducts = filterByMaxPassesPerItemRecalc(applicableProducts, selectedVoucher.product_id, maxPassesPerItem);
|
|
639
481
|
if (applicableProducts.length === 0) {
|
|
640
|
-
// 无适用商品,跳过
|
|
641
482
|
selectedWithDetails.push({
|
|
642
483
|
...selectedVoucher,
|
|
643
484
|
actualDeduction: 0,
|
|
644
485
|
deductionDetails: [],
|
|
645
486
|
_available_max_amount: 0,
|
|
646
487
|
_unified_available_status: 0,
|
|
647
|
-
reasonCode:
|
|
488
|
+
reasonCode: "not_meet_the_required_conditions"
|
|
648
489
|
});
|
|
649
490
|
return;
|
|
650
491
|
}
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
const maxDeduction = _decimal.default.min(new _decimal.default(usageAmount), new _decimal.default(maxDeductionAmount), remainingOrderAmount);
|
|
492
|
+
const usageAmount = typeof selectedVoucher.edit_current_amount === "number" ? selectedVoucher.edit_current_amount : selectedVoucher._available_max_amount ?? getRecommendedAmount(selectedVoucher);
|
|
493
|
+
const maxDeduction = import_decimal.default.min(
|
|
494
|
+
new import_decimal.default(usageAmount),
|
|
495
|
+
new import_decimal.default(maxDeductionAmount),
|
|
496
|
+
remainingOrderAmount
|
|
497
|
+
);
|
|
658
498
|
let deductionLeft = maxDeduction;
|
|
659
499
|
const deductionDetails = [];
|
|
660
500
|
if (allowCrossProduct) {
|
|
661
|
-
|
|
662
|
-
|
|
501
|
+
const sortedProducts = [...applicableProducts].sort(
|
|
502
|
+
(a, b) => a[amountField].comparedTo(b[amountField]) > 0 ? -1 : 1
|
|
503
|
+
);
|
|
663
504
|
let remainingLimit = applicableProductLimit > 0 ? applicableProductLimit : Infinity;
|
|
664
505
|
for (const product of sortedProducts) {
|
|
665
|
-
if (deductionLeft.lessThanOrEqualTo(0) || remainingLimit <= 0)
|
|
666
|
-
|
|
667
|
-
// 动态计算当前可抵扣数量 = ceil(剩余金额 / 单价)
|
|
506
|
+
if (deductionLeft.lessThanOrEqualTo(0) || remainingLimit <= 0)
|
|
507
|
+
break;
|
|
668
508
|
const currentAvailableQty = Math.ceil(product[amountField].dividedBy(product[unitPriceField]).toNumber());
|
|
669
509
|
const availableQty = Math.min(currentAvailableQty, remainingLimit);
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
// 计算实际抵扣的数量(用于记录和配额计算)
|
|
510
|
+
const maxDeductForProduct = import_decimal.default.min(
|
|
511
|
+
product[unitPriceField].times(availableQty),
|
|
512
|
+
product[amountField]
|
|
513
|
+
);
|
|
514
|
+
const actualDeductAmount = import_decimal.default.min(deductionLeft, maxDeductForProduct);
|
|
676
515
|
const actualDeductQty = Math.ceil(actualDeductAmount.dividedBy(product[unitPriceField]).toNumber());
|
|
677
|
-
|
|
678
|
-
// 只更新商品的剩余金额,不更新 remainingQuantity
|
|
679
516
|
product[amountField] = product[amountField].minus(actualDeductAmount);
|
|
680
517
|
deductionLeft = deductionLeft.minus(actualDeductAmount);
|
|
681
518
|
remainingLimit -= actualDeductQty;
|
|
@@ -687,24 +524,23 @@ function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmount, pr
|
|
|
687
524
|
orderLineQuantity: getExpandedOrderLineQuantity(product),
|
|
688
525
|
deductAmount: actualDeductAmount.toNumber(),
|
|
689
526
|
// 转换为数字
|
|
690
|
-
deductQuantity: actualDeductQty
|
|
527
|
+
deductQuantity: actualDeductQty
|
|
528
|
+
// 抵扣涉及的数量(用于记录)
|
|
691
529
|
});
|
|
692
530
|
}
|
|
693
531
|
} else {
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
// maxPassesPerItem 限制每张券最多抵扣的单位数
|
|
532
|
+
const targetProduct = applicableProducts.reduce(
|
|
533
|
+
(max, p) => p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max
|
|
534
|
+
);
|
|
698
535
|
let maxDeductForProduct = targetProduct[amountField];
|
|
699
536
|
if (maxPassesPerItem > 0) {
|
|
700
|
-
maxDeductForProduct =
|
|
537
|
+
maxDeductForProduct = import_decimal.default.min(
|
|
538
|
+
targetProduct[unitPriceField].times(maxPassesPerItem),
|
|
539
|
+
targetProduct[amountField]
|
|
540
|
+
);
|
|
701
541
|
}
|
|
702
|
-
const actualDeductAmount =
|
|
703
|
-
|
|
704
|
-
// 计算实际抵扣的数量
|
|
542
|
+
const actualDeductAmount = import_decimal.default.min(deductionLeft, maxDeductForProduct);
|
|
705
543
|
const actualDeductQty = Math.ceil(actualDeductAmount.dividedBy(targetProduct[unitPriceField]).toNumber());
|
|
706
|
-
|
|
707
|
-
// 只更新商品的剩余金额,不更新 remainingQuantity
|
|
708
544
|
targetProduct[amountField] = targetProduct[amountField].minus(actualDeductAmount);
|
|
709
545
|
deductionLeft = deductionLeft.minus(actualDeductAmount);
|
|
710
546
|
deductionDetails.push({
|
|
@@ -718,8 +554,6 @@ function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmount, pr
|
|
|
718
554
|
});
|
|
719
555
|
}
|
|
720
556
|
const totalDeducted = maxDeduction.minus(deductionLeft);
|
|
721
|
-
|
|
722
|
-
// 更新订单剩余金额
|
|
723
557
|
remainingOrderAmount = remainingOrderAmount.minus(totalDeducted);
|
|
724
558
|
applyMaxPassUsageIncrements(itemPassUsageMap, selectedVoucher.product_id, maxPassesPerItem, deductionDetails);
|
|
725
559
|
selectedWithDetails.push({
|
|
@@ -732,105 +566,97 @@ function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmount, pr
|
|
|
732
566
|
_unified_available_status: totalDeducted.greaterThan(0) ? 1 : 0
|
|
733
567
|
});
|
|
734
568
|
});
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
const usedVoucherCounts = new Map();
|
|
739
|
-
selectedVouchers.forEach(v => {
|
|
569
|
+
const selectedIds = new Set(selectedVouchers.map((v) => v.id));
|
|
570
|
+
const usedVoucherCounts = /* @__PURE__ */ new Map();
|
|
571
|
+
selectedVouchers.forEach((v) => {
|
|
740
572
|
usedVoucherCounts.set(v.product_id, (usedVoucherCounts.get(v.product_id) || 0) + 1);
|
|
741
573
|
});
|
|
742
|
-
const allWithUpdatedStatus = allVouchers.map(voucher => {
|
|
743
|
-
// 如果是已选中的券,使用详细计算结果
|
|
574
|
+
const allWithUpdatedStatus = allVouchers.map((voucher) => {
|
|
744
575
|
if (selectedIds.has(voucher.id)) {
|
|
745
|
-
const selectedDetail = selectedWithDetails.find(
|
|
576
|
+
const selectedDetail = selectedWithDetails.find(
|
|
577
|
+
(v) => v.id === voucher.id
|
|
578
|
+
);
|
|
746
579
|
return selectedDetail || voucher;
|
|
747
580
|
}
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
const
|
|
751
|
-
|
|
752
|
-
id,
|
|
753
|
-
product_id
|
|
754
|
-
} = voucher;
|
|
755
|
-
const {
|
|
756
|
-
maxDeductionAmount,
|
|
757
|
-
allowCrossProduct,
|
|
758
|
-
applicableProductLimit,
|
|
759
|
-
deductTaxAndFee = true,
|
|
760
|
-
maxPassesPerItem = 0
|
|
761
|
-
} = config;
|
|
762
|
-
|
|
763
|
-
// 根据券的配置选择使用哪个单价字段和金额字段
|
|
764
|
-
const unitPriceField = deductTaxAndFee ? 'unitPriceWithTax' : 'unitPricePure';
|
|
765
|
-
const amountField = deductTaxAndFee ? 'remainingAmountWithTax' : 'remainingAmountPure';
|
|
766
|
-
|
|
767
|
-
// 根据 deductTaxAndFee 配置获取推荐金额
|
|
581
|
+
const { config, id, product_id } = voucher;
|
|
582
|
+
const { maxDeductionAmount, allowCrossProduct, applicableProductLimit, deductTaxAndFee = true, maxPassesPerItem = 0 } = config;
|
|
583
|
+
const unitPriceField = deductTaxAndFee ? "unitPriceWithTax" : "unitPricePure";
|
|
584
|
+
const amountField = deductTaxAndFee ? "remainingAmountWithTax" : "remainingAmountPure";
|
|
768
585
|
const recommendedAmount = getRecommendedAmount(voucher);
|
|
769
|
-
|
|
770
|
-
// 检查基本可用性
|
|
771
586
|
let isAvailable = true;
|
|
772
|
-
let calculatedMaxAmount = new
|
|
587
|
+
let calculatedMaxAmount = new import_decimal.default(0);
|
|
773
588
|
let reasonCode;
|
|
774
589
|
if (recommendedAmount <= 0) {
|
|
775
590
|
isAvailable = false;
|
|
776
|
-
reasonCode =
|
|
591
|
+
reasonCode = "not_meet_the_required_conditions";
|
|
777
592
|
} else if (remainingOrderAmount.lessThanOrEqualTo(0)) {
|
|
778
593
|
isAvailable = false;
|
|
779
|
-
reasonCode =
|
|
594
|
+
reasonCode = "exceeds_the_maximum_deduction_limit";
|
|
780
595
|
} else {
|
|
781
|
-
// 检查 maxUsagePerOrder(按 product_id 统计),0 表示不限制
|
|
782
596
|
if (config.maxUsagePerOrder > 0) {
|
|
783
597
|
const usedCount = usedVoucherCounts.get(product_id) || 0;
|
|
784
598
|
if (usedCount >= config.maxUsagePerOrder) {
|
|
785
599
|
isAvailable = false;
|
|
786
|
-
reasonCode =
|
|
600
|
+
reasonCode = "usage_limit_reached";
|
|
787
601
|
}
|
|
788
602
|
}
|
|
789
603
|
if (isAvailable) {
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
604
|
+
let applicableProducts = getApplicableProducts(
|
|
605
|
+
voucher,
|
|
606
|
+
productsForCalc
|
|
607
|
+
).filter((p) => p[amountField].greaterThan(0));
|
|
794
608
|
applicableProducts = filterByMaxPassesPerItemRecalc(applicableProducts, product_id, maxPassesPerItem);
|
|
795
609
|
if (applicableProducts.length === 0) {
|
|
796
610
|
isAvailable = false;
|
|
797
|
-
reasonCode =
|
|
611
|
+
reasonCode = "not_meet_the_required_conditions";
|
|
798
612
|
} else {
|
|
799
|
-
|
|
800
|
-
|
|
613
|
+
const baseAmount = import_decimal.default.min(
|
|
614
|
+
new import_decimal.default(recommendedAmount),
|
|
615
|
+
new import_decimal.default(maxDeductionAmount)
|
|
616
|
+
);
|
|
801
617
|
if (allowCrossProduct) {
|
|
802
618
|
if (applicableProductLimit > 0) {
|
|
803
|
-
// 按剩余金额从高到低排序,按动态计算的可抵扣数量累计直到达到 limit
|
|
804
619
|
const sortedProducts = [...applicableProducts].sort((a, b) => a[amountField].comparedTo(b[amountField]) > 0 ? -1 : 1);
|
|
805
620
|
let remainingLimit = applicableProductLimit;
|
|
806
621
|
for (const product of sortedProducts) {
|
|
807
|
-
if (remainingLimit <= 0)
|
|
808
|
-
|
|
622
|
+
if (remainingLimit <= 0)
|
|
623
|
+
break;
|
|
809
624
|
const currentAvailableQty = Math.ceil(product[amountField].dividedBy(product[unitPriceField]).toNumber());
|
|
810
625
|
const deductQty = Math.min(currentAvailableQty, remainingLimit);
|
|
811
|
-
|
|
812
|
-
|
|
626
|
+
const deductAmount = import_decimal.default.min(
|
|
627
|
+
product[unitPriceField].times(deductQty),
|
|
628
|
+
product[amountField]
|
|
629
|
+
);
|
|
813
630
|
calculatedMaxAmount = calculatedMaxAmount.plus(deductAmount);
|
|
814
631
|
remainingLimit -= deductQty;
|
|
815
632
|
}
|
|
816
633
|
} else {
|
|
817
|
-
|
|
818
|
-
|
|
634
|
+
calculatedMaxAmount = applicableProducts.reduce(
|
|
635
|
+
(sum, p) => sum.plus(p[amountField]),
|
|
636
|
+
new import_decimal.default(0)
|
|
637
|
+
);
|
|
819
638
|
}
|
|
820
639
|
} else {
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
640
|
+
const maxProduct = applicableProducts.reduce(
|
|
641
|
+
(max, p) => p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max
|
|
642
|
+
);
|
|
824
643
|
if (maxPassesPerItem > 0) {
|
|
825
|
-
calculatedMaxAmount =
|
|
644
|
+
calculatedMaxAmount = import_decimal.default.min(
|
|
645
|
+
maxProduct[unitPriceField].times(maxPassesPerItem),
|
|
646
|
+
maxProduct[amountField]
|
|
647
|
+
);
|
|
826
648
|
} else {
|
|
827
649
|
calculatedMaxAmount = maxProduct[amountField];
|
|
828
650
|
}
|
|
829
651
|
}
|
|
830
|
-
calculatedMaxAmount =
|
|
652
|
+
calculatedMaxAmount = import_decimal.default.min(
|
|
653
|
+
baseAmount,
|
|
654
|
+
calculatedMaxAmount,
|
|
655
|
+
remainingOrderAmount
|
|
656
|
+
);
|
|
831
657
|
if (calculatedMaxAmount.lessThanOrEqualTo(0)) {
|
|
832
658
|
isAvailable = false;
|
|
833
|
-
reasonCode =
|
|
659
|
+
reasonCode = "exceeds_the_maximum_deduction_limit";
|
|
834
660
|
}
|
|
835
661
|
}
|
|
836
662
|
}
|
|
@@ -840,9 +666,7 @@ function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmount, pr
|
|
|
840
666
|
_available_max_amount: calculatedMaxAmount.toNumber(),
|
|
841
667
|
// 转换为数字
|
|
842
668
|
_unified_available_status: isAvailable ? 1 : 0,
|
|
843
|
-
...
|
|
844
|
-
reasonCode
|
|
845
|
-
})
|
|
669
|
+
...reasonCode && { reasonCode }
|
|
846
670
|
};
|
|
847
671
|
});
|
|
848
672
|
return {
|
|
@@ -850,158 +674,47 @@ function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmount, pr
|
|
|
850
674
|
selectedWithDetails
|
|
851
675
|
};
|
|
852
676
|
}
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
* @param isDeductTaxAndFee 是否抵扣税费与附加费
|
|
858
|
-
* @returns 舍入余数(税费 + 附加费的舍入余数)
|
|
859
|
-
*/
|
|
860
|
-
const getTaxAndFeeRoundingRemainder = (product, isDeductTaxAndFee) => {
|
|
861
|
-
if (!isDeductTaxAndFee) {
|
|
862
|
-
return 0;
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
// 税费舍入余数(如果价格包含税则为0)
|
|
866
|
-
let taxFeeRoundingRemainder = new _decimal.default(0);
|
|
867
|
-
if (product.is_price_include_tax !== 1) {
|
|
868
|
-
taxFeeRoundingRemainder = new _decimal.default(product?.metadata?.tax_fee_rounding_remainder || 0);
|
|
869
|
-
}
|
|
870
|
-
|
|
871
|
-
// 附加费舍入余数
|
|
872
|
-
const surchargeFeeRoundingRemainder = new _decimal.default(product?.metadata?.surcharge_rounding_remainder || 0);
|
|
873
|
-
return taxFeeRoundingRemainder.add(surchargeFeeRoundingRemainder).toNumber();
|
|
874
|
-
};
|
|
875
|
-
|
|
876
|
-
/**
|
|
877
|
-
* 获取主商品的商品差额
|
|
878
|
-
* @param product 商品
|
|
879
|
-
* @returns 商品差额(与数量无关,计算总价时需要减去)
|
|
880
|
-
*/
|
|
881
|
-
exports.getTaxAndFeeRoundingRemainder = getTaxAndFeeRoundingRemainder;
|
|
882
|
-
const getProductDiscountDifference = product => {
|
|
883
|
-
return new _decimal.default(product?.metadata?.product_discount_difference || 0).toNumber();
|
|
884
|
-
};
|
|
885
|
-
|
|
886
|
-
/**
|
|
887
|
-
* 获取主商品价格(单价,不含舍入余数)
|
|
888
|
-
* @param product 商品
|
|
889
|
-
* @param isDeductTaxAndFee 是否抵扣税费与附加费
|
|
890
|
-
* @returns 商品单价
|
|
891
|
-
*/
|
|
892
|
-
exports.getProductDiscountDifference = getProductDiscountDifference;
|
|
893
|
-
const getMainProductPrice = (product, isDeductTaxAndFee) => {
|
|
894
|
-
let mainProductPrice = new _decimal.default(product?.main_product_selling_price || product.metadata?.main_product_selling_price || 0);
|
|
895
|
-
for (let bundleItem of product?.product_bundle || []) {
|
|
896
|
-
// 子商品是加价或减价才需要计算
|
|
677
|
+
var getMainProductPrice = (product, isDeductTaxAndFee) => {
|
|
678
|
+
var _a, _b, _c, _d, _e;
|
|
679
|
+
let mainProductPrice = new import_decimal.default((product == null ? void 0 : product.main_product_selling_price) || ((_a = product.metadata) == null ? void 0 : _a.main_product_selling_price) || 0);
|
|
680
|
+
for (let bundleItem of (product == null ? void 0 : product.product_bundle) || []) {
|
|
897
681
|
if (getBundleItemIsMarkupOrDiscountPrice(bundleItem)) {
|
|
898
|
-
|
|
899
|
-
const bundleItemPrice = new _decimal.default(bundleItem.bundle_selling_price ?? 0);
|
|
682
|
+
const bundleItemPrice = new import_decimal.default(bundleItem.bundle_selling_price ?? 0);
|
|
900
683
|
mainProductPrice = mainProductPrice.add(bundleItemPrice.times(bundleItem.num));
|
|
901
684
|
}
|
|
902
685
|
}
|
|
903
|
-
let taxFee = new
|
|
686
|
+
let taxFee = new import_decimal.default((product == null ? void 0 : product.tax_fee) || ((_b = product == null ? void 0 : product.metadata) == null ? void 0 : _b.main_product_attached_bundle_tax_fee) || 0).add(((_c = product == null ? void 0 : product.metadata) == null ? void 0 : _c.tax_fee_rounding_remainder) || 0);
|
|
904
687
|
if (product.is_price_include_tax === 1) {
|
|
905
|
-
taxFee = new
|
|
688
|
+
taxFee = new import_decimal.default(0);
|
|
906
689
|
}
|
|
907
|
-
|
|
908
|
-
// 税费
|
|
909
|
-
// 附加费
|
|
910
|
-
const surchargeFee = new _decimal.default(product?.metadata?.main_product_attached_bundle_surcharge_fee || 0).add(product?.metadata?.surcharge_rounding_remainder || 0);
|
|
911
|
-
|
|
912
|
-
// 税费附加费总额
|
|
690
|
+
const surchargeFee = new import_decimal.default(((_d = product == null ? void 0 : product.metadata) == null ? void 0 : _d.main_product_attached_bundle_surcharge_fee) || 0).add(((_e = product == null ? void 0 : product.metadata) == null ? void 0 : _e.surcharge_rounding_remainder) || 0);
|
|
913
691
|
const taxAndFeeTotal = taxFee.add(surchargeFee);
|
|
914
|
-
|
|
915
|
-
// 如果需要抵扣税费与附加费,则加上税费附加费总额
|
|
916
692
|
if (isDeductTaxAndFee) {
|
|
917
693
|
mainProductPrice = mainProductPrice.add(taxAndFeeTotal);
|
|
918
694
|
}
|
|
919
695
|
return mainProductPrice.toNumber();
|
|
920
696
|
};
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
* 获取套餐子商品税费和附加费的舍入余数
|
|
924
|
-
* @param bundleItem 套餐子商品
|
|
925
|
-
* @param isDeductTaxAndFee 是否抵扣税费与附加费
|
|
926
|
-
* @returns 舍入余数(税费 + 附加费的舍入余数)
|
|
927
|
-
*/
|
|
928
|
-
exports.getMainProductPrice = getMainProductPrice;
|
|
929
|
-
const getBundleItemTaxAndFeeRoundingRemainder = (bundleItem, isDeductTaxAndFee) => {
|
|
930
|
-
if (!isDeductTaxAndFee) {
|
|
931
|
-
return 0;
|
|
932
|
-
}
|
|
933
|
-
|
|
934
|
-
// 税费舍入余数(如果价格包含税则为0)
|
|
935
|
-
let taxFeeRoundingRemainder = new _decimal.default(0);
|
|
936
|
-
if (bundleItem.is_price_include_tax !== 1) {
|
|
937
|
-
taxFeeRoundingRemainder = new _decimal.default(bundleItem.metadata?.tax_fee_rounding_remainder || 0);
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
// 附加费舍入余数
|
|
941
|
-
const surchargeFeeRoundingRemainder = new _decimal.default(bundleItem.metadata?.surcharge_rounding_remainder || 0);
|
|
942
|
-
return taxFeeRoundingRemainder.add(surchargeFeeRoundingRemainder).toNumber();
|
|
943
|
-
};
|
|
944
|
-
|
|
945
|
-
/**
|
|
946
|
-
* 获取套餐子商品的商品差额
|
|
947
|
-
* @param bundleItem 套餐子商品
|
|
948
|
-
* @returns 商品差额(与数量无关,计算总价时需要减去)
|
|
949
|
-
*/
|
|
950
|
-
exports.getBundleItemTaxAndFeeRoundingRemainder = getBundleItemTaxAndFeeRoundingRemainder;
|
|
951
|
-
const getBundleItemDiscountDifference = bundleItem => {
|
|
952
|
-
return new _decimal.default(bundleItem.metadata?.product_discount_difference || 0).toNumber();
|
|
953
|
-
};
|
|
954
|
-
|
|
955
|
-
/**
|
|
956
|
-
* 获取套餐子商品价格(不含舍入余数)
|
|
957
|
-
* @param bundleItem 套餐子商品
|
|
958
|
-
* @param parentQuantity 父商品数量
|
|
959
|
-
* @param isDeductTaxAndFee 是否抵扣税费与附加费
|
|
960
|
-
* @returns 子商品总价格(不含舍入余数)
|
|
961
|
-
*/
|
|
962
|
-
exports.getBundleItemDiscountDifference = getBundleItemDiscountDifference;
|
|
963
|
-
const getBundleItemPrice = (bundleItem, parentQuantity, isDeductTaxAndFee) => {
|
|
964
|
-
// 子商品基础价格 = bundle_selling_price * num * 主商品数量
|
|
697
|
+
var getBundleItemPrice = (bundleItem, parentQuantity, isDeductTaxAndFee) => {
|
|
698
|
+
var _a;
|
|
965
699
|
const totalQuantity = bundleItem.num * parentQuantity;
|
|
966
|
-
let bundleItemPrice = new
|
|
967
|
-
|
|
968
|
-
// 根据 deductTaxAndFee 配置决定是否加上税费和附加费
|
|
700
|
+
let bundleItemPrice = new import_decimal.default(bundleItem.bundle_selling_price ?? 0).times(totalQuantity);
|
|
969
701
|
if (isDeductTaxAndFee) {
|
|
970
|
-
|
|
971
|
-
let taxFee = new _decimal.default(bundleItem.tax_fee ?? 0).times(totalQuantity);
|
|
702
|
+
let taxFee = new import_decimal.default(bundleItem.tax_fee ?? 0).times(totalQuantity);
|
|
972
703
|
if (bundleItem.is_price_include_tax === 1) {
|
|
973
|
-
taxFee = new
|
|
704
|
+
taxFee = new import_decimal.default(0);
|
|
974
705
|
}
|
|
975
|
-
|
|
976
|
-
const surchargeFee = new _decimal.default(bundleItem.metadata?.surcharge_fee ?? 0).times(totalQuantity);
|
|
706
|
+
const surchargeFee = new import_decimal.default(((_a = bundleItem.metadata) == null ? void 0 : _a.surcharge_fee) ?? 0).times(totalQuantity);
|
|
977
707
|
bundleItemPrice = bundleItemPrice.add(taxFee).add(surchargeFee);
|
|
978
708
|
}
|
|
979
709
|
return bundleItemPrice.toNumber();
|
|
980
710
|
};
|
|
981
|
-
|
|
982
|
-
/**
|
|
983
|
-
* 将商品数据拆分,包含主商品和原价子商品
|
|
984
|
-
* @param products 原始商品列表
|
|
985
|
-
* @param deductTaxAndFee 是否抵扣税费与附加费(已废弃,保留参数以兼容旧代码)
|
|
986
|
-
* @returns 拆分后的商品数据(包含主商品和子商品,同时维护含税和不含税两个金额池,以及单价和剩余数量)
|
|
987
|
-
*/
|
|
988
|
-
exports.getBundleItemPrice = getBundleItemPrice;
|
|
989
|
-
const expandProductsWithBundleItems = (products, deductTaxAndFee) => {
|
|
711
|
+
var expandProductsWithBundleItems = (products, deductTaxAndFee) => {
|
|
990
712
|
const expandedProducts = [];
|
|
991
713
|
products.forEach((product, indexInOrder) => {
|
|
992
714
|
const productQuantity = getProductQuantity(product);
|
|
993
715
|
const parentLineKey = resolveWalletPassLineKey(product, indexInOrder);
|
|
994
|
-
|
|
995
|
-
// 计算主商品单价(含税和不含税)
|
|
996
716
|
const unitPriceWithTax = getMainProductPrice(product, true);
|
|
997
717
|
const unitPricePure = getMainProductPrice(product, false);
|
|
998
|
-
|
|
999
|
-
// 获取舍入余数(与数量无关,只加一次)
|
|
1000
|
-
const roundingRemainderWithTax = getTaxAndFeeRoundingRemainder(product, true);
|
|
1001
|
-
// 获取商品差额(与数量无关,计算总价时需要减去)
|
|
1002
|
-
const discountDifference = getProductDiscountDifference(product);
|
|
1003
|
-
|
|
1004
|
-
// 1. 添加主商品(同时计算含税和不含税两个金额,以及单价和剩余数量)
|
|
1005
718
|
expandedProducts.push({
|
|
1006
719
|
...product,
|
|
1007
720
|
is_bundle_item: false,
|
|
@@ -1009,32 +722,22 @@ const expandProductsWithBundleItems = (products, deductTaxAndFee) => {
|
|
|
1009
722
|
_walletPassLineKey: parentLineKey,
|
|
1010
723
|
_orderLineQuantity: productQuantity,
|
|
1011
724
|
// 单价(用于按 quantity 计算抵扣)
|
|
1012
|
-
unitPriceWithTax: new
|
|
1013
|
-
unitPricePure: new
|
|
725
|
+
unitPriceWithTax: new import_decimal.default(unitPriceWithTax),
|
|
726
|
+
unitPricePure: new import_decimal.default(unitPricePure),
|
|
1014
727
|
// 剩余可抵扣数量
|
|
1015
728
|
remainingQuantity: productQuantity,
|
|
1016
|
-
//
|
|
1017
|
-
remainingAmountWithTax: new
|
|
1018
|
-
//
|
|
1019
|
-
remainingAmountPure: new
|
|
729
|
+
// 含税费的剩余金额
|
|
730
|
+
remainingAmountWithTax: new import_decimal.default(unitPriceWithTax).times(productQuantity),
|
|
731
|
+
// 纯商品金额(不含税费)
|
|
732
|
+
remainingAmountPure: new import_decimal.default(unitPricePure).times(productQuantity)
|
|
1020
733
|
});
|
|
1021
|
-
|
|
1022
|
-
// 2. 添加原价子商品(作为独立商品项)
|
|
1023
734
|
if (product.product_bundle && product.product_bundle.length > 0) {
|
|
1024
|
-
product.product_bundle.forEach(bundleItem => {
|
|
735
|
+
product.product_bundle.forEach((bundleItem) => {
|
|
1025
736
|
if (getBundleItemIsOriginalPrice(bundleItem)) {
|
|
1026
737
|
const bundleQuantity = bundleItem.num * productQuantity;
|
|
1027
738
|
const bundleLineKey = `${parentLineKey}#bundle:${bundleItem.bundle_id}:${bundleItem.bundle_product_id}`;
|
|
1028
|
-
|
|
1029
|
-
const
|
|
1030
|
-
const bundleUnitPricePure = new _decimal.default(getBundleItemPrice(bundleItem, 1, false)).dividedBy(bundleItem.num);
|
|
1031
|
-
|
|
1032
|
-
// 获取子商品舍入余数(与数量无关,只加一次)
|
|
1033
|
-
const bundleRoundingRemainder = getBundleItemTaxAndFeeRoundingRemainder(bundleItem, true);
|
|
1034
|
-
// 获取子商品差额(与数量无关,计算总价时需要减去)
|
|
1035
|
-
const bundleDiscountDifference = getBundleItemDiscountDifference(bundleItem);
|
|
1036
|
-
|
|
1037
|
-
// 原价子商品作为独立商品
|
|
739
|
+
const bundleUnitPriceWithTax = new import_decimal.default(getBundleItemPrice(bundleItem, 1, true)).dividedBy(bundleItem.num);
|
|
740
|
+
const bundleUnitPricePure = new import_decimal.default(getBundleItemPrice(bundleItem, 1, false)).dividedBy(bundleItem.num);
|
|
1038
741
|
expandedProducts.push({
|
|
1039
742
|
...bundleItem,
|
|
1040
743
|
product_id: bundleItem.bundle_product_id,
|
|
@@ -1050,10 +753,10 @@ const expandProductsWithBundleItems = (products, deductTaxAndFee) => {
|
|
|
1050
753
|
unitPricePure: bundleUnitPricePure,
|
|
1051
754
|
// 剩余可抵扣数量
|
|
1052
755
|
remainingQuantity: bundleQuantity,
|
|
1053
|
-
//
|
|
1054
|
-
remainingAmountWithTax: new
|
|
1055
|
-
//
|
|
1056
|
-
remainingAmountPure: new
|
|
756
|
+
// 含税费的剩余金额
|
|
757
|
+
remainingAmountWithTax: new import_decimal.default(getBundleItemPrice(bundleItem, productQuantity, true)),
|
|
758
|
+
// 纯商品金额(不含税费)
|
|
759
|
+
remainingAmountPure: new import_decimal.default(getBundleItemPrice(bundleItem, productQuantity, false))
|
|
1057
760
|
});
|
|
1058
761
|
}
|
|
1059
762
|
});
|
|
@@ -1061,27 +764,29 @@ const expandProductsWithBundleItems = (products, deductTaxAndFee) => {
|
|
|
1061
764
|
});
|
|
1062
765
|
return expandedProducts;
|
|
1063
766
|
};
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
const getBundleItemIsOriginalPrice = item => {
|
|
1067
|
-
return item?.price_type === 'markup' && item?.price_type_ext === 'product_price';
|
|
767
|
+
var getBundleItemIsOriginalPrice = (item) => {
|
|
768
|
+
return (item == null ? void 0 : item.price_type) === "markup" && (item == null ? void 0 : item.price_type_ext) === "product_price";
|
|
1068
769
|
};
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
exports.getBundleItemIsOriginalPrice = getBundleItemIsOriginalPrice;
|
|
1072
|
-
const getBundleItemIsMarkupPrice = item => {
|
|
1073
|
-
return item?.price_type === 'markup' && (item?.price_type_ext === '' || !item?.price_type_ext);
|
|
770
|
+
var getBundleItemIsMarkupPrice = (item) => {
|
|
771
|
+
return (item == null ? void 0 : item.price_type) === "markup" && ((item == null ? void 0 : item.price_type_ext) === "" || !(item == null ? void 0 : item.price_type_ext));
|
|
1074
772
|
};
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
exports.getBundleItemIsMarkupPrice = getBundleItemIsMarkupPrice;
|
|
1078
|
-
const getBundleItemIsDiscountPrice = item => {
|
|
1079
|
-
return item?.price_type === 'markdown' && (item?.price_type_ext === '' || !item?.price_type_ext);
|
|
773
|
+
var getBundleItemIsDiscountPrice = (item) => {
|
|
774
|
+
return (item == null ? void 0 : item.price_type) === "markdown" && ((item == null ? void 0 : item.price_type_ext) === "" || !(item == null ? void 0 : item.price_type_ext));
|
|
1080
775
|
};
|
|
1081
|
-
|
|
1082
|
-
// bundle商品是否是加价或减价
|
|
1083
|
-
exports.getBundleItemIsDiscountPrice = getBundleItemIsDiscountPrice;
|
|
1084
|
-
const getBundleItemIsMarkupOrDiscountPrice = item => {
|
|
776
|
+
var getBundleItemIsMarkupOrDiscountPrice = (item) => {
|
|
1085
777
|
return getBundleItemIsMarkupPrice(item) || getBundleItemIsDiscountPrice(item);
|
|
1086
778
|
};
|
|
1087
|
-
|
|
779
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
780
|
+
0 && (module.exports = {
|
|
781
|
+
getApplicableProductIds,
|
|
782
|
+
getBundleItemIsDiscountPrice,
|
|
783
|
+
getBundleItemIsMarkupOrDiscountPrice,
|
|
784
|
+
getBundleItemIsMarkupPrice,
|
|
785
|
+
getBundleItemIsOriginalPrice,
|
|
786
|
+
getBundleItemPrice,
|
|
787
|
+
getMainProductPrice,
|
|
788
|
+
getProductQuantity,
|
|
789
|
+
processVouchers,
|
|
790
|
+
recalculateVouchers,
|
|
791
|
+
resolveWalletPassLineKey
|
|
792
|
+
});
|