@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,122 +1,128 @@
|
|
|
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/promotion/evaluator.ts
|
|
30
|
-
var evaluator_exports = {};
|
|
31
|
-
__export(evaluator_exports, {
|
|
32
|
-
PromotionEvaluator: () => PromotionEvaluator
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
33
5
|
});
|
|
34
|
-
|
|
35
|
-
var
|
|
36
|
-
var
|
|
37
|
-
var
|
|
38
|
-
var
|
|
39
|
-
|
|
6
|
+
exports.PromotionEvaluator = void 0;
|
|
7
|
+
var _decimal = _interopRequireDefault(require("decimal.js"));
|
|
8
|
+
var _engine = require("../../engine");
|
|
9
|
+
var _adapter = require("./adapter");
|
|
10
|
+
var _type = require("./type");
|
|
11
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
12
|
+
// ============================================
|
|
13
|
+
// 类型定义
|
|
14
|
+
// ============================================
|
|
15
|
+
|
|
16
|
+
// ============================================
|
|
17
|
+
// 多语言定义
|
|
18
|
+
// ============================================
|
|
19
|
+
|
|
20
|
+
const defaultLocales = {
|
|
40
21
|
en: {
|
|
41
|
-
no_applicable_promotion:
|
|
42
|
-
promotion_not_in_time_range:
|
|
43
|
-
product_not_in_promotion:
|
|
22
|
+
no_applicable_promotion: 'No applicable promotion',
|
|
23
|
+
promotion_not_in_time_range: 'Promotion not in valid time range',
|
|
24
|
+
product_not_in_promotion: 'Product not in promotion scope'
|
|
44
25
|
},
|
|
45
|
-
|
|
46
|
-
no_applicable_promotion:
|
|
47
|
-
promotion_not_in_time_range:
|
|
48
|
-
product_not_in_promotion:
|
|
26
|
+
'zh-CN': {
|
|
27
|
+
no_applicable_promotion: '无适用的促销活动',
|
|
28
|
+
promotion_not_in_time_range: '促销活动不在有效时间范围内',
|
|
29
|
+
product_not_in_promotion: '商品不在促销范围内'
|
|
49
30
|
},
|
|
50
|
-
|
|
51
|
-
no_applicable_promotion:
|
|
52
|
-
promotion_not_in_time_range:
|
|
53
|
-
product_not_in_promotion:
|
|
31
|
+
'zh-HK': {
|
|
32
|
+
no_applicable_promotion: '無適用的促銷活動',
|
|
33
|
+
promotion_not_in_time_range: '促銷活動不在有效時間範圍內',
|
|
34
|
+
product_not_in_promotion: '商品不在促銷範圍內'
|
|
54
35
|
}
|
|
55
36
|
};
|
|
56
|
-
|
|
37
|
+
|
|
38
|
+
// ============================================
|
|
39
|
+
// PromotionEvaluator 实现
|
|
40
|
+
// ============================================
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Promotion 评估器
|
|
44
|
+
*
|
|
45
|
+
* 用于评估商品适用的促销活动
|
|
46
|
+
* 封装了 StrategyEngine 和 PromotionAdapter 的调用逻辑
|
|
47
|
+
*/
|
|
48
|
+
class PromotionEvaluator {
|
|
49
|
+
engine;
|
|
50
|
+
adapter;
|
|
51
|
+
strategyConfigs = [];
|
|
52
|
+
locale = 'en';
|
|
53
|
+
locales = defaultLocales;
|
|
57
54
|
constructor() {
|
|
58
|
-
this.
|
|
59
|
-
this.locale = "en";
|
|
60
|
-
this.locales = defaultLocales;
|
|
61
|
-
this.engine = new import_engine.StrategyEngine({
|
|
55
|
+
this.engine = new _engine.StrategyEngine({
|
|
62
56
|
debug: false,
|
|
63
57
|
enableTrace: false
|
|
64
58
|
});
|
|
65
|
-
this.adapter = new
|
|
59
|
+
this.adapter = new _adapter.PromotionAdapter();
|
|
66
60
|
}
|
|
61
|
+
|
|
67
62
|
// ============================================
|
|
68
63
|
// 配置管理
|
|
69
64
|
// ============================================
|
|
65
|
+
|
|
70
66
|
/**
|
|
71
67
|
* 设置策略配置列表
|
|
72
68
|
*/
|
|
73
69
|
setStrategyConfigs(strategyConfigs) {
|
|
74
|
-
const newStrategyConfigs = strategyConfigs.filter(
|
|
70
|
+
const newStrategyConfigs = strategyConfigs.filter(item => item.metadata.type === 'promotion');
|
|
75
71
|
this.strategyConfigs = newStrategyConfigs;
|
|
76
72
|
}
|
|
73
|
+
|
|
77
74
|
/**
|
|
78
75
|
* 获取策略配置列表
|
|
79
76
|
*/
|
|
80
77
|
getStrategyConfigs() {
|
|
81
78
|
return this.strategyConfigs;
|
|
82
79
|
}
|
|
80
|
+
|
|
83
81
|
/**
|
|
84
82
|
* 添加策略配置
|
|
85
83
|
*/
|
|
86
84
|
addStrategyConfig(strategyConfig) {
|
|
87
85
|
this.strategyConfigs.push(strategyConfig);
|
|
88
86
|
}
|
|
87
|
+
|
|
89
88
|
/**
|
|
90
89
|
* 设置语言
|
|
91
90
|
*/
|
|
92
91
|
setLocale(locale) {
|
|
93
92
|
this.locale = locale;
|
|
94
93
|
}
|
|
94
|
+
|
|
95
95
|
/**
|
|
96
96
|
* 设置自定义多语言文案
|
|
97
97
|
*/
|
|
98
98
|
setLocales(locales) {
|
|
99
|
-
this.locales = {
|
|
99
|
+
this.locales = {
|
|
100
|
+
...defaultLocales,
|
|
101
|
+
...locales
|
|
102
|
+
};
|
|
100
103
|
}
|
|
104
|
+
|
|
101
105
|
/**
|
|
102
106
|
* 获取多语言文案
|
|
103
107
|
*/
|
|
104
108
|
getText(key) {
|
|
105
|
-
|
|
106
|
-
return ((_b = (_a = this.locales) == null ? void 0 : _a[this.locale]) == null ? void 0 : _b[key]) || key;
|
|
109
|
+
return this.locales?.[this.locale]?.[key] || key;
|
|
107
110
|
}
|
|
111
|
+
|
|
108
112
|
/**
|
|
109
113
|
* 获取多语言名称
|
|
110
114
|
*/
|
|
111
115
|
getLocalizedName(name) {
|
|
112
|
-
if (typeof name ===
|
|
116
|
+
if (typeof name === 'string') {
|
|
113
117
|
return name;
|
|
114
118
|
}
|
|
115
|
-
return name[this.locale] || name[
|
|
119
|
+
return name[this.locale] || name['en'] || Object.values(name)[0] || '';
|
|
116
120
|
}
|
|
121
|
+
|
|
117
122
|
// ============================================
|
|
118
123
|
// 核心评估方法
|
|
119
124
|
// ============================================
|
|
125
|
+
|
|
120
126
|
/**
|
|
121
127
|
* 评估商品列表
|
|
122
128
|
*
|
|
@@ -127,19 +133,31 @@ var PromotionEvaluator = class {
|
|
|
127
133
|
* @returns 每个商品的促销评估结果
|
|
128
134
|
*/
|
|
129
135
|
evaluateProducts(input) {
|
|
130
|
-
const {
|
|
136
|
+
const {
|
|
137
|
+
products,
|
|
138
|
+
strategyConfigs,
|
|
139
|
+
channel
|
|
140
|
+
} = input;
|
|
131
141
|
const configs = strategyConfigs || this.strategyConfigs;
|
|
132
142
|
const results = [];
|
|
133
143
|
for (const product of products) {
|
|
134
144
|
const applicablePromotions = [];
|
|
145
|
+
|
|
146
|
+
// 遍历所有策略,检查此商品是否适用
|
|
135
147
|
for (const config of configs) {
|
|
148
|
+
// 1. 先用 getProductMatchInfo 检查商品是否在策略的适用范围内(包含 bundle 子商品检查)
|
|
136
149
|
const matchInfo = this.getProductMatchInfo(product, config);
|
|
137
150
|
if (!matchInfo.isMatch) {
|
|
151
|
+
// 商品不在策略适用范围内,跳过
|
|
138
152
|
continue;
|
|
139
153
|
}
|
|
154
|
+
|
|
155
|
+
// 2. 准备上下文(如果是 bundle 子商品匹配,需要用 bundle 子商品的 ID)
|
|
140
156
|
let contextProduct = product;
|
|
141
|
-
if (matchInfo.matchedBundleIndex !==
|
|
157
|
+
if (matchInfo.matchedBundleIndex !== undefined && product.bundle) {
|
|
142
158
|
const bundleItem = product.bundle[matchInfo.matchedBundleIndex];
|
|
159
|
+
// 创建一个临时的"虚拟商品"用于策略引擎评估
|
|
160
|
+
// 这样策略引擎的 product_match 条件能正确通过
|
|
143
161
|
contextProduct = {
|
|
144
162
|
...product,
|
|
145
163
|
product_id: bundleItem._bundle_product_id,
|
|
@@ -151,6 +169,8 @@ var PromotionEvaluator = class {
|
|
|
151
169
|
currentProduct: contextProduct,
|
|
152
170
|
channel
|
|
153
171
|
});
|
|
172
|
+
|
|
173
|
+
// 3. 评估策略(检查其他条件如时间范围等)
|
|
154
174
|
const result = this.engine.evaluate(config, context);
|
|
155
175
|
if (result.applicable && result.matchedActions.length > 0) {
|
|
156
176
|
const action = result.matchedActions[0];
|
|
@@ -181,6 +201,7 @@ var PromotionEvaluator = class {
|
|
|
181
201
|
}
|
|
182
202
|
return results;
|
|
183
203
|
}
|
|
204
|
+
|
|
184
205
|
/**
|
|
185
206
|
* 评估购物车
|
|
186
207
|
*
|
|
@@ -191,29 +212,42 @@ var PromotionEvaluator = class {
|
|
|
191
212
|
* @returns 购物车评估结果
|
|
192
213
|
*/
|
|
193
214
|
evaluateCart(input) {
|
|
194
|
-
const {
|
|
215
|
+
const {
|
|
216
|
+
products,
|
|
217
|
+
strategyConfigs,
|
|
218
|
+
channel
|
|
219
|
+
} = input;
|
|
195
220
|
const configs = strategyConfigs || this.strategyConfigs;
|
|
221
|
+
|
|
222
|
+
// 1. 先获取每个商品的促销结果
|
|
196
223
|
const productResults = this.evaluateProducts(input);
|
|
197
|
-
|
|
224
|
+
|
|
225
|
+
// 2. 收集所有适用的促销(去重)
|
|
226
|
+
const promotionMap = new Map();
|
|
198
227
|
for (const productResult of productResults) {
|
|
199
228
|
for (const promo of productResult.applicablePromotions) {
|
|
200
229
|
const existing = promotionMap.get(promo.strategyId);
|
|
201
230
|
const product = productResult.product;
|
|
231
|
+
|
|
232
|
+
// 计算促销数量:如果是 bundle 子商品匹配,数量 = 主商品数量 × 子商品数量
|
|
202
233
|
let promoQuantity = product.quantity;
|
|
203
|
-
if (promo.matchedBundleIndex !==
|
|
234
|
+
if (promo.matchedBundleIndex !== undefined && product.bundle) {
|
|
204
235
|
const bundleItem = product.bundle[promo.matchedBundleIndex];
|
|
205
236
|
promoQuantity = product.quantity * (bundleItem.quantity || 1);
|
|
206
237
|
}
|
|
207
238
|
if (existing) {
|
|
239
|
+
// 已存在,添加商品到列表
|
|
208
240
|
existing.applicableProducts.push(product);
|
|
209
241
|
existing.totalQuantity += promoQuantity;
|
|
210
242
|
existing.totalAmount += product.price * product.quantity;
|
|
243
|
+
// 记录每个商品的 matchedBundleIndex
|
|
211
244
|
if (!existing.productMatchedBundleIndexMap) {
|
|
212
|
-
existing.productMatchedBundleIndexMap =
|
|
245
|
+
existing.productMatchedBundleIndexMap = new Map();
|
|
213
246
|
}
|
|
214
247
|
existing.productMatchedBundleIndexMap.set(product.id, promo.matchedBundleIndex);
|
|
215
248
|
} else {
|
|
216
|
-
|
|
249
|
+
// 新促销
|
|
250
|
+
const productMatchedBundleIndexMap = new Map();
|
|
217
251
|
productMatchedBundleIndexMap.set(product.id, promo.matchedBundleIndex);
|
|
218
252
|
promotionMap.set(promo.strategyId, {
|
|
219
253
|
...promo,
|
|
@@ -226,30 +260,28 @@ var PromotionEvaluator = class {
|
|
|
226
260
|
}
|
|
227
261
|
}
|
|
228
262
|
const applicablePromotions = Array.from(promotionMap.values());
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
);
|
|
263
|
+
|
|
264
|
+
// 3. 按促销分组
|
|
265
|
+
const promotionGroups = applicablePromotions.map(promo => ({
|
|
266
|
+
strategyId: promo.strategyId,
|
|
267
|
+
strategyName: promo.strategyName,
|
|
268
|
+
strategyMetadata: promo.strategyConfig?.metadata,
|
|
269
|
+
strategyConfig: promo.strategyConfig,
|
|
270
|
+
actionType: promo.actionType,
|
|
271
|
+
actionDetail: promo.actionDetail,
|
|
272
|
+
products: promo.applicableProducts,
|
|
273
|
+
totalQuantity: promo.totalQuantity,
|
|
274
|
+
totalAmount: promo.totalAmount,
|
|
275
|
+
// 传递 productMatchedBundleIndexMap 到 group
|
|
276
|
+
productMatchedBundleIndexMap: promo.productMatchedBundleIndexMap
|
|
277
|
+
}));
|
|
247
278
|
return {
|
|
248
279
|
productResults,
|
|
249
280
|
applicablePromotions,
|
|
250
281
|
promotionGroups
|
|
251
282
|
};
|
|
252
283
|
}
|
|
284
|
+
|
|
253
285
|
/**
|
|
254
286
|
* 评估购物车并计算定价
|
|
255
287
|
*
|
|
@@ -261,60 +293,70 @@ var PromotionEvaluator = class {
|
|
|
261
293
|
* @returns 带定价的购物车评估结果
|
|
262
294
|
*/
|
|
263
295
|
evaluateCartWithPricing(input) {
|
|
264
|
-
const {
|
|
296
|
+
const {
|
|
297
|
+
products
|
|
298
|
+
} = input;
|
|
299
|
+
|
|
300
|
+
// 1. 先调用 evaluateCart 获取分组结果
|
|
265
301
|
const cartResult = this.evaluateCart(input);
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
302
|
+
|
|
303
|
+
// 2. 按 action priority 排序促销组(从 strategyConfig 获取 priority)
|
|
304
|
+
const sortedGroups = this.sortPromotionGroupsByPriority(cartResult.promotionGroups, cartResult.applicablePromotions);
|
|
305
|
+
|
|
306
|
+
// 3. 追踪已处理的商品(避免重复处理)
|
|
307
|
+
// key: `${product_id}_${product_variant_id}`
|
|
308
|
+
const processedQuantityMap = new Map();
|
|
309
|
+
|
|
310
|
+
// 4. 处理每个促销组,收集结果
|
|
271
311
|
const pricedProducts = [];
|
|
272
312
|
const gifts = [];
|
|
273
|
-
let totalOriginalAmount = new
|
|
274
|
-
let totalFinalAmount = new
|
|
313
|
+
let totalOriginalAmount = new _decimal.default(0);
|
|
314
|
+
let totalFinalAmount = new _decimal.default(0);
|
|
275
315
|
for (const group of sortedGroups) {
|
|
276
|
-
const {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
316
|
+
const {
|
|
317
|
+
actionType
|
|
318
|
+
} = group;
|
|
319
|
+
|
|
320
|
+
// 直接使用 evaluateCart 阶段计算好的 matchedBundleIndexMap
|
|
321
|
+
const matchedBundleIndexMap = group.productMatchedBundleIndexMap || new Map();
|
|
322
|
+
if (actionType === _type.PROMOTION_ACTION_TYPES.X_ITEMS_FOR_Y_PRICE) {
|
|
323
|
+
// X件Y元处理
|
|
324
|
+
const result = this.processXItemsForYPrice(group, processedQuantityMap, matchedBundleIndexMap);
|
|
284
325
|
pricedProducts.push(...result.products);
|
|
285
326
|
totalOriginalAmount = totalOriginalAmount.plus(result.originalAmount);
|
|
286
327
|
totalFinalAmount = totalFinalAmount.plus(result.finalAmount);
|
|
287
|
-
} else if (actionType ===
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
processedQuantityMap,
|
|
291
|
-
matchedBundleIndexMap
|
|
292
|
-
);
|
|
328
|
+
} else if (actionType === _type.PROMOTION_ACTION_TYPES.BUY_X_GET_Y_FREE) {
|
|
329
|
+
// 买X送Y处理
|
|
330
|
+
const result = this.processBuyXGetYFree(group, processedQuantityMap, matchedBundleIndexMap);
|
|
293
331
|
pricedProducts.push(...result.products);
|
|
294
332
|
totalOriginalAmount = totalOriginalAmount.plus(result.originalAmount);
|
|
295
333
|
totalFinalAmount = totalFinalAmount.plus(result.finalAmount);
|
|
334
|
+
|
|
335
|
+
// 添加赠品信息
|
|
296
336
|
if (result.giftInfo) {
|
|
297
337
|
gifts.push(result.giftInfo);
|
|
298
338
|
}
|
|
299
339
|
}
|
|
300
340
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
);
|
|
341
|
+
|
|
342
|
+
// 5. 处理未参与任何促销的商品
|
|
343
|
+
const remainingProducts = this.getRemainingProducts(products, processedQuantityMap);
|
|
305
344
|
for (const product of remainingProducts) {
|
|
306
|
-
const amount = new
|
|
345
|
+
const amount = new _decimal.default(product.price).mul(product.quantity);
|
|
307
346
|
totalOriginalAmount = totalOriginalAmount.plus(amount);
|
|
308
347
|
totalFinalAmount = totalFinalAmount.plus(amount);
|
|
309
348
|
}
|
|
310
349
|
pricedProducts.push(...remainingProducts);
|
|
350
|
+
|
|
351
|
+
// 6. 计算总优惠金额
|
|
311
352
|
const totalDiscount = totalOriginalAmount.minus(totalFinalAmount);
|
|
312
353
|
return {
|
|
313
354
|
products: pricedProducts,
|
|
314
355
|
gifts,
|
|
315
|
-
totalDiscount:
|
|
356
|
+
totalDiscount: _decimal.default.max(0, totalDiscount).toNumber()
|
|
316
357
|
};
|
|
317
358
|
}
|
|
359
|
+
|
|
318
360
|
/**
|
|
319
361
|
* 获取商品适用的促销列表
|
|
320
362
|
*
|
|
@@ -325,13 +367,13 @@ var PromotionEvaluator = class {
|
|
|
325
367
|
* @returns 适用的促销列表
|
|
326
368
|
*/
|
|
327
369
|
getProductPromotions(product, strategyConfigs) {
|
|
328
|
-
var _a;
|
|
329
370
|
const results = this.evaluateProducts({
|
|
330
371
|
products: [product],
|
|
331
372
|
strategyConfigs
|
|
332
373
|
});
|
|
333
|
-
return
|
|
374
|
+
return results[0]?.applicablePromotions || [];
|
|
334
375
|
}
|
|
376
|
+
|
|
335
377
|
/**
|
|
336
378
|
* 获取商品的促销标签
|
|
337
379
|
*
|
|
@@ -343,12 +385,13 @@ var PromotionEvaluator = class {
|
|
|
343
385
|
*/
|
|
344
386
|
getProductPromotionTags(product, strategyConfigs) {
|
|
345
387
|
const promotions = this.getProductPromotions(product, strategyConfigs);
|
|
346
|
-
return promotions.filter(
|
|
388
|
+
return promotions.filter(promo => promo.display).map(promo => ({
|
|
347
389
|
text: this.getLocalizedName(promo.display.text),
|
|
348
390
|
type: promo.display.type,
|
|
349
391
|
strategyId: promo.strategyId
|
|
350
392
|
}));
|
|
351
393
|
}
|
|
394
|
+
|
|
352
395
|
/**
|
|
353
396
|
* 查找商品适用的策略配置
|
|
354
397
|
*
|
|
@@ -358,10 +401,9 @@ var PromotionEvaluator = class {
|
|
|
358
401
|
*/
|
|
359
402
|
findApplicableStrategies(product, strategyConfigs) {
|
|
360
403
|
const configs = strategyConfigs || this.strategyConfigs;
|
|
361
|
-
return configs.filter(
|
|
362
|
-
(config) => this.isProductInStrategy(product, config)
|
|
363
|
-
);
|
|
404
|
+
return configs.filter(config => this.isProductInStrategy(product, config));
|
|
364
405
|
}
|
|
406
|
+
|
|
365
407
|
/**
|
|
366
408
|
* 批量获取商品列表的适用策略信息
|
|
367
409
|
*
|
|
@@ -373,23 +415,30 @@ var PromotionEvaluator = class {
|
|
|
373
415
|
* @returns 每个商品的适用策略完整数据
|
|
374
416
|
*/
|
|
375
417
|
getProductsApplicableStrategies(input, matchVariant = true) {
|
|
376
|
-
const {
|
|
418
|
+
const {
|
|
419
|
+
products,
|
|
420
|
+
strategyConfigs,
|
|
421
|
+
channel
|
|
422
|
+
} = input;
|
|
377
423
|
const configs = strategyConfigs || this.strategyConfigs;
|
|
378
424
|
const results = [];
|
|
379
425
|
for (const product of products) {
|
|
380
426
|
const applicableStrategies = [];
|
|
427
|
+
|
|
428
|
+
// 遍历所有策略,检查此商品是否适用
|
|
381
429
|
for (const config of configs) {
|
|
382
430
|
let contextProduct = product;
|
|
383
431
|
if (!matchVariant) {
|
|
432
|
+
// 只匹配 product_id,忽略 product_variant_id
|
|
384
433
|
const productMatchRule = this.findProductMatchRule(config);
|
|
385
434
|
if (productMatchRule) {
|
|
386
435
|
const configProducts = productMatchRule.value;
|
|
387
|
-
const matchedConfig = configProducts.find(
|
|
388
|
-
(item) => item.product_id === product.product_id
|
|
389
|
-
);
|
|
436
|
+
const matchedConfig = configProducts.find(item => item.product_id === product.product_id);
|
|
390
437
|
if (!matchedConfig) {
|
|
438
|
+
// product_id 不在策略适用范围内,跳过
|
|
391
439
|
continue;
|
|
392
440
|
}
|
|
441
|
+
// 用配置中的 variant_id 构造上下文,确保引擎 product_match 通过
|
|
393
442
|
if (matchedConfig.product_variant_id !== 0 && matchedConfig.product_variant_id !== product.product_variant_id) {
|
|
394
443
|
contextProduct = {
|
|
395
444
|
...product,
|
|
@@ -403,6 +452,8 @@ var PromotionEvaluator = class {
|
|
|
403
452
|
currentProduct: contextProduct,
|
|
404
453
|
channel
|
|
405
454
|
});
|
|
455
|
+
|
|
456
|
+
// 评估策略
|
|
406
457
|
const result = this.engine.evaluate(config, context);
|
|
407
458
|
if (result.applicable && result.matchedActions.length > 0) {
|
|
408
459
|
const action = result.matchedActions[0];
|
|
@@ -412,11 +463,11 @@ var PromotionEvaluator = class {
|
|
|
412
463
|
channel
|
|
413
464
|
});
|
|
414
465
|
if (transformedResult.actionDetail) {
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
);
|
|
466
|
+
// 计算所需数量和可参与商品列表
|
|
467
|
+
const {
|
|
468
|
+
requiredQuantity,
|
|
469
|
+
eligibleProducts
|
|
470
|
+
} = this.getPromotionRequirements(action.type, transformedResult.actionDetail, config);
|
|
420
471
|
applicableStrategies.push({
|
|
421
472
|
strategyId: config.metadata.id,
|
|
422
473
|
strategyName: config.metadata.name,
|
|
@@ -439,6 +490,7 @@ var PromotionEvaluator = class {
|
|
|
439
490
|
}
|
|
440
491
|
return results;
|
|
441
492
|
}
|
|
493
|
+
|
|
442
494
|
/**
|
|
443
495
|
* 获取促销所需数量和可参与商品列表
|
|
444
496
|
*
|
|
@@ -449,41 +501,50 @@ var PromotionEvaluator = class {
|
|
|
449
501
|
*/
|
|
450
502
|
getPromotionRequirements(actionType, actionDetail, config) {
|
|
451
503
|
let requiredQuantity = 0;
|
|
452
|
-
|
|
504
|
+
|
|
505
|
+
// 根据促销类型获取所需数量
|
|
506
|
+
if (actionType === 'BUY_X_GET_Y_FREE') {
|
|
453
507
|
const detail = actionDetail;
|
|
454
508
|
requiredQuantity = detail.buyQuantity || 0;
|
|
455
|
-
} else if (actionType ===
|
|
509
|
+
} else if (actionType === 'X_ITEMS_FOR_Y_PRICE') {
|
|
456
510
|
const detail = actionDetail;
|
|
457
511
|
requiredQuantity = detail.x || 0;
|
|
458
512
|
}
|
|
513
|
+
|
|
514
|
+
// 获取可参与商品列表
|
|
459
515
|
const productMatchRule = this.findProductMatchRule(config);
|
|
460
|
-
const eligibleProducts =
|
|
516
|
+
const eligibleProducts = productMatchRule?.value || [];
|
|
461
517
|
return {
|
|
462
518
|
requiredQuantity,
|
|
463
519
|
eligibleProducts
|
|
464
520
|
};
|
|
465
521
|
}
|
|
522
|
+
|
|
466
523
|
// ============================================
|
|
467
524
|
// 私有辅助方法
|
|
468
525
|
// ============================================
|
|
526
|
+
|
|
469
527
|
/**
|
|
470
528
|
* 按优先级排序促销组
|
|
471
529
|
* 优先级从 strategyConfig.actions[0].priority 获取,数值越小优先级越高
|
|
472
530
|
*/
|
|
473
531
|
sortPromotionGroupsByPriority(groups, promotions) {
|
|
474
|
-
|
|
475
|
-
const priorityMap =
|
|
532
|
+
// 创建策略ID到优先级的映射
|
|
533
|
+
const priorityMap = new Map();
|
|
476
534
|
for (const promo of promotions) {
|
|
477
|
-
const actions =
|
|
478
|
-
const priority =
|
|
535
|
+
const actions = promo.strategyConfig?.actions || [];
|
|
536
|
+
const priority = actions[0]?.priority ?? 999;
|
|
479
537
|
priorityMap.set(promo.strategyId, priority);
|
|
480
538
|
}
|
|
539
|
+
|
|
540
|
+
// 按优先级排序(数值越小优先级越高)
|
|
481
541
|
return [...groups].sort((a, b) => {
|
|
482
542
|
const priorityA = priorityMap.get(a.strategyId) ?? 999;
|
|
483
543
|
const priorityB = priorityMap.get(b.strategyId) ?? 999;
|
|
484
544
|
return priorityA - priorityB;
|
|
485
545
|
});
|
|
486
546
|
}
|
|
547
|
+
|
|
487
548
|
/**
|
|
488
549
|
* 处理 X件Y元 促销
|
|
489
550
|
*
|
|
@@ -495,19 +556,32 @@ var PromotionEvaluator = class {
|
|
|
495
556
|
* 注意:每个商品按 id 独立处理,不会合并不同 id 的商品
|
|
496
557
|
*/
|
|
497
558
|
processXItemsForYPrice(group, processedQuantityMap, matchedBundleIndexMap) {
|
|
498
|
-
const {
|
|
559
|
+
const {
|
|
560
|
+
strategyId,
|
|
561
|
+
strategyMetadata,
|
|
562
|
+
actionDetail,
|
|
563
|
+
products: groupProducts
|
|
564
|
+
} = group;
|
|
499
565
|
const detail = actionDetail;
|
|
500
|
-
const {
|
|
566
|
+
const {
|
|
567
|
+
x,
|
|
568
|
+
price: groupPrice,
|
|
569
|
+
cumulative
|
|
570
|
+
} = detail;
|
|
501
571
|
const result = [];
|
|
502
|
-
let originalAmount = new
|
|
503
|
-
let finalAmount = new
|
|
572
|
+
let originalAmount = new _decimal.default(0);
|
|
573
|
+
let finalAmount = new _decimal.default(0);
|
|
574
|
+
|
|
575
|
+
// 1. 展开所有商品为单件列表(排除已处理的数量)
|
|
576
|
+
// 每个单件记录来自哪个原商品(通过 product.id)
|
|
504
577
|
const unitProducts = [];
|
|
505
578
|
for (const product of groupProducts) {
|
|
506
579
|
const key = this.getProductKey(product);
|
|
507
580
|
const processedQty = processedQuantityMap.get(key) || 0;
|
|
508
581
|
const availableQty = product.quantity - processedQty;
|
|
509
|
-
if (availableQty <= 0)
|
|
510
|
-
|
|
582
|
+
if (availableQty <= 0) continue;
|
|
583
|
+
|
|
584
|
+
// 展开为单件,每个单件都记录来源商品
|
|
511
585
|
for (let i = 0; i < availableQty; i++) {
|
|
512
586
|
unitProducts.push({
|
|
513
587
|
product,
|
|
@@ -518,46 +592,67 @@ var PromotionEvaluator = class {
|
|
|
518
592
|
}
|
|
519
593
|
}
|
|
520
594
|
if (unitProducts.length === 0) {
|
|
521
|
-
return {
|
|
595
|
+
return {
|
|
596
|
+
products: [],
|
|
597
|
+
originalAmount: 0,
|
|
598
|
+
finalAmount: 0
|
|
599
|
+
};
|
|
522
600
|
}
|
|
601
|
+
|
|
602
|
+
// 2. 排序:优先选择来源数量是 x 倍数的商品(可完整凑组不拆分),然后按价格从高到低
|
|
523
603
|
unitProducts.sort((a, b) => {
|
|
604
|
+
// 优先级1:来源购物车项数量是 x 的倍数的排前面(这些商品可以完整凑组,避免拆分)
|
|
524
605
|
const aIsMultiple = a.sourceAvailableQty > 0 && a.sourceAvailableQty % x === 0 ? 1 : 0;
|
|
525
606
|
const bIsMultiple = b.sourceAvailableQty > 0 && b.sourceAvailableQty % x === 0 ? 1 : 0;
|
|
526
|
-
if (aIsMultiple !== bIsMultiple)
|
|
527
|
-
|
|
607
|
+
if (aIsMultiple !== bIsMultiple) return bIsMultiple - aIsMultiple;
|
|
608
|
+
// 优先级2:按价格从高到低(优先使用高价商品)
|
|
528
609
|
return b.price - a.price;
|
|
529
610
|
});
|
|
611
|
+
|
|
612
|
+
// 3. 计算可以凑成多少组(cumulative 缺省视为 true,与 adapter 一致)
|
|
530
613
|
const totalUnits = unitProducts.length;
|
|
531
|
-
const
|
|
614
|
+
const isCumulative = cumulative !== false;
|
|
615
|
+
const groupCount = isCumulative ? Math.floor(totalUnits / x) : totalUnits >= x ? 1 : 0;
|
|
532
616
|
const promotionUnits = groupCount * x;
|
|
617
|
+
|
|
618
|
+
// 4. 分离参与促销的和不参与的商品
|
|
533
619
|
const inPromotionUnits = unitProducts.slice(0, promotionUnits);
|
|
534
620
|
const notInPromotionUnits = unitProducts.slice(promotionUnits);
|
|
535
|
-
|
|
621
|
+
|
|
622
|
+
// 5. 按原商品 id 统计参与促销和不参与的数量
|
|
623
|
+
const promotionQtyByProductId = new Map();
|
|
536
624
|
for (const unit of inPromotionUnits) {
|
|
537
625
|
const id = unit.productId;
|
|
538
626
|
promotionQtyByProductId.set(id, (promotionQtyByProductId.get(id) || 0) + 1);
|
|
539
627
|
}
|
|
540
|
-
const remainingQtyByProductId =
|
|
628
|
+
const remainingQtyByProductId = new Map();
|
|
541
629
|
for (const unit of notInPromotionUnits) {
|
|
542
630
|
const id = unit.productId;
|
|
543
631
|
remainingQtyByProductId.set(id, (remainingQtyByProductId.get(id) || 0) + 1);
|
|
544
632
|
}
|
|
545
|
-
|
|
633
|
+
|
|
634
|
+
// 6. 为每个参与促销的单件计算均摊价格
|
|
635
|
+
// 按组内原价比例均摊
|
|
636
|
+
// 记录每个原商品的均摊价格累加(用于后续聚合)
|
|
637
|
+
const allocatedPricesByProductId = new Map();
|
|
546
638
|
for (let g = 0; g < groupCount; g++) {
|
|
547
639
|
const startIdx = g * x;
|
|
548
640
|
const endIdx = startIdx + x;
|
|
549
641
|
const groupUnits = inPromotionUnits.slice(startIdx, endIdx);
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
642
|
+
|
|
643
|
+
// 计算组内原价总和
|
|
644
|
+
const groupOriginalTotal = groupUnits.reduce((sum, u) => sum.plus(u.price), new _decimal.default(0));
|
|
645
|
+
|
|
646
|
+
// 按原价比例均摊
|
|
647
|
+
const groupPriceDecimal = new _decimal.default(groupPrice);
|
|
648
|
+
let allocatedSum = new _decimal.default(0);
|
|
556
649
|
for (let i = 0; i < groupUnits.length; i++) {
|
|
557
650
|
const unit = groupUnits[i];
|
|
558
651
|
const isLastUnit = i === groupUnits.length - 1;
|
|
559
|
-
const ratio = groupOriginalTotal.eq(0) ? new
|
|
652
|
+
const ratio = groupOriginalTotal.eq(0) ? new _decimal.default(0) : new _decimal.default(unit.price).div(groupOriginalTotal);
|
|
560
653
|
const allocatedDecimal = isLastUnit ? groupPriceDecimal.minus(allocatedSum) : groupPriceDecimal.mul(ratio);
|
|
654
|
+
|
|
655
|
+
// 记录这个单件的均摊价格
|
|
561
656
|
const productId = unit.productId;
|
|
562
657
|
const prices = allocatedPricesByProductId.get(productId) || [];
|
|
563
658
|
prices.push(allocatedDecimal);
|
|
@@ -565,23 +660,25 @@ var PromotionEvaluator = class {
|
|
|
565
660
|
allocatedSum = allocatedSum.plus(allocatedDecimal);
|
|
566
661
|
}
|
|
567
662
|
}
|
|
663
|
+
|
|
664
|
+
// 7. 为每个原商品生成结果
|
|
568
665
|
for (const product of groupProducts) {
|
|
569
666
|
const key = this.getProductKey(product);
|
|
570
667
|
const processedQty = processedQuantityMap.get(key) || 0;
|
|
571
668
|
const availableQty = product.quantity - processedQty;
|
|
572
|
-
if (availableQty <= 0)
|
|
573
|
-
continue;
|
|
669
|
+
if (availableQty <= 0) continue;
|
|
574
670
|
const promoQty = promotionQtyByProductId.get(product.id) || 0;
|
|
575
671
|
const remainingQty = remainingQtyByProductId.get(product.id) || 0;
|
|
576
672
|
const allocatedPrices = allocatedPricesByProductId.get(product.id) || [];
|
|
577
|
-
|
|
673
|
+
|
|
674
|
+
// 获取当前商品的 matchedBundleIndex
|
|
675
|
+
const matchedBundleIndex = matchedBundleIndexMap?.get(product.id);
|
|
578
676
|
if (promoQty > 0 && remainingQty === 0) {
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
);
|
|
583
|
-
const
|
|
584
|
-
const actualTotal = import_decimal.default.min(totalAllocated, productOriginalAmount);
|
|
677
|
+
// 全部参与促销:保留原 id,计算总 finalPrice
|
|
678
|
+
const totalAllocated = allocatedPrices.reduce((sum, p) => sum.plus(p), new _decimal.default(0));
|
|
679
|
+
// 取促销价和原价的最小值,避免促销反而加价
|
|
680
|
+
const productOriginalAmount = new _decimal.default(product.price).mul(promoQty);
|
|
681
|
+
const actualTotal = _decimal.default.min(totalAllocated, productOriginalAmount);
|
|
585
682
|
const finalPricePerUnit = this.formatPrice(actualTotal.div(promoQty));
|
|
586
683
|
result.push({
|
|
587
684
|
...product,
|
|
@@ -596,25 +693,26 @@ var PromotionEvaluator = class {
|
|
|
596
693
|
originalAmount = originalAmount.plus(productOriginalAmount);
|
|
597
694
|
finalAmount = finalAmount.plus(actualTotal);
|
|
598
695
|
} else if (promoQty === 0 && remainingQty > 0) {
|
|
696
|
+
// 全部不参与促销:保留原 id,finalPrice = 原价
|
|
599
697
|
result.push({
|
|
600
698
|
...product,
|
|
601
699
|
quantity: remainingQty,
|
|
602
700
|
finalPrice: this.formatPrice(product.price),
|
|
603
|
-
strategyId:
|
|
604
|
-
strategyMetadata:
|
|
701
|
+
strategyId: undefined,
|
|
702
|
+
strategyMetadata: undefined,
|
|
605
703
|
inPromotion: false,
|
|
606
704
|
isSplit: false
|
|
607
705
|
});
|
|
608
|
-
const amount = new
|
|
706
|
+
const amount = new _decimal.default(product.price).mul(remainingQty);
|
|
609
707
|
originalAmount = originalAmount.plus(amount);
|
|
610
708
|
finalAmount = finalAmount.plus(amount);
|
|
611
709
|
} else if (promoQty > 0 && remainingQty > 0) {
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
const promoOriginalAmount = new
|
|
617
|
-
const actualTotal =
|
|
710
|
+
// 部分参与促销,部分不参与:需要拆分
|
|
711
|
+
// 参与促销的部分:新 id
|
|
712
|
+
const totalAllocated = allocatedPrices.reduce((sum, p) => sum.plus(p), new _decimal.default(0));
|
|
713
|
+
// 取促销价和原价的最小值,避免促销反而加价
|
|
714
|
+
const promoOriginalAmount = new _decimal.default(product.price).mul(promoQty);
|
|
715
|
+
const actualTotal = _decimal.default.min(totalAllocated, promoOriginalAmount);
|
|
618
716
|
const finalPricePerUnit = this.formatPrice(actualTotal.div(promoQty));
|
|
619
717
|
result.push({
|
|
620
718
|
...product,
|
|
@@ -630,44 +728,50 @@ var PromotionEvaluator = class {
|
|
|
630
728
|
});
|
|
631
729
|
originalAmount = originalAmount.plus(promoOriginalAmount);
|
|
632
730
|
finalAmount = finalAmount.plus(actualTotal);
|
|
731
|
+
|
|
732
|
+
// 不参与促销的部分:保留原 id
|
|
633
733
|
result.push({
|
|
634
734
|
...product,
|
|
635
735
|
quantity: remainingQty,
|
|
636
736
|
finalPrice: this.formatPrice(product.price),
|
|
637
|
-
strategyId:
|
|
638
|
-
strategyMetadata:
|
|
737
|
+
strategyId: undefined,
|
|
738
|
+
strategyMetadata: undefined,
|
|
639
739
|
inPromotion: false,
|
|
640
740
|
isSplit: true
|
|
641
741
|
});
|
|
642
|
-
const remainingAmount = new
|
|
742
|
+
const remainingAmount = new _decimal.default(product.price).mul(remainingQty);
|
|
643
743
|
originalAmount = originalAmount.plus(remainingAmount);
|
|
644
744
|
finalAmount = finalAmount.plus(remainingAmount);
|
|
645
745
|
}
|
|
746
|
+
|
|
747
|
+
// 更新已处理数量
|
|
646
748
|
processedQuantityMap.set(key, processedQty + availableQty);
|
|
647
749
|
}
|
|
750
|
+
|
|
751
|
+
// 8. 尾差调整:确保促销商品的 finalPrice × quantity 之和精确等于 groupPrice × groupCount
|
|
648
752
|
if (groupCount > 0) {
|
|
649
|
-
const expectedPromoTotal = new
|
|
650
|
-
const promoItems = result.filter(
|
|
651
|
-
let actualPromoTotal = new
|
|
753
|
+
const expectedPromoTotal = new _decimal.default(groupPrice).mul(groupCount);
|
|
754
|
+
const promoItems = result.filter(p => p.inPromotion);
|
|
755
|
+
let actualPromoTotal = new _decimal.default(0);
|
|
652
756
|
for (const p of promoItems) {
|
|
653
|
-
actualPromoTotal = actualPromoTotal.plus(
|
|
654
|
-
new import_decimal.default(p.finalPrice).mul(p.quantity)
|
|
655
|
-
);
|
|
757
|
+
actualPromoTotal = actualPromoTotal.plus(new _decimal.default(p.finalPrice).mul(p.quantity));
|
|
656
758
|
}
|
|
657
759
|
const roundingDiff = actualPromoTotal.minus(expectedPromoTotal);
|
|
658
760
|
if (!roundingDiff.eq(0)) {
|
|
659
|
-
|
|
761
|
+
// 优先找 quantity=1 的促销商品调整(差额直接加减到单价上)
|
|
762
|
+
const adjustTarget = promoItems.find(p => p.quantity === 1);
|
|
660
763
|
if (adjustTarget) {
|
|
661
|
-
adjustTarget.finalPrice = this.formatPrice(
|
|
662
|
-
new import_decimal.default(adjustTarget.finalPrice).minus(roundingDiff)
|
|
663
|
-
);
|
|
764
|
+
adjustTarget.finalPrice = this.formatPrice(new _decimal.default(adjustTarget.finalPrice).minus(roundingDiff));
|
|
664
765
|
} else if (promoItems.length > 0) {
|
|
766
|
+
// 没有 quantity=1 的促销商品,从最后一个促销商品中拆出1件做尾差调整
|
|
665
767
|
const lastPromo = promoItems[promoItems.length - 1];
|
|
666
|
-
const adjustedUnitPrice = this.formatPrice(
|
|
667
|
-
|
|
668
|
-
|
|
768
|
+
const adjustedUnitPrice = this.formatPrice(new _decimal.default(lastPromo.finalPrice).minus(roundingDiff));
|
|
769
|
+
|
|
770
|
+
// 原商品减少1件
|
|
669
771
|
lastPromo.quantity -= 1;
|
|
670
772
|
lastPromo.isSplit = true;
|
|
773
|
+
|
|
774
|
+
// 拆出1件用调整后的价格
|
|
671
775
|
result.push({
|
|
672
776
|
...lastPromo,
|
|
673
777
|
id: this.generateRandomId(),
|
|
@@ -677,11 +781,11 @@ var PromotionEvaluator = class {
|
|
|
677
781
|
isSplit: true
|
|
678
782
|
});
|
|
679
783
|
}
|
|
680
|
-
|
|
784
|
+
|
|
785
|
+
// 重新计算 finalAmount
|
|
786
|
+
finalAmount = new _decimal.default(0);
|
|
681
787
|
for (const p of result) {
|
|
682
|
-
finalAmount = finalAmount.plus(
|
|
683
|
-
new import_decimal.default(p.finalPrice).mul(p.quantity)
|
|
684
|
-
);
|
|
788
|
+
finalAmount = finalAmount.plus(new _decimal.default(p.finalPrice).mul(p.quantity));
|
|
685
789
|
}
|
|
686
790
|
}
|
|
687
791
|
}
|
|
@@ -691,6 +795,7 @@ var PromotionEvaluator = class {
|
|
|
691
795
|
finalAmount: finalAmount.toNumber()
|
|
692
796
|
};
|
|
693
797
|
}
|
|
798
|
+
|
|
694
799
|
/**
|
|
695
800
|
* 处理 买X送Y 促销
|
|
696
801
|
*
|
|
@@ -706,34 +811,56 @@ var PromotionEvaluator = class {
|
|
|
706
811
|
products: groupProducts
|
|
707
812
|
} = group;
|
|
708
813
|
const detail = actionDetail;
|
|
709
|
-
const {
|
|
814
|
+
const {
|
|
815
|
+
buyQuantity,
|
|
816
|
+
freeQuantity,
|
|
817
|
+
cumulative,
|
|
818
|
+
giftProducts
|
|
819
|
+
} = detail;
|
|
710
820
|
const result = [];
|
|
711
|
-
let originalAmount = new
|
|
712
|
-
let finalAmount = new
|
|
821
|
+
let originalAmount = new _decimal.default(0);
|
|
822
|
+
let finalAmount = new _decimal.default(0);
|
|
823
|
+
|
|
824
|
+
// 1. 先计算可用商品总数量(第一次遍历)
|
|
825
|
+
// 对于 bundle 子商品匹配,促销数量 = 主商品数量 × bundle子商品数量
|
|
713
826
|
let totalPromoQty = 0;
|
|
714
|
-
const productInfoMap =
|
|
827
|
+
const productInfoMap = new Map();
|
|
715
828
|
for (const product of groupProducts) {
|
|
716
829
|
const key = this.getProductKey(product);
|
|
717
830
|
const processedQty = processedQuantityMap.get(key) || 0;
|
|
718
831
|
const availableQty = product.quantity - processedQty;
|
|
719
|
-
if (availableQty <= 0)
|
|
720
|
-
|
|
721
|
-
|
|
832
|
+
if (availableQty <= 0) continue;
|
|
833
|
+
|
|
834
|
+
// 获取 matchedBundleIndex
|
|
835
|
+
const matchedBundleIndex = matchedBundleIndexMap?.get(product.id);
|
|
836
|
+
|
|
837
|
+
// 计算用于促销的数量
|
|
722
838
|
let promoQty = availableQty;
|
|
723
|
-
if (matchedBundleIndex !==
|
|
839
|
+
if (matchedBundleIndex !== undefined && product.bundle) {
|
|
724
840
|
const bundleItem = product.bundle[matchedBundleIndex];
|
|
841
|
+
// 促销数量 = 主商品数量 × bundle子商品数量
|
|
725
842
|
promoQty = availableQty * (bundleItem.quantity || 1);
|
|
726
843
|
}
|
|
727
844
|
totalPromoQty += promoQty;
|
|
728
|
-
productInfoMap.set(key, {
|
|
845
|
+
productInfoMap.set(key, {
|
|
846
|
+
availableQty,
|
|
847
|
+
promoQty,
|
|
848
|
+
matchedBundleIndex
|
|
849
|
+
});
|
|
729
850
|
}
|
|
851
|
+
|
|
852
|
+
// 2. 判断是否满足促销条件
|
|
730
853
|
const isFulfilled = totalPromoQty >= buyQuantity;
|
|
854
|
+
|
|
855
|
+
// 3. 生成商品结果(第二次遍历)
|
|
731
856
|
for (const product of groupProducts) {
|
|
732
857
|
const key = this.getProductKey(product);
|
|
733
858
|
const info = productInfoMap.get(key);
|
|
734
|
-
if (!info || info.availableQty <= 0)
|
|
735
|
-
continue;
|
|
859
|
+
if (!info || info.availableQty <= 0) continue;
|
|
736
860
|
const processedQty = processedQuantityMap.get(key) || 0;
|
|
861
|
+
|
|
862
|
+
// 商品本身价格不变,只是触发赠品
|
|
863
|
+
// inPromotion 只有在满足条件时才为 true
|
|
737
864
|
result.push({
|
|
738
865
|
...product,
|
|
739
866
|
quantity: info.availableQty,
|
|
@@ -745,15 +872,21 @@ var PromotionEvaluator = class {
|
|
|
745
872
|
isSplit: info.availableQty < product.quantity,
|
|
746
873
|
matchedBundleIndex: info.matchedBundleIndex
|
|
747
874
|
});
|
|
748
|
-
const amount = new
|
|
875
|
+
const amount = new _decimal.default(product.price).mul(info.availableQty);
|
|
749
876
|
originalAmount = originalAmount.plus(amount);
|
|
750
877
|
finalAmount = finalAmount.plus(amount);
|
|
878
|
+
|
|
879
|
+
// 更新已处理数量(使用主商品数量)
|
|
751
880
|
processedQuantityMap.set(key, processedQty + info.availableQty);
|
|
752
881
|
}
|
|
882
|
+
|
|
883
|
+
// 4. 计算赠品数量(使用促销数量)
|
|
753
884
|
let giftCount = 0;
|
|
754
885
|
if (isFulfilled) {
|
|
755
886
|
giftCount = cumulative ? Math.floor(totalPromoQty / buyQuantity) * freeQuantity : freeQuantity;
|
|
756
887
|
}
|
|
888
|
+
|
|
889
|
+
// 5. 构建赠品信息
|
|
757
890
|
const giftInfo = giftCount > 0 ? {
|
|
758
891
|
strategyId,
|
|
759
892
|
strategyName,
|
|
@@ -767,6 +900,7 @@ var PromotionEvaluator = class {
|
|
|
767
900
|
giftInfo
|
|
768
901
|
};
|
|
769
902
|
}
|
|
903
|
+
|
|
770
904
|
/**
|
|
771
905
|
* 获取未参与任何促销的商品
|
|
772
906
|
*/
|
|
@@ -781,7 +915,7 @@ var PromotionEvaluator = class {
|
|
|
781
915
|
...product,
|
|
782
916
|
quantity: remainingQty,
|
|
783
917
|
finalPrice: this.formatPrice(product.price),
|
|
784
|
-
strategyId:
|
|
918
|
+
strategyId: undefined,
|
|
785
919
|
inPromotion: false,
|
|
786
920
|
isSplit: remainingQty < product.quantity
|
|
787
921
|
});
|
|
@@ -789,12 +923,14 @@ var PromotionEvaluator = class {
|
|
|
789
923
|
}
|
|
790
924
|
return result;
|
|
791
925
|
}
|
|
926
|
+
|
|
792
927
|
/**
|
|
793
928
|
* 价格统一保留两位小数
|
|
794
929
|
*/
|
|
795
930
|
formatPrice(value) {
|
|
796
|
-
return new
|
|
931
|
+
return new _decimal.default(value).toDecimalPlaces(2, _decimal.default.ROUND_HALF_UP).toNumber();
|
|
797
932
|
}
|
|
933
|
+
|
|
798
934
|
/**
|
|
799
935
|
* 获取商品唯一标识 key
|
|
800
936
|
* 使用商品的 id 作为唯一标识,不同 id 的商品不会被合并
|
|
@@ -802,92 +938,107 @@ var PromotionEvaluator = class {
|
|
|
802
938
|
getProductKey(product) {
|
|
803
939
|
return String(product.id);
|
|
804
940
|
}
|
|
941
|
+
|
|
805
942
|
/**
|
|
806
943
|
* 生成随机ID
|
|
807
944
|
*/
|
|
808
945
|
generateRandomId() {
|
|
809
|
-
return Math.floor(Math.random() *
|
|
946
|
+
return Math.floor(Math.random() * 1000000000) + Date.now();
|
|
810
947
|
}
|
|
948
|
+
|
|
811
949
|
/**
|
|
812
950
|
* 商品匹配结果信息
|
|
813
951
|
*/
|
|
814
952
|
getProductMatchInfo(product, config) {
|
|
815
953
|
const productMatchRule = this.findProductMatchRule(config);
|
|
816
954
|
if (!productMatchRule) {
|
|
817
|
-
|
|
955
|
+
// 没有商品范围条件,默认适用所有商品(匹配主商品)
|
|
956
|
+
return {
|
|
957
|
+
isMatch: true
|
|
958
|
+
};
|
|
818
959
|
}
|
|
819
960
|
const configProducts = productMatchRule.value;
|
|
961
|
+
|
|
962
|
+
// 1. 先检查主商品是否匹配
|
|
820
963
|
if (this.isProductIdMatch(product.product_id, product.product_variant_id, configProducts)) {
|
|
821
|
-
return {
|
|
964
|
+
return {
|
|
965
|
+
isMatch: true
|
|
966
|
+
};
|
|
822
967
|
}
|
|
968
|
+
|
|
969
|
+
// 2. 主商品不匹配,检查 bundle 子商品
|
|
823
970
|
if (product.bundle && product.bundle.length > 0) {
|
|
824
971
|
for (let i = 0; i < product.bundle.length; i++) {
|
|
825
972
|
const bundleItem = product.bundle[i];
|
|
826
|
-
if (this.isProductIdMatch(
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
return { isMatch: true, matchedBundleIndex: i };
|
|
973
|
+
if (this.isProductIdMatch(bundleItem._bundle_product_id, bundleItem.product_variant_id, configProducts)) {
|
|
974
|
+
return {
|
|
975
|
+
isMatch: true,
|
|
976
|
+
matchedBundleIndex: i
|
|
977
|
+
};
|
|
832
978
|
}
|
|
833
979
|
}
|
|
834
980
|
}
|
|
835
|
-
return {
|
|
981
|
+
return {
|
|
982
|
+
isMatch: false
|
|
983
|
+
};
|
|
836
984
|
}
|
|
985
|
+
|
|
837
986
|
/**
|
|
838
987
|
* 检查商品是否在策略的适用范围内
|
|
839
988
|
*/
|
|
840
989
|
isProductInStrategy(product, config) {
|
|
841
990
|
return this.getProductMatchInfo(product, config).isMatch;
|
|
842
991
|
}
|
|
992
|
+
|
|
843
993
|
/**
|
|
844
994
|
* 查找商品匹配规则
|
|
845
995
|
*/
|
|
846
996
|
findProductMatchRule(config) {
|
|
847
|
-
|
|
848
|
-
if (!((_a = config == null ? void 0 : config.conditions) == null ? void 0 : _a.rules)) {
|
|
997
|
+
if (!config?.conditions?.rules) {
|
|
849
998
|
return null;
|
|
850
999
|
}
|
|
851
|
-
return config.conditions.rules.find(
|
|
852
|
-
(rule) => rule.field === "productIdAndVariantId" && (rule.operator === "product_match" || rule.operator === "object_in")
|
|
853
|
-
);
|
|
1000
|
+
return config.conditions.rules.find(rule => rule.field === 'productIdAndVariantId' && (rule.operator === 'product_match' || rule.operator === 'object_in'));
|
|
854
1001
|
}
|
|
1002
|
+
|
|
855
1003
|
/**
|
|
856
1004
|
* 检查商品ID是否匹配配置列表
|
|
857
1005
|
*/
|
|
858
1006
|
isProductIdMatch(productId, productVariantId, configProducts) {
|
|
859
|
-
return configProducts.some(
|
|
1007
|
+
return configProducts.some(config => {
|
|
1008
|
+
// 首先检查 product_id
|
|
860
1009
|
if (config.product_id !== productId) {
|
|
861
1010
|
return false;
|
|
862
1011
|
}
|
|
1012
|
+
|
|
1013
|
+
// 如果配置的 product_variant_id = 0,只需要 product_id 匹配
|
|
863
1014
|
if (config.product_variant_id === 0) {
|
|
864
1015
|
return true;
|
|
865
1016
|
}
|
|
1017
|
+
|
|
1018
|
+
// 否则需要 product_variant_id 精确匹配
|
|
866
1019
|
return config.product_variant_id === productVariantId;
|
|
867
1020
|
});
|
|
868
1021
|
}
|
|
1022
|
+
|
|
869
1023
|
/**
|
|
870
1024
|
* 检查商品是否匹配配置(兼容旧方法)
|
|
871
1025
|
*/
|
|
872
1026
|
isProductMatch(product, configProducts) {
|
|
873
1027
|
return this.isProductIdMatch(product.product_id, product.product_variant_id, configProducts);
|
|
874
1028
|
}
|
|
1029
|
+
|
|
875
1030
|
/**
|
|
876
1031
|
* 获取展示配置
|
|
877
1032
|
*/
|
|
878
1033
|
getDisplayConfig(config) {
|
|
879
|
-
var _a;
|
|
880
1034
|
const custom = config.metadata.custom;
|
|
881
|
-
if (
|
|
1035
|
+
if (custom?.display?.product_card) {
|
|
882
1036
|
return {
|
|
883
1037
|
text: custom.display.product_card.text,
|
|
884
1038
|
type: custom.display.product_card.type
|
|
885
1039
|
};
|
|
886
1040
|
}
|
|
887
|
-
return
|
|
1041
|
+
return undefined;
|
|
888
1042
|
}
|
|
889
|
-
}
|
|
890
|
-
|
|
891
|
-
0 && (module.exports = {
|
|
892
|
-
PromotionEvaluator
|
|
893
|
-
});
|
|
1043
|
+
}
|
|
1044
|
+
exports.PromotionEvaluator = PromotionEvaluator;
|