@pisell/pisellos 2.3.74 → 2.3.76
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 -10
- package/dist/model/strategy/adapter/promotion/index.js +9 -0
- package/dist/model/strategy/adapter/walletPass/example.js +3 -26
- package/dist/model/strategy/strategy-example.js +5 -19
- package/dist/modules/Cart/index.js +0 -3
- package/dist/modules/Cart/utils/cartProduct.js +0 -1
- package/dist/modules/Date/index.js +1 -5
- package/dist/modules/Discount/index.js +2 -4
- package/dist/modules/OpenData/index.js +0 -2
- package/dist/modules/Order/index.d.ts +1 -1
- package/dist/modules/Order/index.js +75 -91
- package/dist/modules/Order/types.d.ts +3 -1
- package/dist/modules/Payment/index.js +97 -162
- package/dist/modules/Rules/index.js +1 -4
- package/dist/modules/Schedule/index.js +0 -1
- package/dist/modules/Schedule/utils.js +0 -1
- package/dist/modules/Step/index.js +0 -1
- package/dist/plugins/request.js +1 -4
- package/dist/plugins/window.js +2 -6
- package/dist/server/index.js +97 -129
- package/dist/server/modules/menu/index.js +32 -41
- package/dist/server/modules/order/index.js +2 -4
- package/dist/server/modules/products/index.js +24 -42
- package/dist/server/modules/quotation/index.js +29 -38
- package/dist/server/modules/resource/index.js +3 -4
- package/dist/server/modules/schedule/index.js +27 -35
- package/dist/server/utils/product.js +0 -1
- package/dist/solution/BaseSales/index.js +100 -72
- package/dist/solution/BaseSales/utils/cartPromotion.d.ts +5 -0
- package/dist/solution/BaseSales/utils/cartPromotion.js +15 -6
- 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.js +0 -2
- package/dist/solution/BookingTicket/utils/scan/cloudSearch.js +6 -7
- package/dist/solution/BookingTicket/utils/scan/handleScan.js +25 -31
- package/dist/solution/BookingTicket/utils/scan/index.js +6 -10
- package/dist/solution/BuyTickets/index.js +9 -12
- package/dist/solution/Checkout/index.js +177 -252
- package/dist/solution/Checkout/utils/index.js +4 -16
- package/dist/solution/RegisterAndLogin/index.js +30 -76
- package/dist/solution/ScanOrder/index.js +50 -60
- package/dist/solution/ShopDiscount/index.js +2 -7
- package/dist/solution/VenueBooking/index.js +45 -55
- 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 +134 -134
- package/lib/effects/index.js +46 -57
- package/lib/index.js +82 -49
- 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 +91 -69
- package/lib/model/strategy/adapter/promotion/evaluator.js +444 -310
- package/lib/model/strategy/adapter/promotion/examples.js +222 -234
- package/lib/model/strategy/adapter/promotion/index.js +1 -0
- package/lib/model/strategy/adapter/promotion/type.js +243 -36
- package/lib/model/strategy/adapter/type.js +4 -16
- package/lib/model/strategy/adapter/walletPass/evaluator.js +180 -150
- 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 +588 -378
- 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.js +23 -42
- package/lib/modules/BookingContext/index.js +158 -136
- package/lib/modules/BookingContext/types.js +46 -32
- package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +138 -146
- package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +78 -83
- package/lib/modules/BookingContext/utils/cacheItemToBookingInput.js +170 -150
- package/lib/modules/BookingContext/utils/flexible.js +38 -55
- package/lib/modules/BookingContext/utils/formatResourceList.js +19 -34
- package/lib/modules/BookingContext/utils/index.js +124 -41
- package/lib/modules/BookingContext/utils/noResource.js +58 -70
- package/lib/modules/BookingContext/utils/orderLineDisplay.js +14 -41
- package/lib/modules/BookingContext/utils/productExtend.js +202 -155
- package/lib/modules/BookingContext/utils/resourceErrors.js +53 -53
- package/lib/modules/BookingContext/utils/resourceSelection.js +19 -41
- package/lib/modules/BookingContext/utils/resources.js +209 -167
- package/lib/modules/BookingContext/utils/serviceTimes.js +115 -116
- package/lib/modules/BookingContext/utils/timeSlices.js +76 -86
- 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 +321 -251
- package/lib/modules/Cart/utils/cartRelationForms.js +29 -35
- package/lib/modules/Cart/utils/cartResource.js +70 -78
- package/lib/modules/Cart/utils/changePrice.js +22 -50
- package/lib/modules/Cart/utils/index.js +106 -48
- package/lib/modules/Customer/constants.js +13 -34
- package/lib/modules/Customer/index.js +235 -172
- 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.js +122 -127
- 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.js +70 -76
- package/lib/modules/OpenData/types.js +4 -16
- package/lib/modules/OpenData/utils.js +44 -78
- package/lib/modules/Order/index.d.ts +1 -1
- package/lib/modules/Order/index.js +1733 -2121
- package/lib/modules/Order/payment-utils.js +77 -120
- package/lib/modules/Order/types.d.ts +3 -1
- package/lib/modules/Order/types.js +88 -35
- package/lib/modules/Order/utils/bundleDiscountHydration.js +41 -74
- package/lib/modules/Order/utils/discountProductLineIdentity.js +142 -100
- package/lib/modules/Order/utils/manualProductDiscount.js +124 -123
- package/lib/modules/Order/utils/orderCollectionIdentity.js +184 -244
- package/lib/modules/Order/utils.js +814 -647
- 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.js +532 -399
- package/lib/modules/Payment/mx51.js +1 -0
- package/lib/modules/Payment/types.js +230 -108
- package/lib/modules/Payment/utils.js +52 -51
- package/lib/modules/Payment/walletpass.js +485 -660
- package/lib/modules/Product/index.js +51 -46
- package/lib/modules/Product/types.js +4 -16
- package/lib/modules/Product/utils.js +32 -33
- package/lib/modules/ProductList/index.js +113 -123
- package/lib/modules/ProductList/types.js +9 -31
- package/lib/modules/Quotation/index.js +81 -118
- 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.js +25 -23
- package/lib/modules/ResourcePlanner/localClock.js +54 -119
- package/lib/modules/ResourcePlanner/planner.js +589 -770
- package/lib/modules/ResourcePlanner/types.js +10 -29
- package/lib/modules/Rules/index.js +1218 -959
- package/lib/modules/Rules/types.js +17 -40
- package/lib/modules/SalesSummary/index.js +85 -90
- package/lib/modules/SalesSummary/types.js +4 -16
- package/lib/modules/SalesSummary/utils.js +355 -430
- 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 +334 -163
- package/lib/modules/Schedule/index.js +100 -114
- package/lib/modules/Schedule/type.js +4 -16
- 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 -71
- package/lib/modules/Summary/types.js +4 -16
- package/lib/modules/Summary/utils.js +773 -418
- package/lib/modules/SurchargeList/index.js +46 -60
- package/lib/modules/SurchargeList/types.js +4 -16
- package/lib/modules/index.js +245 -63
- package/lib/plugins/app.js +4 -16
- package/lib/plugins/index.js +36 -25
- 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.js +3050 -2665
- package/lib/server/modules/floor-plan/index.js +118 -134
- package/lib/server/modules/floor-plan/types.js +15 -30
- package/lib/server/modules/index.js +106 -68
- package/lib/server/modules/menu/index.js +142 -122
- package/lib/server/modules/menu/types.js +18 -31
- package/lib/server/modules/order/index.js +784 -1002
- package/lib/server/modules/order/types.js +122 -33
- package/lib/server/modules/order/utils/filterBookings.js +219 -194
- package/lib/server/modules/order/utils/filterOrders.js +118 -92
- package/lib/server/modules/payment/index.js +59 -83
- package/lib/server/modules/payment/types.js +4 -16
- package/lib/server/modules/products/index.js +583 -471
- package/lib/server/modules/products/types.js +44 -34
- package/lib/server/modules/quotation/index.js +137 -172
- package/lib/server/modules/quotation/types.js +21 -31
- package/lib/server/modules/resource/index.js +220 -186
- package/lib/server/modules/resource/types.js +42 -33
- package/lib/server/modules/schedule/index.js +135 -123
- package/lib/server/modules/schedule/types.js +14 -21
- package/lib/server/modules/schedule/utils.js +334 -163
- package/lib/server/types.js +4 -16
- package/lib/server/utils/index.js +25 -23
- package/lib/server/utils/product.js +196 -139
- package/lib/server/utils/schedule.js +34 -41
- package/lib/server/utils/small-ticket.js +479 -456
- package/lib/server/utils/time.js +40 -49
- package/lib/solution/BaseSales/index.js +1220 -1412
- package/lib/solution/BaseSales/types.js +42 -38
- package/lib/solution/BaseSales/utils/cartPromotion.d.ts +5 -0
- package/lib/solution/BaseSales/utils/cartPromotion.js +652 -498
- package/lib/solution/BaseSales/utils/parseSalesResponse.js +85 -105
- package/lib/solution/BaseSales/utils/quotationPrice.js +56 -114
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +108 -145
- package/lib/solution/BaseSales/utils.js +158 -143
- package/lib/solution/BookingByStep/index.js +1527 -1340
- 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.js +607 -522
- package/lib/solution/BookingTicket/types.js +99 -77
- package/lib/solution/BookingTicket/utils/addProductDecision.js +226 -189
- package/lib/solution/BookingTicket/utils/addTimeAvailability.js +58 -89
- package/lib/solution/BookingTicket/utils/bookingStatus.js +107 -78
- package/lib/solution/BookingTicket/utils/cartView.js +114 -99
- package/lib/solution/BookingTicket/utils/exampleData.js +185 -0
- package/lib/solution/BookingTicket/utils/orderCustomer.js +18 -41
- package/lib/solution/BookingTicket/utils/resolveBestAddTimePlan.js +219 -86
- package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.js +168 -116
- package/lib/solution/BookingTicket/utils/scan/cloudSearch.js +79 -91
- package/lib/solution/BookingTicket/utils/scan/formatGlobalScan.js +54 -41
- package/lib/solution/BookingTicket/utils/scan/handleScan.js +84 -81
- package/lib/solution/BookingTicket/utils/scan/index.js +98 -104
- package/lib/solution/BookingTicket/utils/scan/scanCache.js +90 -43
- package/lib/solution/BookingTicket/utils/scan/scanProductValues.js +52 -64
- package/lib/solution/BookingTicket/utils/sessionCatalogStale.js +56 -58
- package/lib/solution/BookingTicket/utils/weighingProductSku.js +34 -48
- package/lib/solution/BuyTickets/index.js +67 -70
- package/lib/solution/BuyTickets/types.js +22 -38
- package/lib/solution/Checkout/index.js +1451 -1158
- package/lib/solution/Checkout/types.js +91 -61
- package/lib/solution/Checkout/utils/index.js +228 -156
- package/lib/solution/PlaceOrder/index.js +55 -0
- package/lib/solution/RegisterAndLogin/config.js +493 -460
- 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.js +328 -324
- package/lib/solution/Sales/types.js +27 -33
- package/lib/solution/ScanOrder/index.js +832 -864
- package/lib/solution/ScanOrder/types.js +33 -34
- package/lib/solution/ScanOrder/utils.js +409 -374
- package/lib/solution/ShopDiscount/index.js +226 -232
- package/lib/solution/ShopDiscount/types.js +15 -37
- package/lib/solution/ShopDiscount/utils.js +300 -172
- package/lib/solution/UnifiedBookingSales/index.js +1035 -1201
- package/lib/solution/UnifiedBookingSales/remoteOccupancyCache.js +99 -159
- package/lib/solution/UnifiedBookingSales/types.js +10 -32
- package/lib/solution/VenueBooking/index.js +811 -879
- package/lib/solution/VenueBooking/types.js +19 -39
- package/lib/solution/VenueBooking/utils/dateSummary.js +27 -56
- package/lib/solution/VenueBooking/utils/resource.js +31 -54
- package/lib/solution/VenueBooking/utils/slotMerge.js +94 -107
- package/lib/solution/VenueBooking/utils/timeSlot.js +132 -132
- package/lib/solution/VenueBooking/utils.js +130 -67
- package/lib/solution/index.js +124 -41
- package/lib/store/createStore.js +32 -29
- package/lib/types/index.js +4 -16
- package/lib/utils/payment-number.js +26 -46
- package/lib/utils/task.js +36 -36
- package/lib/utils/watch.js +81 -47
- package/package.json +2 -1
|
@@ -1,125 +1,179 @@
|
|
|
1
|
-
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __export = (target, all) => {
|
|
8
|
-
for (var name in all)
|
|
9
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
-
};
|
|
11
|
-
var __copyProps = (to, from, except, desc) => {
|
|
12
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
-
for (let key of __getOwnPropNames(from))
|
|
14
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
-
}
|
|
17
|
-
return to;
|
|
18
|
-
};
|
|
19
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
-
mod
|
|
26
|
-
));
|
|
27
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
1
|
+
"use strict";
|
|
28
2
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "buildManualProductDiscountItem", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _manualProductDiscount.buildManualProductDiscountItem;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
exports.buildSubmitPayload = buildSubmitPayload;
|
|
13
|
+
exports.calculateOrderProductsDeposit = calculateOrderProductsDeposit;
|
|
14
|
+
exports.clearTempOrderHolderAssignments = clearTempOrderHolderAssignments;
|
|
15
|
+
exports.composeLinePrice = composeLinePrice;
|
|
16
|
+
exports.createDefaultOrderRulesHooks = createDefaultOrderRulesHooks;
|
|
17
|
+
exports.createDefaultTempOrder = createDefaultTempOrder;
|
|
18
|
+
Object.defineProperty(exports, "createEmptySummary", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () {
|
|
21
|
+
return _utils2.createEmptySummary;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(exports, "createUuidV4", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () {
|
|
27
|
+
return _orderCollectionIdentity.createUuidV4;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
exports.ensureCartItemOriginHolder = ensureCartItemOriginHolder;
|
|
31
|
+
Object.defineProperty(exports, "ensureManualProductDiscountList", {
|
|
32
|
+
enumerable: true,
|
|
33
|
+
get: function () {
|
|
34
|
+
return _manualProductDiscount.ensureManualProductDiscountList;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
exports.ensureProductSku = ensureProductSku;
|
|
38
|
+
Object.defineProperty(exports, "findManualProductDiscountItem", {
|
|
39
|
+
enumerable: true,
|
|
40
|
+
get: function () {
|
|
41
|
+
return _manualProductDiscount.findManualProductDiscountItem;
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
exports.formatDateTime = formatDateTime;
|
|
45
|
+
exports.formatV1Product = formatV1Product;
|
|
46
|
+
exports.getAllDiscountList = exports.generateDuration = void 0;
|
|
47
|
+
exports.getBundleSellingMagnitude = getBundleSellingMagnitude;
|
|
48
|
+
exports.getBundleSignedUnit = getBundleSignedUnit;
|
|
49
|
+
exports.getOrderProductLineUid = getOrderProductLineUid;
|
|
50
|
+
exports.getProductSkuOptions = getProductSkuOptions;
|
|
51
|
+
exports.getRuntimeProductOrigin = getRuntimeProductOrigin;
|
|
52
|
+
exports.hasAssignedHolderId = hasAssignedHolderId;
|
|
53
|
+
exports.indexOrderProductsByUid = indexOrderProductsByUid;
|
|
54
|
+
exports.isEmptyOrderProductDisplayValue = isEmptyOrderProductDisplayValue;
|
|
55
|
+
exports.isHolderConfigRequired = isHolderConfigRequired;
|
|
56
|
+
exports.isMarkdownBundle = isMarkdownBundle;
|
|
57
|
+
exports.isTempOrder = isTempOrder;
|
|
58
|
+
exports.mapPaymentItemToOrderPayment = mapPaymentItemToOrderPayment;
|
|
59
|
+
exports.mapPaymentItemsToOrderPayments = mapPaymentItemsToOrderPayments;
|
|
60
|
+
Object.defineProperty(exports, "mergeManualProductDiscountIntoList", {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
get: function () {
|
|
63
|
+
return _manualProductDiscount.mergeManualProductDiscountIntoList;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
exports.mergeOrderProductDisplayFields = mergeOrderProductDisplayFields;
|
|
67
|
+
exports.mergeRelationForms = void 0;
|
|
68
|
+
exports.normalizeBookingIsAll = normalizeBookingIsAll;
|
|
69
|
+
exports.normalizeBookingSubType = normalizeBookingSubType;
|
|
70
|
+
exports.normalizeOrderProductDiscountList = normalizeOrderProductDiscountList;
|
|
71
|
+
exports.normalizeProductSkuOptions = normalizeProductSkuOptions;
|
|
72
|
+
exports.normalizeSubmitBooking = normalizeSubmitBooking;
|
|
73
|
+
exports.normalizeSubmitCollectPaxValue = normalizeSubmitCollectPaxValue;
|
|
74
|
+
exports.productRequiresFormSubject = productRequiresFormSubject;
|
|
75
|
+
exports.resolveEffectivePerUnitDiscount = resolveEffectivePerUnitDiscount;
|
|
76
|
+
exports.resolveIsFormSubject = resolveIsFormSubject;
|
|
77
|
+
Object.defineProperty(exports, "resolveManualDiscountMessage", {
|
|
78
|
+
enumerable: true,
|
|
79
|
+
get: function () {
|
|
80
|
+
return _manualProductDiscount.resolveManualDiscountMessage;
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
Object.defineProperty(exports, "resolveManualDiscountOriginTotal", {
|
|
84
|
+
enumerable: true,
|
|
85
|
+
get: function () {
|
|
86
|
+
return _manualProductDiscount.resolveManualDiscountOriginTotal;
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
Object.defineProperty(exports, "resolveManualDiscountReasonFromSources", {
|
|
90
|
+
enumerable: true,
|
|
91
|
+
get: function () {
|
|
92
|
+
return _manualProductDiscount.resolveManualDiscountReasonFromSources;
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
exports.resolveManualOverrideLineOriginalPrice = resolveManualOverrideLineOriginalPrice;
|
|
96
|
+
exports.resolveRulesManualDiscountFlag = resolveRulesManualDiscountFlag;
|
|
97
|
+
Object.defineProperty(exports, "resolveSafeProductNum", {
|
|
98
|
+
enumerable: true,
|
|
99
|
+
get: function () {
|
|
100
|
+
return _manualProductDiscount.resolveSafeProductNum;
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
exports.resolveSubmitCollectPax = resolveSubmitCollectPax;
|
|
104
|
+
Object.defineProperty(exports, "shouldBuildManualProductDiscount", {
|
|
105
|
+
enumerable: true,
|
|
106
|
+
get: function () {
|
|
107
|
+
return _manualProductDiscount.shouldBuildManualProductDiscount;
|
|
108
|
+
}
|
|
85
109
|
});
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
110
|
+
Object.defineProperty(exports, "stripManualProductDiscountItems", {
|
|
111
|
+
enumerable: true,
|
|
112
|
+
get: function () {
|
|
113
|
+
return _manualProductDiscount.stripManualProductDiscountItems;
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
exports.sumOptionUnitPrice = sumOptionUnitPrice;
|
|
117
|
+
Object.defineProperty(exports, "syncManualProductDiscountProductNum", {
|
|
118
|
+
enumerable: true,
|
|
119
|
+
get: function () {
|
|
120
|
+
return _manualProductDiscount.syncManualProductDiscountProductNum;
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
var _dayjs = _interopRequireDefault(require("dayjs"));
|
|
124
|
+
var _decimal = _interopRequireDefault(require("decimal.js"));
|
|
125
|
+
var _utils = require("../Holder/utils");
|
|
126
|
+
var _utils2 = require("../../solution/ScanOrder/utils");
|
|
127
|
+
var _orderCollectionIdentity = require("./utils/orderCollectionIdentity");
|
|
128
|
+
var _manualProductDiscount = require("./utils/manualProductDiscount");
|
|
129
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
130
|
+
/**
|
|
131
|
+
* 把"含 option 的主商品单价"与 bundle 合成"单行 composite 单价"。
|
|
132
|
+
*
|
|
133
|
+
* 新语义 v2 约定:
|
|
134
|
+
* - `mainPrice` 必须是**已经包含 option 的主商品单价**(即 `metadata.main_product_selling_price`
|
|
135
|
+
* 或 `metadata.main_product_original_price`),option 价格不由本函数叠加。
|
|
136
|
+
* - 套餐价:Σ((bundle.bundle_selling_price ?? bundle.price) × (bundle.num ?? bundle.quantity ?? 1))
|
|
137
|
+
* 当 `useOriginalBundle=true` 时,改用 `bundle.original_price ?? bundle.product_price ?? bundle.price`。
|
|
138
|
+
* - 返回值:保留 2 位小数的字符串,方便直接写回 `selling_price` / `original_price` 字段。
|
|
139
|
+
*
|
|
140
|
+
* 被 `normalizeOrderProduct`、Rules setProduct 钩子、各 Solution 的 setDiscountSelected 共用,
|
|
141
|
+
* 保证合成逻辑单点来源。
|
|
142
|
+
*/
|
|
94
143
|
function composeLinePrice(params) {
|
|
95
|
-
const {
|
|
96
|
-
|
|
144
|
+
const {
|
|
145
|
+
mainPrice,
|
|
146
|
+
bundle,
|
|
147
|
+
useOriginalBundle
|
|
148
|
+
} = params;
|
|
149
|
+
let total = new _decimal.default(Number(mainPrice) || 0);
|
|
97
150
|
if (Array.isArray(bundle)) {
|
|
98
151
|
for (const item of bundle) {
|
|
99
|
-
|
|
100
|
-
const
|
|
101
|
-
|
|
152
|
+
// markdown(减价)按带符号净额取减;markup/原价维持相加。
|
|
153
|
+
const signedUnit = getBundleSignedUnit(item, {
|
|
154
|
+
useOriginal: useOriginalBundle
|
|
155
|
+
});
|
|
156
|
+
const rawNum = item?.num ?? item?.quantity ?? 1;
|
|
157
|
+
const num = new _decimal.default(Number(rawNum) || 0);
|
|
102
158
|
total = total.plus(signedUnit.times(num));
|
|
103
159
|
}
|
|
104
160
|
}
|
|
105
161
|
return total.toDecimalPlaces(2).toFixed(2);
|
|
106
162
|
}
|
|
107
163
|
function normalizeProductSkuOptions(options) {
|
|
108
|
-
if (!Array.isArray(options))
|
|
109
|
-
|
|
110
|
-
return options.map((option) => {
|
|
164
|
+
if (!Array.isArray(options)) return [];
|
|
165
|
+
return options.map(option => {
|
|
111
166
|
const normalized = {
|
|
112
|
-
...option && typeof option ===
|
|
167
|
+
...(option && typeof option === 'object' ? option : {})
|
|
113
168
|
};
|
|
114
169
|
const addPrice = normalized.add_price ?? normalized.price;
|
|
115
|
-
if (addPrice !==
|
|
116
|
-
normalized.add_price = addPrice;
|
|
170
|
+
if (addPrice !== undefined) normalized.add_price = addPrice;
|
|
117
171
|
delete normalized.price;
|
|
118
172
|
return normalized;
|
|
119
173
|
});
|
|
120
174
|
}
|
|
121
175
|
function ensureProductSku(product) {
|
|
122
|
-
const rawSku =
|
|
176
|
+
const rawSku = product?.product_sku && typeof product.product_sku === 'object' ? product.product_sku : {};
|
|
123
177
|
return {
|
|
124
178
|
...rawSku,
|
|
125
179
|
option: normalizeProductSkuOptions(rawSku.option)
|
|
@@ -128,21 +182,25 @@ function ensureProductSku(product) {
|
|
|
128
182
|
function getProductSkuOptions(product) {
|
|
129
183
|
return ensureProductSku(product).option;
|
|
130
184
|
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* 计算 option 单价合计:Σ(option.add_price × option.num)。
|
|
188
|
+
* 兼容入参仍带旧 `price` 的调用方,但运行时归一化后只维护 `add_price`。
|
|
189
|
+
* 在新语义 v2 下,main_product_original_price = source_product_price + 本函数结果。
|
|
190
|
+
*/
|
|
131
191
|
function sumOptionUnitPrice(options) {
|
|
132
|
-
let total = new
|
|
133
|
-
if (!Array.isArray(options))
|
|
134
|
-
return total;
|
|
192
|
+
let total = new _decimal.default(0);
|
|
193
|
+
if (!Array.isArray(options)) return total;
|
|
135
194
|
for (const opt of options) {
|
|
136
|
-
const price = new
|
|
137
|
-
const num = new
|
|
195
|
+
const price = new _decimal.default(Number(opt?.add_price ?? opt?.price) || 0);
|
|
196
|
+
const num = new _decimal.default(Number(opt?.num) || 0);
|
|
138
197
|
total = total.plus(price.times(num));
|
|
139
198
|
}
|
|
140
199
|
return total;
|
|
141
200
|
}
|
|
142
201
|
function getSafeOrderProductNum(num) {
|
|
143
202
|
const parsedNum = Number(num ?? 1);
|
|
144
|
-
if (!Number.isFinite(parsedNum) || parsedNum < 1)
|
|
145
|
-
return 1;
|
|
203
|
+
if (!Number.isFinite(parsedNum) || parsedNum < 1) return 1;
|
|
146
204
|
return Math.floor(parsedNum);
|
|
147
205
|
}
|
|
148
206
|
function getOrderProductDepositUnitTotal(product) {
|
|
@@ -150,48 +208,57 @@ function getOrderProductDepositUnitTotal(product) {
|
|
|
150
208
|
const paymentPrice = metadata.main_product_attached_bundle_payment_price;
|
|
151
209
|
const mainSellingPrice = metadata.main_product_selling_price;
|
|
152
210
|
const fallbackPrice = product.selling_price;
|
|
153
|
-
return new
|
|
211
|
+
return new _decimal.default(Number(paymentPrice ?? mainSellingPrice ?? fallbackPrice) || 0);
|
|
154
212
|
}
|
|
155
213
|
function normalizeDepositProtocols(protocols) {
|
|
156
|
-
if (!Array.isArray(protocols))
|
|
157
|
-
return [];
|
|
214
|
+
if (!Array.isArray(protocols)) return [];
|
|
158
215
|
return protocols.reduce((result, protocol) => {
|
|
159
|
-
const id = Number(protocol
|
|
160
|
-
if (!Number.isFinite(id))
|
|
161
|
-
return result;
|
|
216
|
+
const id = Number(protocol?.id);
|
|
217
|
+
if (!Number.isFinite(id)) return result;
|
|
162
218
|
result.push({
|
|
163
219
|
id: Math.floor(id),
|
|
164
|
-
title: String(
|
|
220
|
+
title: String(protocol?.title || '')
|
|
165
221
|
});
|
|
166
222
|
return result;
|
|
167
223
|
}, []);
|
|
168
224
|
}
|
|
169
225
|
function getDepositPolicyIds(depositData) {
|
|
170
|
-
const ids = [
|
|
171
|
-
...Array.isArray(depositData == null ? void 0 : depositData.self_deposit_policy_ids) ? depositData.self_deposit_policy_ids : [],
|
|
172
|
-
...Array.isArray(depositData == null ? void 0 : depositData.deposit_policy_ids) ? depositData.deposit_policy_ids : []
|
|
173
|
-
];
|
|
226
|
+
const ids = [...(Array.isArray(depositData?.self_deposit_policy_ids) ? depositData.self_deposit_policy_ids : []), ...(Array.isArray(depositData?.deposit_policy_ids) ? depositData.deposit_policy_ids : [])];
|
|
174
227
|
return ids.reduce((result, id) => {
|
|
175
228
|
const normalizedId = Number(id);
|
|
176
|
-
if (!Number.isFinite(normalizedId))
|
|
177
|
-
return result;
|
|
229
|
+
if (!Number.isFinite(normalizedId)) return result;
|
|
178
230
|
result.push(Math.floor(normalizedId));
|
|
179
231
|
return result;
|
|
180
232
|
}, []);
|
|
181
233
|
}
|
|
182
234
|
function handleOrderProductDeposit(params) {
|
|
183
|
-
const {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
235
|
+
const {
|
|
236
|
+
depositData,
|
|
237
|
+
total,
|
|
238
|
+
num
|
|
239
|
+
} = params;
|
|
240
|
+
if (!depositData) return {
|
|
241
|
+
result: false,
|
|
242
|
+
depositTotal: new _decimal.default(0)
|
|
243
|
+
};
|
|
244
|
+
const {
|
|
245
|
+
deposit_fixed,
|
|
246
|
+
deposit_percentage
|
|
247
|
+
} = depositData;
|
|
248
|
+
if (typeof deposit_fixed !== 'string' || typeof deposit_percentage !== 'string') {
|
|
249
|
+
return {
|
|
250
|
+
result: false,
|
|
251
|
+
depositTotal: new _decimal.default(0)
|
|
252
|
+
};
|
|
189
253
|
}
|
|
190
|
-
const depositFixed = new
|
|
191
|
-
const depositPercent = new
|
|
192
|
-
const productTotalPrice = new
|
|
254
|
+
const depositFixed = new _decimal.default(deposit_fixed || 0);
|
|
255
|
+
const depositPercent = new _decimal.default(deposit_percentage || 0);
|
|
256
|
+
const productTotalPrice = new _decimal.default(total || 0);
|
|
193
257
|
const deposit = depositFixed.plus(depositPercent.times(productTotalPrice));
|
|
194
|
-
return {
|
|
258
|
+
return {
|
|
259
|
+
depositTotal: deposit.times(num),
|
|
260
|
+
result: true
|
|
261
|
+
};
|
|
195
262
|
}
|
|
196
263
|
function resolveOrderProductDepositSource(product, runtimeOrigin) {
|
|
197
264
|
const record = product;
|
|
@@ -208,15 +275,14 @@ function resolveOrderProductDepositSource(product, runtimeOrigin) {
|
|
|
208
275
|
function getOrderProductDeposit(product, runtimeOrigin) {
|
|
209
276
|
const depositProduct = resolveOrderProductDepositSource(product, runtimeOrigin);
|
|
210
277
|
const depositData = depositProduct.custom_deposit_data;
|
|
211
|
-
if (
|
|
212
|
-
return null;
|
|
278
|
+
if (depositData?.has_deposit != 1) return null;
|
|
213
279
|
const num = getSafeOrderProductNum(product.num);
|
|
214
280
|
const total = getOrderProductDepositUnitTotal(product).times(num);
|
|
215
281
|
const allProtocols = normalizeDepositProtocols(depositData.deposit_policy_data);
|
|
216
282
|
const protocolIds = [];
|
|
217
|
-
let depositTotal = new
|
|
283
|
+
let depositTotal = new _decimal.default(0);
|
|
218
284
|
let hasDeposit = false;
|
|
219
|
-
if (typeof depositData.deposit_fixed ===
|
|
285
|
+
if (typeof depositData.deposit_fixed === 'string' && typeof depositData.deposit_percentage === 'string') {
|
|
220
286
|
const result = handleOrderProductDeposit({
|
|
221
287
|
depositData,
|
|
222
288
|
total,
|
|
@@ -232,10 +298,8 @@ function getOrderProductDeposit(product, runtimeOrigin) {
|
|
|
232
298
|
} else {
|
|
233
299
|
const productVariantId = depositProduct.product_variant_id ?? product.product_variant_id;
|
|
234
300
|
if (productVariantId) {
|
|
235
|
-
const variantProduct = (depositProduct.variant || []).find(
|
|
236
|
-
|
|
237
|
-
);
|
|
238
|
-
const variantDepositData = variantProduct == null ? void 0 : variantProduct.custom_deposit_data;
|
|
301
|
+
const variantProduct = (depositProduct.variant || []).find(item => item?.id === productVariantId);
|
|
302
|
+
const variantDepositData = variantProduct?.custom_deposit_data;
|
|
239
303
|
const result = handleOrderProductDeposit({
|
|
240
304
|
depositData: variantDepositData,
|
|
241
305
|
total,
|
|
@@ -244,221 +308,285 @@ function getOrderProductDeposit(product, runtimeOrigin) {
|
|
|
244
308
|
if (result.result) {
|
|
245
309
|
depositTotal = result.depositTotal;
|
|
246
310
|
protocolIds.push(...getDepositPolicyIds({
|
|
247
|
-
self_deposit_policy_ids: variantDepositData
|
|
311
|
+
self_deposit_policy_ids: variantDepositData?.self_deposit_policy_ids
|
|
248
312
|
}));
|
|
249
313
|
hasDeposit = true;
|
|
250
314
|
}
|
|
251
315
|
}
|
|
252
316
|
if (Array.isArray(product.product_bundle) && product.product_bundle.length) {
|
|
253
317
|
depositTotal = product.product_bundle.reduce((accumulator, bundleProduct) => {
|
|
254
|
-
const bundleDepositData = bundleProduct
|
|
318
|
+
const bundleDepositData = bundleProduct?.custom_deposit_data;
|
|
255
319
|
const result = handleOrderProductDeposit({
|
|
256
320
|
depositData: bundleDepositData,
|
|
257
|
-
total: bundleProduct
|
|
258
|
-
num: getSafeOrderProductNum(
|
|
321
|
+
total: bundleProduct?.price,
|
|
322
|
+
num: getSafeOrderProductNum(bundleProduct?.num || 1)
|
|
259
323
|
});
|
|
260
|
-
if (!result.result)
|
|
261
|
-
return accumulator;
|
|
324
|
+
if (!result.result) return accumulator;
|
|
262
325
|
protocolIds.push(...getDepositPolicyIds({
|
|
263
|
-
self_deposit_policy_ids: bundleDepositData
|
|
326
|
+
self_deposit_policy_ids: bundleDepositData?.self_deposit_policy_ids
|
|
264
327
|
}));
|
|
265
328
|
hasDeposit = true;
|
|
266
329
|
return accumulator.plus(result.depositTotal);
|
|
267
|
-
}, new
|
|
330
|
+
}, new _decimal.default(0));
|
|
268
331
|
}
|
|
269
332
|
}
|
|
270
|
-
if (!hasDeposit)
|
|
271
|
-
return null;
|
|
333
|
+
if (!hasDeposit) return null;
|
|
272
334
|
const protocolIdSet = new Set(protocolIds);
|
|
273
|
-
const protocols = allProtocols.filter(
|
|
335
|
+
const protocols = allProtocols.filter(protocol => protocolIdSet.has(protocol.id));
|
|
274
336
|
return {
|
|
275
337
|
total: depositTotal.toNumber(),
|
|
276
338
|
protocols
|
|
277
339
|
};
|
|
278
340
|
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* 仅基于 tempOrder.products 重算整单定金。
|
|
344
|
+
*
|
|
345
|
+
* 商品折扣在进入定金计算前已体现在商品行价格字段中,
|
|
346
|
+
* 因此这里只按商品定金规则汇总,不再扣减 discount_list;tempOrder.bookings 不参与这里的计算。
|
|
347
|
+
*/
|
|
279
348
|
function calculateOrderProductsDeposit(products = [], options) {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
let total = new import_decimal.default(0);
|
|
349
|
+
const protocolMap = new Map();
|
|
350
|
+
let total = new _decimal.default(0);
|
|
283
351
|
let hasDeposit = false;
|
|
284
352
|
for (const product of products || []) {
|
|
285
|
-
const productUid =
|
|
286
|
-
const runtimeOrigin = productUid ?
|
|
353
|
+
const productUid = product.metadata?.unique_identification_number;
|
|
354
|
+
const runtimeOrigin = productUid ? options?.productsByUid?.[productUid]?.origin : undefined;
|
|
287
355
|
const deposit = getOrderProductDeposit(product, runtimeOrigin);
|
|
288
356
|
product.deposit = deposit;
|
|
289
|
-
if (!
|
|
290
|
-
continue;
|
|
357
|
+
if (!deposit?.total || Number(deposit.total) <= 0) continue;
|
|
291
358
|
total = total.plus(deposit.total);
|
|
292
359
|
for (const protocol of deposit.protocols || []) {
|
|
293
|
-
if (!protocolMap.has(protocol.id))
|
|
294
|
-
protocolMap.set(protocol.id, protocol);
|
|
360
|
+
if (!protocolMap.has(protocol.id)) protocolMap.set(protocol.id, protocol);
|
|
295
361
|
}
|
|
296
362
|
hasDeposit = true;
|
|
297
363
|
}
|
|
298
|
-
const roundedTotal = total.toDecimalPlaces(2,
|
|
364
|
+
const roundedTotal = total.toDecimalPlaces(2, _decimal.default.ROUND_HALF_UP);
|
|
299
365
|
const protocols = [...protocolMap.values()];
|
|
300
366
|
return {
|
|
301
367
|
total: roundedTotal.toNumber(),
|
|
302
368
|
totalText: roundedTotal.toFixed(2),
|
|
303
369
|
protocols,
|
|
304
|
-
deposit_policy_ids: protocols.map(
|
|
370
|
+
deposit_policy_ids: protocols.map(protocol => protocol.id),
|
|
305
371
|
hasDeposit
|
|
306
372
|
};
|
|
307
373
|
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* 判定套餐子商品是否为 markdown(减价)类型。
|
|
377
|
+
* 与后端口径一致:price_type='markdown' 且 price_type_ext 非 'product_price'(原价子商品)。
|
|
378
|
+
*/
|
|
308
379
|
function isMarkdownBundle(bundle) {
|
|
309
|
-
if (!bundle || typeof bundle !==
|
|
310
|
-
return false;
|
|
380
|
+
if (!bundle || typeof bundle !== 'object') return false;
|
|
311
381
|
const ext = bundle.price_type_ext ?? bundle.custom_price_type_ext;
|
|
312
382
|
const type = bundle.price_type ?? bundle.custom_price_type;
|
|
313
|
-
return type ===
|
|
383
|
+
return type === 'markdown' && ext !== 'product_price';
|
|
314
384
|
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* 套餐子商品对「行价」的带符号单位贡献(与后端 markdown 口径对齐)。
|
|
388
|
+
*
|
|
389
|
+
* - markdown(减价):净额 = |catalog 毛价| − Σ(option.add_price×num),**取负**(行内减)。
|
|
390
|
+
* catalog 毛价优先 `price`/`custom_price`(避免读已落净额的 `bundle_selling_price` 造成 option 二次扣减);
|
|
391
|
+
* 仅当毛价缺失(历史/hydrate 仅剩净额)时退回 `bundle_selling_price`,且此时不再扣 option。
|
|
392
|
+
* - markup(加价)/原价子商品:维持 `+(bundle_selling_price ?? price)`,行为不变。
|
|
393
|
+
*/
|
|
315
394
|
function getBundleSignedUnit(bundle, options) {
|
|
316
|
-
if (!bundle || typeof bundle !==
|
|
317
|
-
|
|
318
|
-
const useOriginal = (options == null ? void 0 : options.useOriginal) ?? false;
|
|
395
|
+
if (!bundle || typeof bundle !== 'object') return new _decimal.default(0);
|
|
396
|
+
const useOriginal = options?.useOriginal ?? false;
|
|
319
397
|
if (isMarkdownBundle(bundle)) {
|
|
320
398
|
const catalog = useOriginal ? bundle.original_price ?? bundle.product_price ?? bundle.custom_price ?? bundle.base_price ?? bundle.price : bundle.custom_price ?? bundle.product_price ?? bundle.original_price ?? bundle.base_price ?? bundle.price;
|
|
321
|
-
if (catalog !==
|
|
322
|
-
const raw = new
|
|
323
|
-
|
|
324
|
-
|
|
399
|
+
if (catalog !== undefined && catalog !== null && catalog !== '') {
|
|
400
|
+
const raw = new _decimal.default(Number(catalog) || 0);
|
|
401
|
+
// 负值表示价格已是「带符号净额」(如 cart/changePrice 产出的 -3.7),直接取用不再扣 option,
|
|
402
|
+
// 避免与下游 option 二次扣减;正值为毛价(H5 路径,如 5),净额 = price − Σoptions 后取负。
|
|
403
|
+
if (raw.lt(0)) return raw;
|
|
325
404
|
return raw.minus(sumOptionUnitPrice(bundle.option)).negated();
|
|
326
405
|
}
|
|
327
|
-
|
|
406
|
+
// 仅剩净额(无毛价)兜底:直接取负,不再扣 option
|
|
407
|
+
return new _decimal.default(Number(bundle.bundle_selling_price) || 0).abs().negated();
|
|
328
408
|
}
|
|
329
409
|
const rawPrice = useOriginal ? bundle.original_price ?? bundle.product_price ?? bundle.price : bundle.bundle_selling_price ?? bundle.price;
|
|
330
|
-
return new
|
|
410
|
+
return new _decimal.default(Number(rawPrice) || 0);
|
|
331
411
|
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* 套餐子商品 `bundle_selling_price` 的存储净额(正值幅度)。
|
|
415
|
+
* markdown 取净额绝对值(3.70);markup/原价维持原值。
|
|
416
|
+
*/
|
|
332
417
|
function getBundleSellingMagnitude(bundle) {
|
|
333
418
|
return getBundleSignedUnit(bundle).abs();
|
|
334
419
|
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* OrderModule 默认 Rules 钩子工厂。
|
|
423
|
+
*
|
|
424
|
+
* 价格语义约定(订单域,v2 composite 口径):
|
|
425
|
+
* - `selling_price`:券后 **行 composite 单价**
|
|
426
|
+
* = `metadata.main_product_selling_price` + Σ(bundle_selling_price × num)。
|
|
427
|
+
* - `original_price`:券前 **行 composite 单价**
|
|
428
|
+
* = `metadata.main_product_original_price` + Σ(bundle 原价 × num)。
|
|
429
|
+
* - `metadata.source_product_price`:主商品/variant 基础价(已应用报价单),不含 option、
|
|
430
|
+
* 不含折扣。**权威源**。
|
|
431
|
+
* - `metadata.main_product_original_price` = source + Σ(option.price × option.num)(含 option、不含折扣)。
|
|
432
|
+
* - `metadata.main_product_selling_price` = main_original − 主商品券 per-unit amount(含 option、含折扣)。
|
|
433
|
+
* - `payment_price`:出站 payload 中为行 composite 已减整单折扣均摊价(无折扣时与 `selling_price` 同义)。
|
|
434
|
+
*
|
|
435
|
+
* Rules 钩子契约(hook_adapt 方案,Rules 内部保持不变):
|
|
436
|
+
* - `getProduct.price` / `getProduct.original_price` 回传 **source-level 主价**
|
|
437
|
+
* (`metadata.source_product_price`)。Rules 内部 `getProductTotalPrice` /
|
|
438
|
+
* `getProductOriginTotalPrice` 会自行叠加 option + bundle,喂 source 可避免 option 双加。
|
|
439
|
+
* - `getProduct.total` = `selling_price × num`(行 composite × num),与 Rules 内部产出的
|
|
440
|
+
* total(source + option + bundle)对齐。
|
|
441
|
+
* - `setProduct` 反向流程:把 Rules 返回的 source-level `main_product_selling_price` / `price`
|
|
442
|
+
* 加回 Σoptions,重新合成含 option 的 main_product_* 并派生 composite。
|
|
443
|
+
* 优先级:
|
|
444
|
+
* 1. `values.main_product_selling_price`(券应用分支,per-unit 券后 source-level 主价)
|
|
445
|
+
* 2. `values.price`(还原分支 `restoredPrice`、good_pass 归零)
|
|
446
|
+
* 3. `values.total / num`(仅当 Rules 只给出总价时的兜底)
|
|
447
|
+
*
|
|
448
|
+
* 导出为纯函数方便单测直接驱动钩子,不依赖 OrderModule 实例。
|
|
449
|
+
*/
|
|
450
|
+
|
|
451
|
+
/** Rules calcDiscount 用手动价标记;undefined 表示交给 Rules 用 total/origin_total 推断 */
|
|
335
452
|
function resolveRulesManualDiscountFlag(metadata) {
|
|
336
|
-
if (!metadata)
|
|
337
|
-
return void 0;
|
|
453
|
+
if (!metadata) return undefined;
|
|
338
454
|
if (metadata.is_manual_discount === true || metadata.is_manual_discount === 1) {
|
|
339
455
|
return true;
|
|
340
456
|
}
|
|
341
457
|
const priceOverride = metadata.price_override;
|
|
342
|
-
if (priceOverride !==
|
|
458
|
+
if (priceOverride !== undefined && priceOverride !== null && priceOverride !== '') {
|
|
343
459
|
return true;
|
|
344
460
|
}
|
|
345
|
-
return
|
|
461
|
+
return undefined;
|
|
346
462
|
}
|
|
347
463
|
function normalizeOrderProductDiscountAmount(amount) {
|
|
348
|
-
if (amount ===
|
|
349
|
-
return void 0;
|
|
464
|
+
if (amount === undefined || amount === null) return undefined;
|
|
350
465
|
return String(amount);
|
|
351
466
|
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* 商品行折扣只保留后端 OrderProductDiscountItem 协议字段。
|
|
470
|
+
* Rules/券计算过程中的 `_num`、`config` 等运行态字段不应进入 tempOrder 或提交 payload。
|
|
471
|
+
*/
|
|
352
472
|
function normalizeOrderProductDiscountList(discountList) {
|
|
353
|
-
if (!Array.isArray(discountList))
|
|
354
|
-
|
|
355
|
-
return discountList.filter((item) => !!item && typeof item === "object").map((item) => {
|
|
473
|
+
if (!Array.isArray(discountList)) return [];
|
|
474
|
+
return discountList.filter(item => !!item && typeof item === 'object').map(item => {
|
|
356
475
|
const normalized = {
|
|
357
476
|
discount_id: Number.isFinite(Number(item.discount_id)) ? Number(item.discount_id) : 0
|
|
358
477
|
};
|
|
359
478
|
if (item.order_discount_id === null) {
|
|
360
479
|
normalized.order_discount_id = null;
|
|
361
|
-
} else if (item.order_discount_id !==
|
|
480
|
+
} else if (item.order_discount_id !== undefined) {
|
|
362
481
|
const orderDiscountId = Number(item.order_discount_id);
|
|
363
482
|
if (Number.isFinite(orderDiscountId)) {
|
|
364
483
|
normalized.order_discount_id = orderDiscountId;
|
|
365
484
|
}
|
|
366
485
|
}
|
|
367
|
-
if (item.type !==
|
|
368
|
-
normalized.type = item.type;
|
|
486
|
+
if (item.type !== undefined) normalized.type = item.type;
|
|
369
487
|
const amount = normalizeOrderProductDiscountAmount(item.amount);
|
|
370
|
-
if (amount !==
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
488
|
+
if (amount !== undefined) normalized.amount = amount;
|
|
489
|
+
if (item.discount && typeof item.discount === 'object') {
|
|
490
|
+
normalized.discount = {
|
|
491
|
+
...item.discount
|
|
492
|
+
};
|
|
374
493
|
}
|
|
375
494
|
if (item.metadata === null) {
|
|
376
495
|
normalized.metadata = null;
|
|
377
|
-
} else if (item.metadata && typeof item.metadata ===
|
|
378
|
-
normalized.metadata = {
|
|
496
|
+
} else if (item.metadata && typeof item.metadata === 'object') {
|
|
497
|
+
normalized.metadata = {
|
|
498
|
+
...item.metadata
|
|
499
|
+
};
|
|
379
500
|
}
|
|
380
501
|
return normalized;
|
|
381
502
|
});
|
|
382
503
|
}
|
|
383
504
|
function resolveSubmitBundleMapId(bundle) {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
if (metadataMapId !== void 0 && metadataMapId !== null && metadataMapId !== "") {
|
|
505
|
+
const metadataMapId = bundle.metadata?.custom_product_bundle_map_id;
|
|
506
|
+
if (metadataMapId !== undefined && metadataMapId !== null && metadataMapId !== '') {
|
|
387
507
|
return metadataMapId;
|
|
388
508
|
}
|
|
389
|
-
if (bundle._id !==
|
|
509
|
+
if (bundle._id !== undefined && bundle._id !== null && bundle._id !== '') {
|
|
390
510
|
return bundle._id;
|
|
391
511
|
}
|
|
392
|
-
return
|
|
512
|
+
return undefined;
|
|
393
513
|
}
|
|
394
514
|
function collectSubmitProductDiscountList(product) {
|
|
395
|
-
const submitDiscountList = Array.isArray(product
|
|
396
|
-
for (const bundle of
|
|
397
|
-
if (!bundle || typeof bundle !==
|
|
398
|
-
continue;
|
|
515
|
+
const submitDiscountList = Array.isArray(product?.discount_list) ? [...product.discount_list] : [];
|
|
516
|
+
for (const bundle of product?.product_bundle || []) {
|
|
517
|
+
if (!bundle || typeof bundle !== 'object') continue;
|
|
399
518
|
const bundleMapId = resolveSubmitBundleMapId(bundle);
|
|
400
519
|
const bundleDiscountList = Array.isArray(bundle.discount_list) ? bundle.discount_list : [];
|
|
401
520
|
for (const discount of bundleDiscountList) {
|
|
402
|
-
if (!discount || typeof discount !==
|
|
403
|
-
|
|
404
|
-
const
|
|
405
|
-
const discountMapId = discountMetadata.custom_product_bundle_map_id !== void 0 && discountMetadata.custom_product_bundle_map_id !== null && discountMetadata.custom_product_bundle_map_id !== "" ? discountMetadata.custom_product_bundle_map_id : bundleMapId;
|
|
521
|
+
if (!discount || typeof discount !== 'object') continue;
|
|
522
|
+
const discountMetadata = discount.metadata && typeof discount.metadata === 'object' ? discount.metadata : {};
|
|
523
|
+
const discountMapId = discountMetadata.custom_product_bundle_map_id !== undefined && discountMetadata.custom_product_bundle_map_id !== null && discountMetadata.custom_product_bundle_map_id !== '' ? discountMetadata.custom_product_bundle_map_id : bundleMapId;
|
|
406
524
|
submitDiscountList.push({
|
|
407
525
|
...discount,
|
|
408
|
-
...discountMapId !==
|
|
526
|
+
...(discountMapId !== undefined ? {
|
|
409
527
|
metadata: {
|
|
410
528
|
...discountMetadata,
|
|
411
529
|
custom_product_bundle_map_id: discountMapId
|
|
412
530
|
}
|
|
413
|
-
} : {}
|
|
531
|
+
} : {})
|
|
414
532
|
});
|
|
415
533
|
}
|
|
416
534
|
}
|
|
417
535
|
return normalizeOrderProductDiscountList(submitDiscountList);
|
|
418
536
|
}
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* 手动改价(price_override)时行级 original_price(composite 单价):
|
|
540
|
+
* 购物车划线价应对齐 metadata.origin._extend.origin_total(改价前单价 composite,如 40),
|
|
541
|
+
* 而非 bundle 子项 catalog 原价合成的 composedOriginalPrice(如 30)。
|
|
542
|
+
*
|
|
543
|
+
* origin_total 与 SkuDetailModal / cacheItem._extend 一致,为单价语义,不再除以 num。
|
|
544
|
+
*/
|
|
419
545
|
function resolveManualOverrideLineOriginalPrice(params, fallbackCompositeOriginal) {
|
|
420
|
-
var _a, _b;
|
|
421
546
|
const metadata = params.metadata || {};
|
|
422
547
|
const priceOverride = metadata.price_override;
|
|
423
|
-
if (priceOverride ===
|
|
548
|
+
if (priceOverride === undefined || priceOverride === null || priceOverride === '') {
|
|
424
549
|
return fallbackCompositeOriginal;
|
|
425
550
|
}
|
|
426
|
-
const refTotal =
|
|
427
|
-
if (refTotal !==
|
|
551
|
+
const refTotal = metadata.origin?._extend?.origin_total;
|
|
552
|
+
if (refTotal !== undefined && refTotal !== null && refTotal !== '') {
|
|
428
553
|
const parsed = Number(refTotal);
|
|
429
554
|
if (Number.isFinite(parsed)) {
|
|
430
|
-
return new
|
|
555
|
+
return new _decimal.default(parsed).toDecimalPlaces(2).toFixed(2);
|
|
431
556
|
}
|
|
432
557
|
}
|
|
433
558
|
const lineOriginal = params.lineOriginalPrice;
|
|
434
|
-
if (lineOriginal !==
|
|
559
|
+
if (lineOriginal !== undefined && lineOriginal !== null && lineOriginal !== '') {
|
|
435
560
|
const parsedLine = Number(lineOriginal);
|
|
436
561
|
const parsedFallback = Number(fallbackCompositeOriginal);
|
|
437
562
|
if (Number.isFinite(parsedLine) && Number.isFinite(parsedFallback) && parsedLine > parsedFallback) {
|
|
438
|
-
return new
|
|
563
|
+
return new _decimal.default(parsedLine).toDecimalPlaces(2).toFixed(2);
|
|
439
564
|
}
|
|
440
565
|
}
|
|
441
566
|
return fallbackCompositeOriginal;
|
|
442
567
|
}
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* 计算商品行「每单位有效折扣」:discount_list 合计 + 被 Rules 剥离但仍 inPromotion 的差额。
|
|
571
|
+
*
|
|
572
|
+
* Rules.calcDiscount 会把 type=promotion 从 discount_list 去掉,但 metadata._promotion 仍保留;
|
|
573
|
+
* applyProductDiscountPrices 必须回读 _promotion,否则抬价/降价都会在第二步被 source 原价覆盖。
|
|
574
|
+
*
|
|
575
|
+
* @example
|
|
576
|
+
* resolveEffectivePerUnitDiscount({ metadata: { _promotion: { inPromotion: true, originalPrice: 1, finalPrice: 5 } }, discount_list: [] });
|
|
577
|
+
* // => -4
|
|
578
|
+
*/
|
|
443
579
|
function resolveEffectivePerUnitDiscount(product) {
|
|
444
|
-
const discountList = Array.isArray(product
|
|
445
|
-
const fromList = discountList.reduce(
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
const hasPromoDiscountItem = discountList.some(
|
|
450
|
-
(item) => {
|
|
451
|
-
var _a, _b;
|
|
452
|
-
return (item == null ? void 0 : item.type) === "promotion" || (item == null ? void 0 : item.type) === "product" && ((_a = item == null ? void 0 : item.metadata) == null ? void 0 : _a.source) === "promotion" && ((_b = item == null ? void 0 : item.metadata) == null ? void 0 : _b.actionType) === "ITEM_REWARD";
|
|
453
|
-
}
|
|
454
|
-
);
|
|
455
|
-
if (hasPromoDiscountItem)
|
|
456
|
-
return fromList;
|
|
457
|
-
const metadata = (product == null ? void 0 : product.metadata) || {};
|
|
580
|
+
const discountList = Array.isArray(product?.discount_list) ? product.discount_list : [];
|
|
581
|
+
const fromList = discountList.reduce((sum, discount) => sum + Number(discount?.amount || 0), 0);
|
|
582
|
+
const hasPromoDiscountItem = discountList.some(item => item?.type === 'promotion' || item?.type === 'product' && item?.metadata?.source === 'promotion' && item?.metadata?.actionType === 'ITEM_REWARD');
|
|
583
|
+
if (hasPromoDiscountItem) return fromList;
|
|
584
|
+
const metadata = product?.metadata || {};
|
|
458
585
|
const promo = metadata._promotion;
|
|
459
|
-
if (
|
|
460
|
-
return fromList;
|
|
586
|
+
if (promo?.inPromotion !== true) return fromList;
|
|
461
587
|
const optionSum = sumOptionUnitPrice(getProductSkuOptions(product)).toNumber();
|
|
588
|
+
|
|
589
|
+
// applyPromotion 写价后、Rules 剥离 promotion discount 的兜底
|
|
462
590
|
if (!discountList.length && metadata.source_product_price != null && metadata.main_product_selling_price != null) {
|
|
463
591
|
const source = Number(metadata.source_product_price);
|
|
464
592
|
const selling = Number(metadata.main_product_selling_price) - optionSum;
|
|
@@ -468,77 +596,70 @@ function resolveEffectivePerUnitDiscount(product) {
|
|
|
468
596
|
}
|
|
469
597
|
const originalPrice = Number(promo.originalPrice);
|
|
470
598
|
const finalPrice = Number(promo.finalPrice);
|
|
471
|
-
if (!Number.isFinite(originalPrice) || !Number.isFinite(finalPrice))
|
|
472
|
-
return fromList;
|
|
599
|
+
if (!Number.isFinite(originalPrice) || !Number.isFinite(finalPrice)) return fromList;
|
|
473
600
|
return fromList + (originalPrice - finalPrice);
|
|
474
601
|
}
|
|
475
602
|
function createDefaultOrderRulesHooks() {
|
|
476
603
|
const toUnitPriceString = (totalLike, num) => {
|
|
477
604
|
const effectiveNum = Number(num) > 0 ? Number(num) : 1;
|
|
478
|
-
return new
|
|
605
|
+
return new _decimal.default(Number(totalLike) || 0).dividedBy(effectiveNum).toDecimalPlaces(2).toString();
|
|
479
606
|
};
|
|
480
|
-
const getBundleIdentity =
|
|
481
|
-
return [
|
|
482
|
-
bundle.bundle_id ?? bundle.id ?? "",
|
|
483
|
-
bundle.bundle_product_id ?? bundle._bundle_product_id ?? bundle.product_id ?? "",
|
|
484
|
-
bundle.bundle_variant_id ?? bundle.variant_id ?? bundle.product_variant_id ?? 0,
|
|
485
|
-
bundle.bundle_group_id ?? bundle.group_id ?? ""
|
|
486
|
-
].join("|");
|
|
607
|
+
const getBundleIdentity = bundle => {
|
|
608
|
+
return [bundle.bundle_id ?? bundle.id ?? '', bundle.bundle_product_id ?? bundle._bundle_product_id ?? bundle.product_id ?? '', bundle.bundle_variant_id ?? bundle.variant_id ?? bundle.product_variant_id ?? 0, bundle.bundle_group_id ?? bundle.group_id ?? ''].join('|');
|
|
487
609
|
};
|
|
488
610
|
const mergeRulesBundlePrices = (currentBundle, rulesBundle) => {
|
|
489
|
-
if (!Array.isArray(rulesBundle))
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
if (!bundle || typeof bundle !== "object")
|
|
494
|
-
return;
|
|
611
|
+
if (!Array.isArray(rulesBundle)) return rulesBundle;
|
|
612
|
+
const currentByIdentity = new Map();
|
|
613
|
+
(currentBundle || []).forEach(bundle => {
|
|
614
|
+
if (!bundle || typeof bundle !== 'object') return;
|
|
495
615
|
currentByIdentity.set(getBundleIdentity(bundle), bundle);
|
|
496
616
|
});
|
|
497
|
-
return rulesBundle.map(
|
|
498
|
-
if (!bundle || typeof bundle !==
|
|
499
|
-
return bundle;
|
|
617
|
+
return rulesBundle.map(bundle => {
|
|
618
|
+
if (!bundle || typeof bundle !== 'object') return bundle;
|
|
500
619
|
const current = currentByIdentity.get(getBundleIdentity(bundle));
|
|
501
|
-
if (!current)
|
|
502
|
-
return bundle;
|
|
620
|
+
if (!current) return bundle;
|
|
503
621
|
const bundleWithDisplayFields = {
|
|
504
622
|
...bundle,
|
|
505
|
-
...isEmptyOrderProductDisplayValue(bundle.cover) && !isEmptyOrderProductDisplayValue(current.cover) ? {
|
|
623
|
+
...(isEmptyOrderProductDisplayValue(bundle.cover) && !isEmptyOrderProductDisplayValue(current.cover) ? {
|
|
624
|
+
cover: current.cover
|
|
625
|
+
} : {})
|
|
506
626
|
};
|
|
507
|
-
const isProductPriceBundle = (bundle.price_type_ext ?? current.price_type_ext) ===
|
|
508
|
-
if (!isProductPriceBundle)
|
|
509
|
-
return bundleWithDisplayFields;
|
|
627
|
+
const isProductPriceBundle = (bundle.price_type_ext ?? current.price_type_ext) === 'product_price';
|
|
628
|
+
if (!isProductPriceBundle) return bundleWithDisplayFields;
|
|
510
629
|
const sourcePrice = current.price ?? current.custom_price ?? current.original_price ?? current.bundle_selling_price;
|
|
511
630
|
const originalPrice = current.original_price ?? current.product_price ?? current.price ?? current.custom_price ?? sourcePrice;
|
|
512
631
|
return {
|
|
513
632
|
...bundleWithDisplayFields,
|
|
514
|
-
...sourcePrice !==
|
|
515
|
-
|
|
516
|
-
|
|
633
|
+
...(sourcePrice !== undefined ? {
|
|
634
|
+
price: sourcePrice
|
|
635
|
+
} : {}),
|
|
636
|
+
...(originalPrice !== undefined ? {
|
|
637
|
+
original_price: originalPrice
|
|
638
|
+
} : {}),
|
|
639
|
+
...(current.original_total !== undefined ? {
|
|
640
|
+
original_total: current.original_total
|
|
641
|
+
} : {})
|
|
517
642
|
};
|
|
518
643
|
});
|
|
519
644
|
};
|
|
520
645
|
return {
|
|
521
|
-
getProduct:
|
|
522
|
-
|
|
646
|
+
getProduct: product => {
|
|
647
|
+
// source_product_price 是权威源;兜底链:source → mainSelling − options(反推)→ 行 selling_price
|
|
523
648
|
const metadataAny = product.metadata || {};
|
|
524
649
|
const optionSum = sumOptionUnitPrice(getProductSkuOptions(product));
|
|
525
650
|
let sourcePrice;
|
|
526
|
-
if (metadataAny.source_product_price !==
|
|
651
|
+
if (metadataAny.source_product_price !== undefined) {
|
|
527
652
|
sourcePrice = String(metadataAny.source_product_price);
|
|
528
|
-
} else if (metadataAny.main_product_selling_price !==
|
|
529
|
-
sourcePrice = new
|
|
530
|
-
Number(metadataAny.main_product_selling_price) || 0
|
|
531
|
-
).minus(optionSum).toDecimalPlaces(2).toString();
|
|
653
|
+
} else if (metadataAny.main_product_selling_price !== undefined) {
|
|
654
|
+
sourcePrice = new _decimal.default(Number(metadataAny.main_product_selling_price) || 0).minus(optionSum).toDecimalPlaces(2).toString();
|
|
532
655
|
} else {
|
|
533
656
|
sourcePrice = String(product.selling_price ?? 0);
|
|
534
657
|
}
|
|
535
658
|
let sourceOriginalPrice;
|
|
536
|
-
if (metadataAny.source_product_price !==
|
|
659
|
+
if (metadataAny.source_product_price !== undefined) {
|
|
537
660
|
sourceOriginalPrice = String(metadataAny.source_product_price);
|
|
538
|
-
} else if (metadataAny.main_product_original_price !==
|
|
539
|
-
sourceOriginalPrice = new
|
|
540
|
-
Number(metadataAny.main_product_original_price) || 0
|
|
541
|
-
).minus(optionSum).toDecimalPlaces(2).toString();
|
|
661
|
+
} else if (metadataAny.main_product_original_price !== undefined) {
|
|
662
|
+
sourceOriginalPrice = new _decimal.default(Number(metadataAny.main_product_original_price) || 0).minus(optionSum).toDecimalPlaces(2).toString();
|
|
542
663
|
} else {
|
|
543
664
|
sourceOriginalPrice = sourcePrice;
|
|
544
665
|
}
|
|
@@ -548,46 +669,50 @@ function createDefaultOrderRulesHooks() {
|
|
|
548
669
|
// 否则同 SKU 不同小料会在 calcDiscount 重组时互相覆盖。
|
|
549
670
|
// 不透明 identity 契约下,normalizeOrderProduct / hydrate 已保证唯一值存在;
|
|
550
671
|
// 留 fingerprint 分支仅作 Rules 单测里直接传裸 product 时的兜底。
|
|
551
|
-
_id:
|
|
552
|
-
getProductSkuOptions(product),
|
|
553
|
-
product.product_bundle
|
|
554
|
-
)}`,
|
|
672
|
+
_id: product.metadata?.unique_identification_number ? `${product.product_id}_${product.product_variant_id}_${product.metadata.unique_identification_number}` : `${product.product_id}_${product.product_variant_id}_${(0, _utils2.buildProductLineFingerprint)(getProductSkuOptions(product), product.product_bundle)}`,
|
|
555
673
|
// Rules 内部 getProductTotalPrice / getProductOriginTotalPrice 会各自再叠加 bundle + option,
|
|
556
674
|
// 所以这里必须喂 source-level(不含 option、不含 bundle、不含折扣)单价,避免双加 option。
|
|
557
675
|
price: sourcePrice,
|
|
558
676
|
// total / origin_total 使用 composite × num,跟 Rules 内部产出的 total 对齐(含 option + bundle)。
|
|
559
|
-
total: new
|
|
560
|
-
origin_total: new
|
|
561
|
-
product.original_price || product.selling_price || 0
|
|
562
|
-
).times(product.num || 1).toNumber(),
|
|
677
|
+
total: new _decimal.default(product.selling_price || 0).times(product.num || 1).toNumber(),
|
|
678
|
+
origin_total: new _decimal.default(product.original_price || product.selling_price || 0).times(product.num || 1).toNumber(),
|
|
563
679
|
original_price: sourceOriginalPrice,
|
|
564
680
|
quantity: product.num || 1,
|
|
565
681
|
num: product.num || 1,
|
|
566
682
|
discount_list: product.discount_list || [],
|
|
567
683
|
bundle: product.product_bundle || [],
|
|
568
|
-
booking_id:
|
|
684
|
+
booking_id: product.metadata?.booking_id || null,
|
|
569
685
|
isClient: false,
|
|
570
686
|
// 勿写死 false:否则 Rules 不会走 total≠origin_total 的手动价推断,
|
|
571
687
|
// 无券时会把 bundle 价还原成 original_price(手动改价套餐会从 20 回到 30)。
|
|
572
688
|
isManualDiscount: resolveRulesManualDiscountFlag(metadataAny),
|
|
573
|
-
holder_id:
|
|
574
|
-
startDate:
|
|
575
|
-
main_product_selling_price: metadataAny.main_product_selling_price !==
|
|
576
|
-
inPromotion:
|
|
689
|
+
holder_id: product.metadata?.holder_id,
|
|
690
|
+
startDate: product.metadata?.start_date || product.metadata?.startDate,
|
|
691
|
+
main_product_selling_price: metadataAny.main_product_selling_price !== undefined ? new _decimal.default(Number(metadataAny.main_product_selling_price) || 0).minus(optionSum).toDecimalPlaces(2).toString() : undefined,
|
|
692
|
+
inPromotion: metadataAny._promotion?.inPromotion === true,
|
|
577
693
|
_promotion: metadataAny._promotion
|
|
578
694
|
};
|
|
579
695
|
},
|
|
580
696
|
setProduct: (product, values) => {
|
|
581
697
|
const nextNum = Number(values.quantity ?? product.num ?? 1) || 1;
|
|
582
698
|
const metadataAny = product.metadata || {};
|
|
583
|
-
const existedSource = metadataAny.source_product_price ?? product.selling_price ??
|
|
699
|
+
const existedSource = metadataAny.source_product_price ?? product.selling_price ?? '0';
|
|
584
700
|
const nextOptions = getProductSkuOptions(product);
|
|
585
701
|
const optionSum = sumOptionUnitPrice(nextOptions);
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
const
|
|
702
|
+
|
|
703
|
+
// Rules 返回的 main_product_selling_price / price / total 均为 source-level。
|
|
704
|
+
// 优先级:main_product_selling_price(per-unit 券后 source)> price(还原/good_pass 分支)>
|
|
705
|
+
// total/num(仅当 Rules 只给 total 时的兜底)> 保留当前 source。
|
|
706
|
+
const nextSourceSellingPrice = values.main_product_selling_price !== undefined ? String(values.main_product_selling_price) : values.price !== undefined ? String(values.price) : values.total !== undefined ? toUnitPriceString(values.total, nextNum) : String(existedSource);
|
|
707
|
+
|
|
708
|
+
// 券前 source:values.original_price 是 source-level(Rules 层本就不含 option),
|
|
709
|
+
// 缺省时保留现有 source(券前 = 当前 source)。
|
|
710
|
+
const nextSourceOriginalPrice = values.original_price !== undefined ? String(values.original_price) : String(existedSource);
|
|
711
|
+
|
|
712
|
+
// 含 option 的 main_product_*
|
|
713
|
+
const nextMainSellingPrice = new _decimal.default(Number(nextSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
|
|
714
|
+
const nextMainOriginalPrice = new _decimal.default(Number(nextSourceOriginalPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
|
|
715
|
+
const nextBundle = values.bundle !== undefined ? mergeRulesBundlePrices(product.product_bundle, values.bundle) : product.product_bundle;
|
|
591
716
|
const composedSellingPrice = composeLinePrice({
|
|
592
717
|
mainPrice: nextMainSellingPrice,
|
|
593
718
|
bundle: nextBundle
|
|
@@ -597,10 +722,11 @@ function createDefaultOrderRulesHooks() {
|
|
|
597
722
|
bundle: nextBundle,
|
|
598
723
|
useOriginalBundle: true
|
|
599
724
|
});
|
|
600
|
-
const finalOriginalPrice = resolveManualOverrideLineOriginalPrice(
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
725
|
+
const finalOriginalPrice = resolveManualOverrideLineOriginalPrice({
|
|
726
|
+
num: nextNum,
|
|
727
|
+
metadata: metadataAny,
|
|
728
|
+
lineOriginalPrice: product.original_price
|
|
729
|
+
}, composedOriginalPrice);
|
|
604
730
|
return {
|
|
605
731
|
...product,
|
|
606
732
|
selling_price: composedSellingPrice,
|
|
@@ -619,47 +745,73 @@ function createDefaultOrderRulesHooks() {
|
|
|
619
745
|
}
|
|
620
746
|
};
|
|
621
747
|
}
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
748
|
+
|
|
749
|
+
/**
|
|
750
|
+
* 通过 session 类商品的开始时间结束时间生成商品的时长
|
|
751
|
+
* @param {CartItem} cartItem
|
|
752
|
+
* @return {*}
|
|
753
|
+
*/
|
|
754
|
+
const generateDuration = cartItem => {
|
|
755
|
+
const startDate = (0, _dayjs.default)(`${cartItem.start_date} ${cartItem.start_time}`);
|
|
756
|
+
const endDate = (0, _dayjs.default)(`${cartItem.end_date} ${cartItem.end_time}`);
|
|
757
|
+
const duration = endDate.diff(startDate, 'minutes');
|
|
758
|
+
return {
|
|
759
|
+
duration,
|
|
760
|
+
durationType: 'minutes'
|
|
761
|
+
};
|
|
627
762
|
};
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
}
|
|
641
|
-
|
|
763
|
+
|
|
764
|
+
/**
|
|
765
|
+
* 合并关联表单
|
|
766
|
+
* @param relationForms 关联表单
|
|
767
|
+
* @returns 合并后的关联表单
|
|
768
|
+
*/
|
|
769
|
+
exports.generateDuration = generateDuration;
|
|
770
|
+
const mergeRelationForms = relationForms => {
|
|
771
|
+
return Object.values(relationForms.reduce((acc, cur) => {
|
|
772
|
+
const {
|
|
773
|
+
form_id,
|
|
774
|
+
form_record_ids
|
|
775
|
+
} = cur;
|
|
776
|
+
// 如果 acc 中没有 form_id,则初始化一个空数组
|
|
777
|
+
if (!acc[form_id]) {
|
|
778
|
+
acc[form_id] = {
|
|
779
|
+
form_id,
|
|
780
|
+
form_record_ids: []
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
// 兼容 form_record_id 可能是数组或单个数字
|
|
785
|
+
const ids = Array.isArray(form_record_ids) ? form_record_ids : [form_record_ids];
|
|
786
|
+
// 过滤掉空值(null、undefined等)
|
|
787
|
+
const validIds = ids.filter(id => id != null);
|
|
788
|
+
acc[form_id].form_record_ids.push(...validIds);
|
|
789
|
+
// 去重
|
|
790
|
+
acc[form_id].form_record_ids = [...new Set(acc[form_id].form_record_ids)];
|
|
791
|
+
return acc;
|
|
792
|
+
}, {})).filter(item => item.form_record_ids.length > 0); // 过滤掉没有有效记录的表单
|
|
642
793
|
};
|
|
794
|
+
exports.mergeRelationForms = mergeRelationForms;
|
|
643
795
|
function getCustomerIdFromStorage(window) {
|
|
644
|
-
var _a;
|
|
645
796
|
try {
|
|
646
|
-
const customer = JSON.parse(
|
|
647
|
-
const customerId = Number(customer
|
|
648
|
-
return Number.isFinite(customerId) && customerId > 0 ? customerId :
|
|
797
|
+
const customer = JSON.parse(window?.getLocalStorage?.('customer') || '{}');
|
|
798
|
+
const customerId = Number(customer?.id);
|
|
799
|
+
return Number.isFinite(customerId) && customerId > 0 ? customerId : undefined;
|
|
649
800
|
} catch {
|
|
650
|
-
return
|
|
801
|
+
return undefined;
|
|
651
802
|
}
|
|
652
803
|
}
|
|
804
|
+
|
|
805
|
+
/**
|
|
806
|
+
* 为购物车行补齐订单所需的 holder 信息(与 cartAccount 结构保持一致)
|
|
807
|
+
*/
|
|
653
808
|
function ensureCartItemOriginHolder(cartItem, window) {
|
|
654
|
-
|
|
655
|
-
if ((_a = cartItem == null ? void 0 : cartItem._origin) == null ? void 0 : _a.holder) {
|
|
809
|
+
if (cartItem?._origin?.holder) {
|
|
656
810
|
return;
|
|
657
811
|
}
|
|
658
|
-
const holderConfig = (0,
|
|
659
|
-
|
|
660
|
-
)
|
|
661
|
-
const formRecordId = cartItem == null ? void 0 : cartItem.holder_id;
|
|
662
|
-
if (!(holderConfig == null ? void 0 : holderConfig.resource_id) || formRecordId == null) {
|
|
812
|
+
const holderConfig = (0, _utils.getProductHolderConfig)(cartItem?._productInit ?? cartItem?._productOrigin);
|
|
813
|
+
const formRecordId = cartItem?.holder_id;
|
|
814
|
+
if (!holderConfig?.resource_id || formRecordId == null) {
|
|
663
815
|
return;
|
|
664
816
|
}
|
|
665
817
|
cartItem._origin.holder = {
|
|
@@ -668,24 +820,25 @@ function ensureCartItemOriginHolder(cartItem, window) {
|
|
|
668
820
|
form_record: [formRecordId]
|
|
669
821
|
};
|
|
670
822
|
}
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
let discountList =
|
|
674
|
-
(
|
|
675
|
-
discountList = [...discountList, ...(item
|
|
676
|
-
item.discount_list =
|
|
823
|
+
;
|
|
824
|
+
const getAllDiscountList = cartItem => {
|
|
825
|
+
let discountList = cartItem?._origin?.product?.discount_list || [];
|
|
826
|
+
(cartItem?._origin?.product?.product_bundle || []).forEach(item => {
|
|
827
|
+
discountList = [...discountList, ...(item?.discount_list || [])];
|
|
828
|
+
item.discount_list = undefined;
|
|
677
829
|
});
|
|
678
830
|
return discountList;
|
|
679
831
|
};
|
|
832
|
+
|
|
833
|
+
// ─── 以下为从 ScanOrder/utils.ts 迁入的 Order 专属工具函数 ───
|
|
834
|
+
exports.getAllDiscountList = getAllDiscountList;
|
|
680
835
|
function isTempOrder(data) {
|
|
681
|
-
if (!data || typeof data !==
|
|
682
|
-
|
|
683
|
-
if (!Array.isArray(data.products))
|
|
684
|
-
return false;
|
|
836
|
+
if (!data || typeof data !== 'object') return false;
|
|
837
|
+
if (!Array.isArray(data.products)) return false;
|
|
685
838
|
return true;
|
|
686
839
|
}
|
|
687
840
|
function formatDateTime(date) {
|
|
688
|
-
const pad =
|
|
841
|
+
const pad = value => value.toString().padStart(2, '0');
|
|
689
842
|
const year = date.getFullYear();
|
|
690
843
|
const month = pad(date.getMonth() + 1);
|
|
691
844
|
const day = pad(date.getDate());
|
|
@@ -695,29 +848,26 @@ function formatDateTime(date) {
|
|
|
695
848
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
|
696
849
|
}
|
|
697
850
|
function normalizeSubmitPlatform(platform) {
|
|
698
|
-
const value = String(platform ||
|
|
699
|
-
if (!value)
|
|
700
|
-
return "H5";
|
|
851
|
+
const value = String(platform || '').trim();
|
|
852
|
+
if (!value) return 'H5';
|
|
701
853
|
const lower = value.toLowerCase();
|
|
702
|
-
if (lower ===
|
|
703
|
-
|
|
704
|
-
if (lower === "h5")
|
|
705
|
-
return "H5";
|
|
854
|
+
if (lower === 'pc') return 'PC';
|
|
855
|
+
if (lower === 'h5') return 'H5';
|
|
706
856
|
return value;
|
|
707
857
|
}
|
|
858
|
+
|
|
859
|
+
// 后端 checkout 协议字段 option_group_item_id;tempOrder 内部也保持同一字段名。
|
|
708
860
|
function formatSubmitOptionItems(options) {
|
|
709
|
-
if (!Array.isArray(options))
|
|
710
|
-
|
|
711
|
-
return options.map((d) => {
|
|
861
|
+
if (!Array.isArray(options)) return [];
|
|
862
|
+
return options.map(d => {
|
|
712
863
|
const option = {
|
|
713
|
-
...d && typeof d ===
|
|
714
|
-
num: d
|
|
715
|
-
option_group_item_id: d
|
|
716
|
-
option_group_id: d
|
|
864
|
+
...(d && typeof d === 'object' ? d : {}),
|
|
865
|
+
num: d?.num,
|
|
866
|
+
option_group_item_id: d?.option_group_item_id,
|
|
867
|
+
option_group_id: d?.option_group_id
|
|
717
868
|
};
|
|
718
|
-
const addPrice =
|
|
719
|
-
if (addPrice !==
|
|
720
|
-
option.add_price = String(addPrice);
|
|
869
|
+
const addPrice = d?.add_price ?? d?.price;
|
|
870
|
+
if (addPrice !== undefined) option.add_price = String(addPrice);
|
|
721
871
|
delete option.price;
|
|
722
872
|
return option;
|
|
723
873
|
});
|
|
@@ -728,33 +878,31 @@ function toBundleNumber(value, fallback = 0) {
|
|
|
728
878
|
}
|
|
729
879
|
function toMoneyString(value) {
|
|
730
880
|
const parsed = Number(value);
|
|
731
|
-
if (Number.isFinite(parsed))
|
|
732
|
-
|
|
733
|
-
if (value === null || value === void 0 || value === "")
|
|
734
|
-
return "0.00";
|
|
881
|
+
if (Number.isFinite(parsed)) return parsed.toFixed(2);
|
|
882
|
+
if (value === null || value === undefined || value === '') return '0.00';
|
|
735
883
|
return String(value);
|
|
736
884
|
}
|
|
885
|
+
|
|
886
|
+
// 出站补齐:只输出后端 checkout 协议字段,运行时/详情展示字段不进入 bundle payload。
|
|
737
887
|
function formatSubmitBundleItems(bundle) {
|
|
738
|
-
if (!Array.isArray(bundle))
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
const
|
|
742
|
-
const existedMetadata = rawBundle.metadata && typeof rawBundle.metadata === "object" ? rawBundle.metadata : {};
|
|
888
|
+
if (!Array.isArray(bundle)) return [];
|
|
889
|
+
return bundle.map(b => {
|
|
890
|
+
const rawBundle = b && typeof b === 'object' ? b : {};
|
|
891
|
+
const existedMetadata = rawBundle.metadata && typeof rawBundle.metadata === 'object' ? rawBundle.metadata : {};
|
|
743
892
|
const {
|
|
744
893
|
custom_product_bundle_map_id: _customProductBundleMapId,
|
|
745
894
|
...submitMetadata
|
|
746
895
|
} = existedMetadata;
|
|
896
|
+
|
|
897
|
+
// bundle_selling_price 出站存「正净额」:markdown 为 |price| − Σoptions(如 3.70),
|
|
898
|
+
// markup/原价维持原值;与后端口径一致(price 仍为毛价)。
|
|
747
899
|
const sellingPrice = getBundleSellingMagnitude(rawBundle).toFixed(2);
|
|
748
|
-
|
|
900
|
+
// payment 价由整单折扣均摊层产出;缺省(无折扣)时与 selling 净额同义。
|
|
901
|
+
const paymentPrice = rawBundle.bundle_payment_price !== undefined && rawBundle.bundle_payment_price !== null && rawBundle.bundle_payment_price !== '' ? toMoneyString(rawBundle.bundle_payment_price) : sellingPrice;
|
|
749
902
|
const priceValue = rawBundle.price ?? rawBundle.custom_price ?? rawBundle.bundle_selling_price;
|
|
750
903
|
const relationSurchargeIds = Array.isArray(rawBundle.relation_surcharge_ids) ? rawBundle.relation_surcharge_ids : Array.isArray(existedMetadata.relation_surcharge_ids) ? existedMetadata.relation_surcharge_ids : [];
|
|
751
|
-
const surchargeFee = toMoneyString(
|
|
752
|
-
|
|
753
|
-
);
|
|
754
|
-
const productDiscountDifference = toBundleNumber(
|
|
755
|
-
existedMetadata.product_discount_difference,
|
|
756
|
-
0
|
|
757
|
-
);
|
|
904
|
+
const surchargeFee = toMoneyString(rawBundle.surcharge_fee ?? existedMetadata.surcharge_fee);
|
|
905
|
+
const productDiscountDifference = toBundleNumber(existedMetadata.product_discount_difference, 0);
|
|
758
906
|
const num = toBundleNumber(rawBundle.num ?? rawBundle.quantity, 1);
|
|
759
907
|
const bundleMapId = resolveSubmitBundleMapId(rawBundle);
|
|
760
908
|
const hasSubmitBundleDiscounts = Array.isArray(rawBundle.discount_list) && rawBundle.discount_list.length > 0;
|
|
@@ -764,20 +912,22 @@ function formatSubmitBundleItems(bundle) {
|
|
|
764
912
|
num,
|
|
765
913
|
quantity: toBundleNumber(rawBundle.quantity ?? rawBundle.num, num),
|
|
766
914
|
extension_id: rawBundle.extension_id ?? 0,
|
|
767
|
-
extension_type: rawBundle.extension_type ??
|
|
915
|
+
extension_type: rawBundle.extension_type ?? 'normal',
|
|
768
916
|
price: priceValue,
|
|
769
|
-
price_type: rawBundle.price_type ?? rawBundle.custom_price_type ??
|
|
770
|
-
price_type_ext: rawBundle.price_type_ext ?? rawBundle.custom_price_type_ext ??
|
|
917
|
+
price_type: rawBundle.price_type ?? rawBundle.custom_price_type ?? '',
|
|
918
|
+
price_type_ext: rawBundle.price_type_ext ?? rawBundle.custom_price_type_ext ?? '',
|
|
771
919
|
bundle_selling_price: sellingPrice,
|
|
772
920
|
bundle_payment_price: paymentPrice,
|
|
773
921
|
option: formatSubmitOptionItems(rawBundle.option),
|
|
774
|
-
bundle_group_id:
|
|
775
|
-
bundle_id:
|
|
776
|
-
bundle_product_id:
|
|
922
|
+
bundle_group_id: rawBundle?.bundle_group_id ?? rawBundle?.group_id,
|
|
923
|
+
bundle_id: rawBundle?.bundle_id ?? rawBundle?.id,
|
|
924
|
+
bundle_product_id: rawBundle?.bundle_product_id ?? rawBundle?._bundle_product_id,
|
|
777
925
|
cover: rawBundle.cover,
|
|
778
926
|
metadata: {
|
|
779
927
|
...submitMetadata,
|
|
780
|
-
...hasSubmitBundleDiscounts && bundleMapId !==
|
|
928
|
+
...(hasSubmitBundleDiscounts && bundleMapId !== undefined ? {
|
|
929
|
+
custom_product_bundle_map_id: bundleMapId
|
|
930
|
+
} : {}),
|
|
781
931
|
surcharge_fee: surchargeFee,
|
|
782
932
|
relation_surcharge_ids: relationSurchargeIds,
|
|
783
933
|
product_discount_difference: productDiscountDifference
|
|
@@ -785,9 +935,28 @@ function formatSubmitBundleItems(bundle) {
|
|
|
785
935
|
};
|
|
786
936
|
});
|
|
787
937
|
}
|
|
938
|
+
|
|
939
|
+
/**
|
|
940
|
+
* 把 tempOrder product 打包成出站 submit payload。
|
|
941
|
+
*
|
|
942
|
+
* 价格字段语义(出站口径,v2 composite):
|
|
943
|
+
* - `selling_price`:**行 composite 券后单价**
|
|
944
|
+
* = `metadata.main_product_selling_price` + Σ(bundle_selling_price × num)。
|
|
945
|
+
* - `original_price`:**行 composite 券前单价**
|
|
946
|
+
* = `metadata.main_product_original_price` + Σ(bundle 原价 × num)。
|
|
947
|
+
* - `payment_price`:兼容后端的出站字段,行 composite 已减整单折扣均摊(无折扣时与 `selling_price` 同义)。
|
|
948
|
+
* - `metadata.source_product_price`:主商品/variant 基础价(不含 option、不含折扣),权威源。
|
|
949
|
+
* - `metadata.main_product_original_price`:含 option、不含折扣。
|
|
950
|
+
* - `metadata.main_product_selling_price`:含 option、含主商品折扣。
|
|
951
|
+
* - `metadata.price_schema_version`:schema 版本号(当前 = 2),用于跨端协商价格口径。
|
|
952
|
+
*
|
|
953
|
+
* 本函数不再改造价格字段形状,仅做字段/metadata 裁剪。
|
|
954
|
+
*/
|
|
788
955
|
function normalizeSubmitProduct(product) {
|
|
789
|
-
|
|
790
|
-
|
|
956
|
+
const {
|
|
957
|
+
unique_identification_number: _runtimeUid,
|
|
958
|
+
...submitProduct
|
|
959
|
+
} = product;
|
|
791
960
|
const {
|
|
792
961
|
num,
|
|
793
962
|
surcharge_fee: _productSurchargeFee,
|
|
@@ -798,54 +967,45 @@ function normalizeSubmitProduct(product) {
|
|
|
798
967
|
discount_per: _deprecatedDiscountPer,
|
|
799
968
|
...productRest
|
|
800
969
|
} = submitProduct;
|
|
801
|
-
delete productRest[`product_${
|
|
970
|
+
delete productRest[`product_${'option'}_item`];
|
|
802
971
|
const rawMetadata = submitProduct.metadata || {};
|
|
803
972
|
const bookingUid = rawMetadata.booking_uid;
|
|
973
|
+
// 兼容历史 BigSale 编辑链路:bundle_edit 曾被写入 metadata,
|
|
974
|
+
// 出站时需提升到商品顶层;套餐未编辑时也必须显式提交 0。
|
|
804
975
|
const hasProductBundle = Array.isArray(submitProduct.product_bundle) && submitProduct.product_bundle.length > 0;
|
|
805
|
-
const bundleEdit = submitProduct.bundle_edit ?? rawMetadata.bundle_edit ?? (hasProductBundle ? 0 :
|
|
976
|
+
const bundleEdit = submitProduct.bundle_edit ?? rawMetadata.bundle_edit ?? (hasProductBundle ? 0 : undefined);
|
|
806
977
|
const cleanMetadata = {};
|
|
807
978
|
if (rawMetadata.unique_identification_number) {
|
|
808
979
|
cleanMetadata.unique_identification_number = rawMetadata.unique_identification_number;
|
|
809
980
|
}
|
|
810
|
-
const priceMetaKeys = [
|
|
811
|
-
"main_product_original_price",
|
|
812
|
-
"main_product_selling_price",
|
|
813
|
-
"main_product_attached_bundle_selling_price",
|
|
814
|
-
"main_product_attached_bundle_payment_price",
|
|
815
|
-
"average_discount_amount_rate",
|
|
816
|
-
"source_product_price",
|
|
817
|
-
"main_product_attached_bundle_surcharge_fee",
|
|
818
|
-
"main_product_attached_bundle_tax_fee",
|
|
819
|
-
"surcharge_rounding_remainder",
|
|
820
|
-
"tax_fee_rounding_remainder",
|
|
821
|
-
"relation_surcharge_ids",
|
|
822
|
-
"discountable_flag",
|
|
823
|
-
"parent_unique_identification_number",
|
|
824
|
-
"product_add_schedule_time"
|
|
825
|
-
];
|
|
981
|
+
const priceMetaKeys = ['main_product_original_price', 'main_product_selling_price', 'main_product_attached_bundle_selling_price', 'main_product_attached_bundle_payment_price', 'average_discount_amount_rate', 'source_product_price', 'main_product_attached_bundle_surcharge_fee', 'main_product_attached_bundle_tax_fee', 'surcharge_rounding_remainder', 'tax_fee_rounding_remainder', 'relation_surcharge_ids', 'discountable_flag', 'parent_unique_identification_number', 'product_add_schedule_time'];
|
|
826
982
|
for (const key of priceMetaKeys) {
|
|
827
|
-
if (rawMetadata[key] !==
|
|
983
|
+
if (rawMetadata[key] !== undefined) {
|
|
828
984
|
cleanMetadata[key] = rawMetadata[key];
|
|
829
985
|
}
|
|
830
986
|
}
|
|
831
|
-
cleanMetadata.product_discount_difference = rawMetadata.product_discount_difference ??
|
|
987
|
+
cleanMetadata.product_discount_difference = rawMetadata.product_discount_difference ?? '';
|
|
832
988
|
if (rawMetadata.price_breakdown) {
|
|
833
989
|
cleanMetadata.price_breakdown = rawMetadata.price_breakdown;
|
|
834
990
|
}
|
|
835
|
-
if (rawMetadata.is_rule !==
|
|
991
|
+
if (rawMetadata.is_rule !== undefined) {
|
|
836
992
|
cleanMetadata.is_rule = rawMetadata.is_rule;
|
|
837
993
|
}
|
|
838
|
-
if (rawMetadata.holder_config !==
|
|
994
|
+
if (rawMetadata.holder_config !== undefined) {
|
|
839
995
|
cleanMetadata.holder_config = rawMetadata.holder_config;
|
|
840
996
|
}
|
|
841
997
|
const productSku = {
|
|
842
|
-
...submitProduct.product_sku && typeof submitProduct.product_sku ===
|
|
843
|
-
option: formatSubmitOptionItems(
|
|
998
|
+
...(submitProduct.product_sku && typeof submitProduct.product_sku === 'object' ? submitProduct.product_sku : {}),
|
|
999
|
+
option: formatSubmitOptionItems(submitProduct.product_sku?.option)
|
|
844
1000
|
};
|
|
845
1001
|
return {
|
|
846
1002
|
...productRest,
|
|
847
|
-
...bookingUid ? {
|
|
848
|
-
|
|
1003
|
+
...(bookingUid ? {
|
|
1004
|
+
booking_uid: bookingUid
|
|
1005
|
+
} : {}),
|
|
1006
|
+
...(bundleEdit !== undefined ? {
|
|
1007
|
+
bundle_edit: bundleEdit
|
|
1008
|
+
} : {}),
|
|
849
1009
|
product_quantity: toBundleNumber(num ?? submitProduct.product_quantity, 1),
|
|
850
1010
|
product_sku: productSku,
|
|
851
1011
|
discount_list: collectSubmitProductDiscountList(submitProduct),
|
|
@@ -856,90 +1016,98 @@ function normalizeSubmitProduct(product) {
|
|
|
856
1016
|
payment_price: submitProduct.payment_price ?? submitProduct.selling_price
|
|
857
1017
|
};
|
|
858
1018
|
}
|
|
859
|
-
|
|
860
|
-
"unique_identification_number",
|
|
861
|
-
"collect_pax",
|
|
862
|
-
"capacity",
|
|
863
|
-
"holder_id",
|
|
864
|
-
"resource_select_type",
|
|
865
|
-
"holder"
|
|
866
|
-
];
|
|
1019
|
+
const SUBMIT_BOOKING_METADATA_WHITELIST = ['unique_identification_number', 'collect_pax', 'capacity', 'holder_id', 'resource_select_type', 'holder'];
|
|
867
1020
|
function normalizeBookingIsAll(booking) {
|
|
868
|
-
return booking.is_all === true || booking.is_all === 1 || booking.is_all ===
|
|
1021
|
+
return booking.is_all === true || booking.is_all === 1 || booking.is_all === '1' || booking.is_all === 'true' ? 1 : 0;
|
|
869
1022
|
}
|
|
870
1023
|
function normalizeBookingSubType(booking) {
|
|
871
|
-
if (normalizeBookingIsAll(booking) === 1)
|
|
872
|
-
|
|
873
|
-
if (booking.sub_type !== void 0 && booking.sub_type !== null && booking.sub_type !== "") {
|
|
1024
|
+
if (normalizeBookingIsAll(booking) === 1) return 'days';
|
|
1025
|
+
if (booking.sub_type !== undefined && booking.sub_type !== null && booking.sub_type !== '') {
|
|
874
1026
|
return String(booking.sub_type);
|
|
875
1027
|
}
|
|
876
|
-
return
|
|
1028
|
+
return 'minutes';
|
|
877
1029
|
}
|
|
878
1030
|
function normalizeSubmitBooking(booking) {
|
|
879
1031
|
const rawMetadata = booking.metadata || {};
|
|
880
1032
|
const cleanMetadata = {};
|
|
881
1033
|
for (const key of SUBMIT_BOOKING_METADATA_WHITELIST) {
|
|
882
|
-
if (rawMetadata[key] !==
|
|
1034
|
+
if (rawMetadata[key] !== undefined) {
|
|
883
1035
|
cleanMetadata[key] = rawMetadata[key];
|
|
884
1036
|
}
|
|
885
1037
|
}
|
|
886
|
-
if (cleanMetadata.holder_id ===
|
|
887
|
-
cleanMetadata.holder_id = null;
|
|
1038
|
+
if (cleanMetadata.holder_id === undefined) cleanMetadata.holder_id = null;
|
|
888
1039
|
const bookingRecord = booking;
|
|
889
1040
|
const startDate = bookingRecord.start_date;
|
|
890
|
-
const shouldRestoreSelectDate = bookingRecord.select_date ===
|
|
891
|
-
const selectDateFromStartDate = typeof startDate ===
|
|
1041
|
+
const shouldRestoreSelectDate = bookingRecord.select_date === undefined || bookingRecord.select_date === null || bookingRecord.select_date === '';
|
|
1042
|
+
const selectDateFromStartDate = typeof startDate === 'string' ? startDate.split(/\s+/)[0] : startDate;
|
|
892
1043
|
return {
|
|
893
1044
|
...booking,
|
|
894
|
-
...shouldRestoreSelectDate && selectDateFromStartDate ? {
|
|
1045
|
+
...(shouldRestoreSelectDate && selectDateFromStartDate ? {
|
|
1046
|
+
select_date: selectDateFromStartDate
|
|
1047
|
+
} : {}),
|
|
895
1048
|
is_all: normalizeBookingIsAll(bookingRecord),
|
|
896
1049
|
sub_type: normalizeBookingSubType(bookingRecord),
|
|
897
1050
|
metadata: cleanMetadata
|
|
898
1051
|
};
|
|
899
1052
|
}
|
|
1053
|
+
const DEFAULT_TABLE_OCCUPANCY_DURATION = 20;
|
|
1054
|
+
function resolveTableOccupancyDuration(tempOrder) {
|
|
1055
|
+
const metadata = tempOrder.metadata || {};
|
|
1056
|
+
const candidates = [metadata.table_occupancy_duration, metadata.booking_duration, metadata.table_duration, metadata.duration, metadata.table_config?.occupancy_duration, metadata.tableConfig?.occupancy_duration, metadata.resource_config?.occupancy_duration, metadata.resourceConfig?.occupancy_duration];
|
|
1057
|
+
for (const value of candidates) {
|
|
1058
|
+
const duration = Number(value);
|
|
1059
|
+
if (Number.isFinite(duration) && duration > 0) {
|
|
1060
|
+
return Math.floor(duration);
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
return DEFAULT_TABLE_OCCUPANCY_DURATION;
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
/** 提交用人数:有限且为正则向下取整,否则为 1 */
|
|
900
1067
|
function normalizeSubmitCollectPaxValue(value) {
|
|
901
1068
|
const n = Number(value);
|
|
902
1069
|
return Number.isFinite(n) && n > 0 ? Math.floor(n) : 1;
|
|
903
1070
|
}
|
|
1071
|
+
|
|
1072
|
+
/** 从临时订单 metadata 解析合成 booking 的 collect_pax */
|
|
904
1073
|
function resolveSubmitCollectPax(tempOrder) {
|
|
905
|
-
|
|
906
|
-
return normalizeSubmitCollectPaxValue((_a = tempOrder.metadata) == null ? void 0 : _a.collect_pax);
|
|
1074
|
+
return normalizeSubmitCollectPaxValue(tempOrder.metadata?.collect_pax);
|
|
907
1075
|
}
|
|
908
1076
|
function createDefaultTempOrder(params) {
|
|
909
1077
|
return {
|
|
910
1078
|
order_id: null,
|
|
911
|
-
external_sale_number:
|
|
1079
|
+
external_sale_number: '',
|
|
912
1080
|
order_number: null,
|
|
913
1081
|
shop_order_number: null,
|
|
914
1082
|
shop_full_order_number: null,
|
|
915
|
-
type:
|
|
916
|
-
business_code:
|
|
917
|
-
platform:
|
|
918
|
-
sales_channel:
|
|
919
|
-
order_sales_channel:
|
|
920
|
-
status:
|
|
921
|
-
payment_status:
|
|
922
|
-
shipping_status:
|
|
1083
|
+
type: '',
|
|
1084
|
+
business_code: undefined,
|
|
1085
|
+
platform: 'h5',
|
|
1086
|
+
sales_channel: 'my_pisel',
|
|
1087
|
+
order_sales_channel: 'online_store',
|
|
1088
|
+
status: 'normal',
|
|
1089
|
+
payment_status: 'payment_processing',
|
|
1090
|
+
shipping_status: 'unfulfilled',
|
|
923
1091
|
customer_id: 0,
|
|
924
|
-
customer_name:
|
|
925
|
-
country_calling_code:
|
|
926
|
-
phone:
|
|
927
|
-
email:
|
|
1092
|
+
customer_name: '',
|
|
1093
|
+
country_calling_code: '',
|
|
1094
|
+
phone: '',
|
|
1095
|
+
email: '',
|
|
928
1096
|
customer: null,
|
|
929
1097
|
is_price_include_tax: 1,
|
|
930
|
-
tax_title:
|
|
931
|
-
tax_country_code:
|
|
932
|
-
currency_code:
|
|
933
|
-
currency_symbol:
|
|
934
|
-
currency_format:
|
|
1098
|
+
tax_title: '',
|
|
1099
|
+
tax_country_code: '',
|
|
1100
|
+
currency_code: '',
|
|
1101
|
+
currency_symbol: '',
|
|
1102
|
+
currency_format: 'symbol_first',
|
|
935
1103
|
is_deposit: 0,
|
|
936
|
-
deposit_amount:
|
|
937
|
-
shop_discount:
|
|
938
|
-
surcharge_fee:
|
|
939
|
-
note:
|
|
1104
|
+
deposit_amount: '0.00',
|
|
1105
|
+
shop_discount: '0.00',
|
|
1106
|
+
surcharge_fee: '0.00',
|
|
1107
|
+
note: '',
|
|
940
1108
|
schedule_date: params.now,
|
|
941
|
-
created_at:
|
|
942
|
-
request_unique_idempotency_token:
|
|
1109
|
+
created_at: undefined,
|
|
1110
|
+
request_unique_idempotency_token: '',
|
|
943
1111
|
vouchers: [],
|
|
944
1112
|
products: [],
|
|
945
1113
|
bookings: [],
|
|
@@ -956,11 +1124,10 @@ function createDefaultTempOrder(params) {
|
|
|
956
1124
|
};
|
|
957
1125
|
}
|
|
958
1126
|
function buildSubmitPayload(params) {
|
|
959
|
-
var _a;
|
|
960
1127
|
const {
|
|
961
1128
|
tempOrder,
|
|
962
1129
|
cacheId,
|
|
963
|
-
now =
|
|
1130
|
+
now = new Date(),
|
|
964
1131
|
platform,
|
|
965
1132
|
businessCode,
|
|
966
1133
|
channel,
|
|
@@ -969,9 +1136,9 @@ function buildSubmitPayload(params) {
|
|
|
969
1136
|
enhance
|
|
970
1137
|
} = params;
|
|
971
1138
|
const scheduleDate = tempOrder.schedule_date || tempOrder.created_at || formatDateTime(now);
|
|
972
|
-
const bookingUuid = (0,
|
|
1139
|
+
const bookingUuid = (0, _orderCollectionIdentity.createUuidV4)();
|
|
973
1140
|
const {
|
|
974
|
-
_extend,
|
|
1141
|
+
_extend: _extend,
|
|
975
1142
|
relation_id: _relationId,
|
|
976
1143
|
table_form_id: _tableFormId,
|
|
977
1144
|
resource_id: _resourceId,
|
|
@@ -993,69 +1160,72 @@ function buildSubmitPayload(params) {
|
|
|
993
1160
|
} = tempOrder;
|
|
994
1161
|
let submitType = type ?? tempOrder.type;
|
|
995
1162
|
if (!submitType) {
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
1163
|
+
// 如果外部没有传递 types,根据订单里当前是否有 bookings 来决定是 appointment_booking 还是 virtual
|
|
1164
|
+
if (tempOrder?.bookings?.length) {
|
|
1165
|
+
// 260807 如果 biz 是堂食,type 使用table-order
|
|
1166
|
+
if (businessCode === 'dine_in') {
|
|
1167
|
+
submitType = 'table-order';
|
|
999
1168
|
} else {
|
|
1000
|
-
submitType =
|
|
1169
|
+
submitType = 'appointment_booking';
|
|
1001
1170
|
}
|
|
1002
1171
|
} else {
|
|
1003
|
-
submitType =
|
|
1172
|
+
submitType = 'virtual';
|
|
1004
1173
|
}
|
|
1005
1174
|
}
|
|
1006
1175
|
const payload = {
|
|
1007
1176
|
...tempOrderRest,
|
|
1008
1177
|
customer_id: tempOrder.customer_id ?? 1,
|
|
1009
|
-
customer_name: tempOrder.customer_name ||
|
|
1010
|
-
country_calling_code: String(tempOrder.country_calling_code ??
|
|
1011
|
-
phone: String(tempOrder.phone ??
|
|
1012
|
-
email: String(tempOrder.email ??
|
|
1178
|
+
customer_name: tempOrder.customer_name || 'Walk-In',
|
|
1179
|
+
country_calling_code: String(tempOrder.country_calling_code ?? ''),
|
|
1180
|
+
phone: String(tempOrder.phone ?? ''),
|
|
1181
|
+
email: String(tempOrder.email ?? ''),
|
|
1013
1182
|
order_number: tempOrder.order_number ?? null,
|
|
1014
1183
|
shop_order_number: tempOrder.shop_order_number ?? null,
|
|
1015
1184
|
shop_full_order_number: tempOrder.shop_full_order_number ?? null,
|
|
1016
1185
|
platform: normalizeSubmitPlatform(platform),
|
|
1017
|
-
request_unique_idempotency_token:
|
|
1186
|
+
request_unique_idempotency_token: params?.request_unique_idempotency_token || tempOrder.request_unique_idempotency_token || `${tempOrder.external_sale_number}_${now.getTime()}`,
|
|
1018
1187
|
type: submitType,
|
|
1019
1188
|
business_code: businessCode ?? tempOrder.business_code,
|
|
1020
|
-
sales_channel: tempOrder.sales_channel ||
|
|
1021
|
-
order_sales_channel: channel ?? tempOrder.order_sales_channel ??
|
|
1022
|
-
status: tempOrder.status ||
|
|
1023
|
-
payment_status: tempOrder.payment_status ||
|
|
1189
|
+
sales_channel: tempOrder.sales_channel || 'my_pisel',
|
|
1190
|
+
order_sales_channel: channel ?? tempOrder.order_sales_channel ?? 'online_store',
|
|
1191
|
+
status: tempOrder.status || 'normal',
|
|
1192
|
+
payment_status: tempOrder.payment_status || 'payment_processing',
|
|
1024
1193
|
// shipping_status: tempOrder.shipping_status || 'unfulfilled',
|
|
1025
1194
|
is_price_include_tax: tempOrder.is_price_include_tax ?? 1,
|
|
1026
|
-
currency_format: tempOrder.currency_format ||
|
|
1195
|
+
currency_format: tempOrder.currency_format || 'symbol_first',
|
|
1027
1196
|
is_deposit: tempOrder.is_deposit ?? 0,
|
|
1028
|
-
deposit_amount: tempOrder.deposit_amount ||
|
|
1029
|
-
shop_discount: tempOrder.shop_discount ||
|
|
1030
|
-
surcharge_fee: tempOrder.surcharge_fee ||
|
|
1031
|
-
note: tempOrder.note ||
|
|
1032
|
-
delivery_type: tempOrder.delivery_type ||
|
|
1197
|
+
deposit_amount: tempOrder.deposit_amount || '0.00',
|
|
1198
|
+
shop_discount: tempOrder.shop_discount || '0.00',
|
|
1199
|
+
surcharge_fee: tempOrder.surcharge_fee || '0.00',
|
|
1200
|
+
note: tempOrder.note || '',
|
|
1201
|
+
delivery_type: tempOrder.delivery_type || 'nil',
|
|
1033
1202
|
schedule_date: scheduleDate,
|
|
1034
1203
|
// created_at: tempOrder.created_at || formatDateTime(now), 和后端协定这个字段先不提交到接口
|
|
1035
|
-
bookings: (tempOrder.bookings || []).filter(
|
|
1036
|
-
(booking) => Number(booking.parent_id) !== 0
|
|
1037
|
-
).map((booking) => normalizeSubmitBooking(booking)),
|
|
1204
|
+
bookings: (tempOrder.bookings || []).filter(booking => Number(booking.parent_id) !== 0).map(booking => normalizeSubmitBooking(booking)),
|
|
1038
1205
|
payments: tempOrder.payments || [],
|
|
1039
1206
|
relation_forms: tempOrder.relation_forms || [],
|
|
1040
1207
|
// contacts: tempOrder.contacts || [],
|
|
1041
1208
|
contacts_info: tempOrder.contacts_info && !Array.isArray(tempOrder.contacts_info) ? tempOrder.contacts_info : null,
|
|
1042
1209
|
// holder: tempOrder.holder || null,
|
|
1043
|
-
summary: summary || tempOrder.summary || (0,
|
|
1210
|
+
summary: summary || tempOrder.summary || (0, _utils2.createEmptySummary)(),
|
|
1044
1211
|
metadata: (() => {
|
|
1045
1212
|
const {
|
|
1046
1213
|
collect_pax: _collectPax,
|
|
1047
1214
|
table_occupancy_duration: _tableOccupancyDuration,
|
|
1048
1215
|
...rest
|
|
1049
1216
|
} = tempOrder.metadata || {};
|
|
1050
|
-
return {
|
|
1217
|
+
return {
|
|
1218
|
+
...rest
|
|
1219
|
+
};
|
|
1051
1220
|
})(),
|
|
1052
|
-
products: (tempOrder.products || []).map(
|
|
1053
|
-
(product) => normalizeSubmitProduct(product)
|
|
1054
|
-
)
|
|
1221
|
+
products: (tempOrder.products || []).map(product => normalizeSubmitProduct(product))
|
|
1055
1222
|
};
|
|
1056
|
-
if (!enhance)
|
|
1057
|
-
|
|
1058
|
-
|
|
1223
|
+
if (!enhance) return payload;
|
|
1224
|
+
const enhancedPayload = enhance(payload, {
|
|
1225
|
+
tempOrder,
|
|
1226
|
+
bookingUuid,
|
|
1227
|
+
now
|
|
1228
|
+
});
|
|
1059
1229
|
return {
|
|
1060
1230
|
...enhancedPayload,
|
|
1061
1231
|
summary: enhancedPayload.summary ?? payload.summary
|
|
@@ -1064,198 +1234,244 @@ function buildSubmitPayload(params) {
|
|
|
1064
1234
|
function mapPaymentItemToOrderPayment(paymentItem) {
|
|
1065
1235
|
const item = paymentItem;
|
|
1066
1236
|
const customPaymentId = item.custom_payment_id ?? item.id;
|
|
1067
|
-
const metadata = item.metadata && typeof item.metadata ===
|
|
1237
|
+
const metadata = item.metadata && typeof item.metadata === 'object' ? {
|
|
1238
|
+
...item.metadata
|
|
1239
|
+
} : {};
|
|
1068
1240
|
const paymentNumber = item.payment_number;
|
|
1069
|
-
const paymentMetadataKeys = [
|
|
1070
|
-
"rounding_rule",
|
|
1071
|
-
"shop_wallet_pass_id",
|
|
1072
|
-
"actual_paid_amount",
|
|
1073
|
-
"change_given_amount"
|
|
1074
|
-
];
|
|
1241
|
+
const paymentMetadataKeys = ['rounding_rule', 'shop_wallet_pass_id', 'actual_paid_amount', 'change_given_amount'];
|
|
1075
1242
|
for (const key of paymentMetadataKeys) {
|
|
1076
|
-
if (item[key] !==
|
|
1243
|
+
if (item[key] !== undefined && metadata[key] === undefined) {
|
|
1077
1244
|
metadata[key] = item[key];
|
|
1078
1245
|
}
|
|
1079
1246
|
}
|
|
1080
|
-
const timestamp = (0,
|
|
1247
|
+
const timestamp = (0, _dayjs.default)().format('YYYY-MM-DD HH:mm:ss');
|
|
1081
1248
|
const paymentTime = item.payment_time ?? timestamp;
|
|
1082
1249
|
const createdAt = item.created_at ?? timestamp;
|
|
1083
1250
|
return {
|
|
1084
|
-
...item.order_payment_id !==
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1251
|
+
...(item.order_payment_id !== undefined ? {
|
|
1252
|
+
order_payment_id: item.order_payment_id
|
|
1253
|
+
} : {}),
|
|
1254
|
+
...(paymentNumber !== undefined && paymentNumber !== null && paymentNumber !== '' ? {
|
|
1255
|
+
payment_number: String(paymentNumber)
|
|
1256
|
+
} : {}),
|
|
1257
|
+
amount: String(item.amount ?? '0.00'),
|
|
1258
|
+
code: String(item.code || ''),
|
|
1088
1259
|
custom_payment_id: Number(customPaymentId ?? 0),
|
|
1089
|
-
...item.custom_payment_type !==
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
...item.
|
|
1095
|
-
|
|
1260
|
+
...(item.custom_payment_type !== undefined ? {
|
|
1261
|
+
custom_payment_type: String(item.custom_payment_type)
|
|
1262
|
+
} : {}),
|
|
1263
|
+
name: String(item.name || ''),
|
|
1264
|
+
type: String(item.type || ''),
|
|
1265
|
+
...(item.voucher_id !== undefined ? {
|
|
1266
|
+
voucher_id: item.voucher_id
|
|
1267
|
+
} : {}),
|
|
1268
|
+
...(item.origin_amount !== undefined ? {
|
|
1269
|
+
origin_amount: String(item.origin_amount)
|
|
1270
|
+
} : {}),
|
|
1271
|
+
...(item.service_fee !== undefined ? {
|
|
1272
|
+
service_fee: String(item.service_fee)
|
|
1273
|
+
} : {}),
|
|
1274
|
+
...(item.status !== undefined ? {
|
|
1275
|
+
status: item.status
|
|
1276
|
+
} : {}),
|
|
1096
1277
|
payment_time: paymentTime,
|
|
1097
1278
|
created_at: createdAt,
|
|
1098
|
-
...item.wallet_pass_usage_unit !==
|
|
1099
|
-
|
|
1100
|
-
|
|
1279
|
+
...(item.wallet_pass_usage_unit !== undefined ? {
|
|
1280
|
+
wallet_pass_usage_unit: item.wallet_pass_usage_unit
|
|
1281
|
+
} : {}),
|
|
1282
|
+
...(item.wallet_pass_use_value !== undefined ? {
|
|
1283
|
+
wallet_pass_use_value: item.wallet_pass_use_value
|
|
1284
|
+
} : {}),
|
|
1285
|
+
...(item.fund_record && typeof item.fund_record === 'object' && !Array.isArray(item.fund_record) ? {
|
|
1286
|
+
fund_record: {
|
|
1287
|
+
...item.fund_record
|
|
1288
|
+
}
|
|
1289
|
+
} : {}),
|
|
1101
1290
|
metadata,
|
|
1102
|
-
...item.rounding_amount !==
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
...item.
|
|
1291
|
+
...(item.rounding_amount !== undefined ? {
|
|
1292
|
+
rounding_amount: String(item.rounding_amount)
|
|
1293
|
+
} : {}),
|
|
1294
|
+
...(item.service_charge !== undefined ? {
|
|
1295
|
+
service_charge: item.service_charge
|
|
1296
|
+
} : {}),
|
|
1297
|
+
...(item.order_payment_type !== undefined ? {
|
|
1298
|
+
order_payment_type: item.order_payment_type
|
|
1299
|
+
} : {}),
|
|
1300
|
+
...(item.updated_at !== undefined ? {
|
|
1301
|
+
updated_at: item.updated_at
|
|
1302
|
+
} : {})
|
|
1106
1303
|
};
|
|
1107
1304
|
}
|
|
1108
1305
|
function mapPaymentItemsToOrderPayments(paymentItems, options = {}) {
|
|
1109
|
-
if (!Array.isArray(paymentItems))
|
|
1110
|
-
|
|
1111
|
-
return paymentItems.filter((item) => options.includeVoided || item.status !== "voided").map((item) => mapPaymentItemToOrderPayment(item));
|
|
1306
|
+
if (!Array.isArray(paymentItems)) return [];
|
|
1307
|
+
return paymentItems.filter(item => options.includeVoided || item.status !== 'voided').map(item => mapPaymentItemToOrderPayment(item));
|
|
1112
1308
|
}
|
|
1309
|
+
|
|
1310
|
+
/**
|
|
1311
|
+
* 历史 V1 加餐结构映射器。
|
|
1312
|
+
*
|
|
1313
|
+
* @deprecated 标准 Sales checkout 已统一提交结构。
|
|
1314
|
+
* 本函数仅保留以兼容历史接入方,未来会移除。新代码请勿再调用。
|
|
1315
|
+
*/
|
|
1113
1316
|
function formatV1Product(products) {
|
|
1114
|
-
return products.map(
|
|
1115
|
-
var _a;
|
|
1317
|
+
return products.map(product => {
|
|
1116
1318
|
return {
|
|
1117
1319
|
bundle: product.product_bundle,
|
|
1118
1320
|
key: product.product_id,
|
|
1119
|
-
option:
|
|
1321
|
+
option: product.product_sku?.option || [],
|
|
1120
1322
|
product_id: product.product_id,
|
|
1121
1323
|
product_variant_id: product.product_variant_id,
|
|
1122
1324
|
num: product.product_quantity,
|
|
1123
|
-
note: String(product.note ??
|
|
1325
|
+
note: String(product.note ?? ''),
|
|
1124
1326
|
rowKey: product.product_id,
|
|
1125
1327
|
session: null,
|
|
1126
|
-
unique: (0,
|
|
1328
|
+
unique: (0, _orderCollectionIdentity.createUuidV4)()
|
|
1127
1329
|
};
|
|
1128
1330
|
});
|
|
1129
1331
|
}
|
|
1332
|
+
|
|
1333
|
+
/**
|
|
1334
|
+
* 判断 holder_id 是否已分配(非空)。
|
|
1335
|
+
*
|
|
1336
|
+
* @example
|
|
1337
|
+
* hasAssignedHolderId(12); // true
|
|
1338
|
+
* hasAssignedHolderId([]); // false
|
|
1339
|
+
*/
|
|
1130
1340
|
function hasAssignedHolderId(value) {
|
|
1131
|
-
if (value ===
|
|
1132
|
-
|
|
1133
|
-
if (Array.isArray(value))
|
|
1134
|
-
return value.length > 0;
|
|
1341
|
+
if (value === undefined || value === null || value === '') return false;
|
|
1342
|
+
if (Array.isArray(value)) return value.length > 0;
|
|
1135
1343
|
return true;
|
|
1136
1344
|
}
|
|
1345
|
+
|
|
1346
|
+
/**
|
|
1347
|
+
* 清空 tempOrder 购物车行上的 holder 分配(products / bookings / runtime origin)。
|
|
1348
|
+
* 移除或更换下单客户时调用,与 booking 页换客户清 holder 行为对齐。
|
|
1349
|
+
*
|
|
1350
|
+
* @example
|
|
1351
|
+
* clearTempOrderHolderAssignments(tempOrder);
|
|
1352
|
+
*/
|
|
1137
1353
|
function clearTempOrderHolderAssignments(tempOrder) {
|
|
1138
|
-
var _a;
|
|
1139
1354
|
let changed = false;
|
|
1140
|
-
const resetHolderField = (target, key =
|
|
1141
|
-
if (!hasAssignedHolderId(target[key]))
|
|
1142
|
-
return;
|
|
1355
|
+
const resetHolderField = (target, key = 'holder_id') => {
|
|
1356
|
+
if (!hasAssignedHolderId(target[key])) return;
|
|
1143
1357
|
target[key] = null;
|
|
1144
1358
|
changed = true;
|
|
1145
1359
|
};
|
|
1146
1360
|
for (const product of tempOrder.products || []) {
|
|
1147
|
-
if (product.metadata && typeof product.metadata ===
|
|
1361
|
+
if (product.metadata && typeof product.metadata === 'object') {
|
|
1148
1362
|
resetHolderField(product.metadata);
|
|
1149
1363
|
}
|
|
1150
1364
|
}
|
|
1151
1365
|
for (const booking of tempOrder.bookings || []) {
|
|
1152
1366
|
const bookingRecord = booking;
|
|
1153
|
-
if (booking.metadata && typeof booking.metadata ===
|
|
1367
|
+
if (booking.metadata && typeof booking.metadata === 'object') {
|
|
1154
1368
|
resetHolderField(booking.metadata);
|
|
1155
1369
|
}
|
|
1156
|
-
if (bookingRecord.holder !==
|
|
1370
|
+
if (bookingRecord.holder !== undefined && bookingRecord.holder !== null) {
|
|
1157
1371
|
delete bookingRecord.holder;
|
|
1158
1372
|
changed = true;
|
|
1159
1373
|
}
|
|
1160
1374
|
}
|
|
1161
|
-
const productsByUid =
|
|
1162
|
-
if (productsByUid && typeof productsByUid ===
|
|
1375
|
+
const productsByUid = tempOrder._extend?.productsByUid;
|
|
1376
|
+
if (productsByUid && typeof productsByUid === 'object') {
|
|
1163
1377
|
for (const entry of Object.values(productsByUid)) {
|
|
1164
|
-
const origin = entry
|
|
1165
|
-
if (!origin || typeof origin !==
|
|
1166
|
-
|
|
1167
|
-
if (origin.metadata && typeof origin.metadata === "object") {
|
|
1378
|
+
const origin = entry?.origin;
|
|
1379
|
+
if (!origin || typeof origin !== 'object') continue;
|
|
1380
|
+
if (origin.metadata && typeof origin.metadata === 'object') {
|
|
1168
1381
|
resetHolderField(origin.metadata);
|
|
1169
1382
|
}
|
|
1170
|
-
if (origin._extend && typeof origin._extend ===
|
|
1383
|
+
if (origin._extend && typeof origin._extend === 'object') {
|
|
1171
1384
|
resetHolderField(origin._extend);
|
|
1172
1385
|
}
|
|
1173
1386
|
}
|
|
1174
1387
|
}
|
|
1175
1388
|
return changed;
|
|
1176
1389
|
}
|
|
1390
|
+
|
|
1391
|
+
/**
|
|
1392
|
+
* 读取购物车行的 stable uid(优先 metadata.unique_identification_number)。
|
|
1393
|
+
*
|
|
1394
|
+
* @example
|
|
1395
|
+
* getOrderProductLineUid({ metadata: { unique_identification_number: 'line-1' } }); // 'line-1'
|
|
1396
|
+
*/
|
|
1177
1397
|
function getOrderProductLineUid(product) {
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
const uid = ((_a = product.metadata) == null ? void 0 : _a.unique_identification_number) ?? product.unique_identification_number;
|
|
1182
|
-
if (uid === void 0 || uid === null || uid === "")
|
|
1183
|
-
return null;
|
|
1398
|
+
if (!product || typeof product !== 'object') return null;
|
|
1399
|
+
const uid = product.metadata?.unique_identification_number ?? product.unique_identification_number;
|
|
1400
|
+
if (uid === undefined || uid === null || uid === '') return null;
|
|
1184
1401
|
return String(uid);
|
|
1185
1402
|
}
|
|
1186
1403
|
function getRuntimeProductOrigin(tempOrder, product) {
|
|
1187
|
-
var _a, _b, _c, _d, _e, _f;
|
|
1188
1404
|
const uid = getOrderProductLineUid(product);
|
|
1189
|
-
if (uid &&
|
|
1405
|
+
if (uid && tempOrder?._extend?.productsByUid?.[uid]?.origin) {
|
|
1190
1406
|
return tempOrder._extend.productsByUid[uid].origin;
|
|
1191
1407
|
}
|
|
1192
|
-
const matchedProduct = (
|
|
1193
|
-
const matchedUid = matchedProduct ? getOrderProductLineUid(matchedProduct) :
|
|
1194
|
-
return matchedUid ?
|
|
1408
|
+
const matchedProduct = (tempOrder?.products || []).find(item => item === product || getOrderProductLineUid(item) === uid || String(item?.product_id ?? item?.id ?? '') === String(product?.product_id ?? product?.id ?? ''));
|
|
1409
|
+
const matchedUid = matchedProduct ? getOrderProductLineUid(matchedProduct) : '';
|
|
1410
|
+
return matchedUid ? tempOrder?._extend?.productsByUid?.[matchedUid]?.origin || null : null;
|
|
1195
1411
|
}
|
|
1196
1412
|
function isHolderConfigRequired(holderConfig) {
|
|
1197
|
-
if (!holderConfig || typeof holderConfig !==
|
|
1198
|
-
|
|
1199
|
-
if (holderConfig.status === "disable")
|
|
1200
|
-
return false;
|
|
1413
|
+
if (!holderConfig || typeof holderConfig !== 'object') return false;
|
|
1414
|
+
if (holderConfig.status === 'disable') return false;
|
|
1201
1415
|
return Number(holderConfig.required) === 1;
|
|
1202
1416
|
}
|
|
1203
1417
|
function productRequiresFormSubject(tempOrder, product) {
|
|
1204
|
-
|
|
1205
|
-
const _orderProduct = (_a = tempOrder == null ? void 0 : tempOrder.products) == null ? void 0 : _a.find((item) => {
|
|
1418
|
+
const _orderProduct = tempOrder?.products?.find(item => {
|
|
1206
1419
|
return item.metadata.unique_identification_number === product._id || item.product_id === product.id;
|
|
1207
1420
|
});
|
|
1208
1421
|
const runtimeOrigin = getRuntimeProductOrigin(tempOrder, product);
|
|
1209
|
-
return isHolderConfigRequired(
|
|
1422
|
+
return isHolderConfigRequired(_orderProduct?.metadata?.holder_config) || isHolderConfigRequired(runtimeOrigin?.holder_config) || isHolderConfigRequired(product?.holder_config);
|
|
1210
1423
|
}
|
|
1211
1424
|
function resolveIsFormSubject(tempOrder, product) {
|
|
1212
|
-
|
|
1213
|
-
if (
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
return productRequiresFormSubject(tempOrder, product);
|
|
1217
|
-
return ((tempOrder == null ? void 0 : tempOrder.products) || []).some(
|
|
1218
|
-
(item) => productRequiresFormSubject(tempOrder, item)
|
|
1219
|
-
);
|
|
1425
|
+
// 旧版预约维度的 holder 类型仍然生效;新版则从当前商品 holder_config 判断。
|
|
1426
|
+
if (tempOrder?.holder?.type === 'form') return true;
|
|
1427
|
+
if (product) return productRequiresFormSubject(tempOrder, product);
|
|
1428
|
+
return (tempOrder?.products || []).some(item => productRequiresFormSubject(tempOrder, item));
|
|
1220
1429
|
}
|
|
1430
|
+
|
|
1431
|
+
/**
|
|
1432
|
+
* 判断展示字段是否为空(含 i18n 对象全空)。
|
|
1433
|
+
*
|
|
1434
|
+
* @example
|
|
1435
|
+
* isEmptyOrderProductDisplayValue(''); // true
|
|
1436
|
+
* isEmptyOrderProductDisplayValue({ auto: '桌台费' }); // false
|
|
1437
|
+
*/
|
|
1221
1438
|
function isEmptyOrderProductDisplayValue(value) {
|
|
1222
|
-
if (value ===
|
|
1223
|
-
|
|
1224
|
-
if (typeof value ===
|
|
1225
|
-
return value.trim() === "";
|
|
1226
|
-
if (typeof value === "object") {
|
|
1439
|
+
if (value === undefined || value === null) return true;
|
|
1440
|
+
if (typeof value === 'string') return value.trim() === '';
|
|
1441
|
+
if (typeof value === 'object') {
|
|
1227
1442
|
const record = value;
|
|
1228
|
-
return !Object.values(record).some(
|
|
1229
|
-
(item) => typeof item === "string" && item.trim() !== ""
|
|
1230
|
-
);
|
|
1443
|
+
return !Object.values(record).some(item => typeof item === 'string' && item.trim() !== '');
|
|
1231
1444
|
}
|
|
1232
1445
|
return false;
|
|
1233
1446
|
}
|
|
1447
|
+
|
|
1448
|
+
/**
|
|
1449
|
+
* calcDiscount / applyDiscount 回写时 Rules 往往不带 product_title 等展示字段;
|
|
1450
|
+
* 用旧行补齐,避免编辑态 hydrate 后标题被冲掉。
|
|
1451
|
+
*
|
|
1452
|
+
* @example
|
|
1453
|
+
* mergeOrderProductDisplayFields(
|
|
1454
|
+
* { product_title: { auto: '桌台费' }, metadata: { unique_identification_number: 'u1' } },
|
|
1455
|
+
* { selling_price: '10.00', metadata: { unique_identification_number: 'u1' } },
|
|
1456
|
+
* );
|
|
1457
|
+
*/
|
|
1234
1458
|
function mergeOrderProductDisplayFields(previous, next) {
|
|
1235
|
-
const merged = {
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
"cover",
|
|
1241
|
-
"product_cover",
|
|
1242
|
-
"variant_title",
|
|
1243
|
-
"product_sku",
|
|
1244
|
-
"payment_price"
|
|
1245
|
-
];
|
|
1246
|
-
displayFields.forEach((field) => {
|
|
1459
|
+
const merged = {
|
|
1460
|
+
...next
|
|
1461
|
+
};
|
|
1462
|
+
const displayFields = ['product_title', 'product_name', 'product_cover', 'cover', 'product_cover', 'variant_title', 'product_sku', 'payment_price'];
|
|
1463
|
+
displayFields.forEach(field => {
|
|
1247
1464
|
if (isEmptyOrderProductDisplayValue(merged[field]) && !isEmptyOrderProductDisplayValue(previous[field])) {
|
|
1248
1465
|
merged[field] = previous[field];
|
|
1249
1466
|
}
|
|
1250
1467
|
});
|
|
1251
1468
|
if (previous.metadata || next.metadata) {
|
|
1252
1469
|
merged.metadata = {
|
|
1253
|
-
...previous.metadata || {},
|
|
1254
|
-
...next.metadata || {}
|
|
1470
|
+
...(previous.metadata || {}),
|
|
1471
|
+
...(next.metadata || {})
|
|
1255
1472
|
};
|
|
1256
|
-
[
|
|
1257
|
-
|
|
1258
|
-
if (isEmptyOrderProductDisplayValue(merged.metadata[field]) && !isEmptyOrderProductDisplayValue((_a = previous.metadata) == null ? void 0 : _a[field])) {
|
|
1473
|
+
['product_title', 'product_name'].forEach(field => {
|
|
1474
|
+
if (isEmptyOrderProductDisplayValue(merged.metadata[field]) && !isEmptyOrderProductDisplayValue(previous.metadata?.[field])) {
|
|
1259
1475
|
merged.metadata[field] = previous.metadata[field];
|
|
1260
1476
|
}
|
|
1261
1477
|
});
|
|
@@ -1265,8 +1481,15 @@ function mergeOrderProductDisplayFields(previous, next) {
|
|
|
1265
1481
|
}
|
|
1266
1482
|
return merged;
|
|
1267
1483
|
}
|
|
1484
|
+
|
|
1485
|
+
/**
|
|
1486
|
+
* 按 uid 索引 tempOrder.products,供 applyDiscount 合并展示字段。
|
|
1487
|
+
*
|
|
1488
|
+
* @example
|
|
1489
|
+
* indexOrderProductsByUid([{ metadata: { unique_identification_number: 'u1' } }]);
|
|
1490
|
+
*/
|
|
1268
1491
|
function indexOrderProductsByUid(products) {
|
|
1269
|
-
const map =
|
|
1492
|
+
const map = new Map();
|
|
1270
1493
|
(products || []).forEach((product, index) => {
|
|
1271
1494
|
const uid = getOrderProductLineUid(product);
|
|
1272
1495
|
if (uid) {
|
|
@@ -1276,60 +1499,4 @@ function indexOrderProductsByUid(products) {
|
|
|
1276
1499
|
map.set(`__index__:${index}`, product);
|
|
1277
1500
|
});
|
|
1278
1501
|
return map;
|
|
1279
|
-
}
|
|
1280
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
1281
|
-
0 && (module.exports = {
|
|
1282
|
-
buildManualProductDiscountItem,
|
|
1283
|
-
buildSubmitPayload,
|
|
1284
|
-
calculateOrderProductsDeposit,
|
|
1285
|
-
clearTempOrderHolderAssignments,
|
|
1286
|
-
composeLinePrice,
|
|
1287
|
-
createDefaultOrderRulesHooks,
|
|
1288
|
-
createDefaultTempOrder,
|
|
1289
|
-
createEmptySummary,
|
|
1290
|
-
createUuidV4,
|
|
1291
|
-
ensureCartItemOriginHolder,
|
|
1292
|
-
ensureManualProductDiscountList,
|
|
1293
|
-
ensureProductSku,
|
|
1294
|
-
findManualProductDiscountItem,
|
|
1295
|
-
formatDateTime,
|
|
1296
|
-
formatV1Product,
|
|
1297
|
-
generateDuration,
|
|
1298
|
-
getAllDiscountList,
|
|
1299
|
-
getBundleSellingMagnitude,
|
|
1300
|
-
getBundleSignedUnit,
|
|
1301
|
-
getOrderProductLineUid,
|
|
1302
|
-
getProductSkuOptions,
|
|
1303
|
-
getRuntimeProductOrigin,
|
|
1304
|
-
hasAssignedHolderId,
|
|
1305
|
-
indexOrderProductsByUid,
|
|
1306
|
-
isEmptyOrderProductDisplayValue,
|
|
1307
|
-
isHolderConfigRequired,
|
|
1308
|
-
isMarkdownBundle,
|
|
1309
|
-
isTempOrder,
|
|
1310
|
-
mapPaymentItemToOrderPayment,
|
|
1311
|
-
mapPaymentItemsToOrderPayments,
|
|
1312
|
-
mergeManualProductDiscountIntoList,
|
|
1313
|
-
mergeOrderProductDisplayFields,
|
|
1314
|
-
mergeRelationForms,
|
|
1315
|
-
normalizeBookingIsAll,
|
|
1316
|
-
normalizeBookingSubType,
|
|
1317
|
-
normalizeOrderProductDiscountList,
|
|
1318
|
-
normalizeProductSkuOptions,
|
|
1319
|
-
normalizeSubmitBooking,
|
|
1320
|
-
normalizeSubmitCollectPaxValue,
|
|
1321
|
-
productRequiresFormSubject,
|
|
1322
|
-
resolveEffectivePerUnitDiscount,
|
|
1323
|
-
resolveIsFormSubject,
|
|
1324
|
-
resolveManualDiscountMessage,
|
|
1325
|
-
resolveManualDiscountOriginTotal,
|
|
1326
|
-
resolveManualDiscountReasonFromSources,
|
|
1327
|
-
resolveManualOverrideLineOriginalPrice,
|
|
1328
|
-
resolveRulesManualDiscountFlag,
|
|
1329
|
-
resolveSafeProductNum,
|
|
1330
|
-
resolveSubmitCollectPax,
|
|
1331
|
-
shouldBuildManualProductDiscount,
|
|
1332
|
-
stripManualProductDiscountItems,
|
|
1333
|
-
sumOptionUnitPrice,
|
|
1334
|
-
syncManualProductDiscountProductNum
|
|
1335
|
-
});
|
|
1502
|
+
}
|