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