@pisell/pisellos 0.0.567 → 0.0.568
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/index.js +6 -9
- package/dist/model/strategy/adapter/walletPass/evaluator.js +0 -2
- package/dist/model/strategy/adapter/walletPass/example.js +3 -26
- package/dist/model/strategy/adapter/walletPass/utils.js +0 -3
- 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 +1 -4
- package/dist/modules/OpenData/index.js +0 -2
- package/dist/modules/Order/index.d.ts +1 -1
- package/dist/modules/Order/index.js +14 -41
- package/dist/modules/Payment/index.js +142 -270
- package/dist/modules/Payment/walletpass.js +4 -5
- package/dist/modules/Rules/index.js +0 -7
- 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 +88 -121
- package/dist/server/modules/menu/index.js +32 -41
- package/dist/server/modules/products/index.js +29 -49
- 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 +32 -40
- package/dist/server/utils/product.js +0 -1
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/BookingByStep/index.js +7 -59
- package/dist/solution/BookingByStep/utils/capacity.js +1 -11
- package/dist/solution/BookingByStep/utils/resources.js +1 -3
- package/dist/solution/BookingByStep/utils/timeslots.js +2 -43
- package/dist/solution/BookingTicket/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.js +5 -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 -246
- 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.d.ts +5 -0
- package/dist/solution/VenueBooking/index.js +364 -327
- package/dist/utils/task.js +15 -18
- package/dist/utils/watch.js +0 -1
- package/lib/apis/picoding.js +2 -0
- package/lib/core/index.js +130 -131
- package/lib/effects/index.js +46 -57
- package/lib/index.js +92 -53
- package/lib/model/index.js +14 -21
- package/lib/model/strategy/adapter/dataVariant/adapter.js +38 -50
- package/lib/model/strategy/adapter/dataVariant/evaluator.js +162 -236
- package/lib/model/strategy/adapter/dataVariant/examples.js +229 -237
- package/lib/model/strategy/adapter/dataVariant/index.js +39 -34
- package/lib/model/strategy/adapter/dataVariant/type.js +57 -28
- package/lib/model/strategy/adapter/index.js +100 -64
- package/lib/model/strategy/adapter/itemRule/adapter.js +156 -144
- package/lib/model/strategy/adapter/itemRule/evaluator.js +36 -48
- package/lib/model/strategy/adapter/itemRule/examples.js +295 -225
- package/lib/model/strategy/adapter/itemRule/index.js +83 -57
- package/lib/model/strategy/adapter/itemRule/type.js +97 -36
- package/lib/model/strategy/adapter/promotion/adapter.js +84 -63
- package/lib/model/strategy/adapter/promotion/evaluator.js +381 -231
- package/lib/model/strategy/adapter/promotion/examples.js +139 -159
- package/lib/model/strategy/adapter/promotion/index.js +1 -49
- package/lib/model/strategy/adapter/promotion/type.js +199 -35
- package/lib/model/strategy/adapter/type.js +4 -16
- package/lib/model/strategy/adapter/walletPass/evaluator.js +180 -152
- package/lib/model/strategy/adapter/walletPass/example.js +217 -190
- package/lib/model/strategy/adapter/walletPass/index.js +75 -51
- package/lib/model/strategy/adapter/walletPass/locales.js +36 -58
- package/lib/model/strategy/adapter/walletPass/type.js +4 -16
- package/lib/model/strategy/adapter/walletPass/utils.js +652 -402
- package/lib/model/strategy/engine.js +270 -168
- package/lib/model/strategy/index.js +49 -34
- package/lib/model/strategy/strategy-example.js +243 -239
- package/lib/model/strategy/type.js +100 -40
- package/lib/modules/Account/index.js +39 -53
- package/lib/modules/Account/types.js +20 -33
- package/lib/modules/AccountList/index.js +116 -154
- package/lib/modules/AccountList/types.js +30 -31
- package/lib/modules/AccountList/utils.js +18 -30
- package/lib/modules/BaseModule.js +22 -45
- 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 +306 -241
- package/lib/modules/Cart/utils/cartRelationForms.js +29 -35
- package/lib/modules/Cart/utils/cartResource.js +72 -78
- package/lib/modules/Cart/utils/changePrice.js +26 -62
- package/lib/modules/Cart/utils/index.js +106 -48
- package/lib/modules/Customer/constants.js +13 -34
- package/lib/modules/Customer/index.js +216 -153
- 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 +117 -113
- 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 +63 -74
- 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 +332 -320
- package/lib/modules/Order/types.js +24 -33
- package/lib/modules/Order/utils.js +350 -284
- 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 +566 -432
- package/lib/modules/Payment/mx51.js +1 -0
- package/lib/modules/Payment/types.js +216 -107
- package/lib/modules/Payment/utils.js +50 -47
- package/lib/modules/Payment/walletpass.js +221 -203
- 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 +111 -110
- package/lib/modules/ProductList/types.js +9 -31
- package/lib/modules/Quotation/index.js +60 -82
- 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/Rules/index.js +1172 -872
- package/lib/modules/Rules/types.js +17 -40
- package/lib/modules/SalesSummary/index.js +59 -68
- package/lib/modules/SalesSummary/types.js +4 -16
- package/lib/modules/SalesSummary/utils.js +176 -193
- 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 -167
- package/lib/modules/Schedule/index.js +97 -107
- 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 -70
- package/lib/modules/Summary/types.js +4 -16
- package/lib/modules/Summary/utils.js +782 -429
- package/lib/modules/index.js +212 -57
- 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 +882 -623
- package/lib/server/modules/index.js +85 -59
- package/lib/server/modules/menu/index.js +146 -122
- package/lib/server/modules/menu/types.js +18 -31
- package/lib/server/modules/order/index.js +195 -231
- package/lib/server/modules/order/types.js +107 -32
- package/lib/server/modules/order/utils/filterBookings.js +174 -140
- package/lib/server/modules/order/utils/filterOrders.js +89 -60
- package/lib/server/modules/products/index.js +430 -335
- package/lib/server/modules/products/types.js +41 -34
- package/lib/server/modules/quotation/index.js +76 -77
- package/lib/server/modules/quotation/types.js +21 -31
- package/lib/server/modules/resource/index.js +216 -187
- package/lib/server/modules/resource/types.js +42 -33
- package/lib/server/modules/schedule/index.js +134 -119
- 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/time.js +40 -49
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/BookingByStep/index.js +1530 -1343
- package/lib/solution/BookingByStep/types.js +40 -99
- package/lib/solution/BookingByStep/utils/capacity.js +192 -160
- package/lib/solution/BookingByStep/utils/products.js +42 -52
- package/lib/solution/BookingByStep/utils/resources.js +527 -330
- package/lib/solution/BookingByStep/utils/stock.js +65 -44
- package/lib/solution/BookingByStep/utils/timeslots.js +129 -131
- package/lib/solution/BookingTicket/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.js +147 -122
- package/lib/solution/BookingTicket/types.js +38 -64
- package/lib/solution/BookingTicket/utils/scan/cloudSearch.js +64 -80
- package/lib/solution/BookingTicket/utils/scan/handleScan.js +82 -80
- package/lib/solution/BookingTicket/utils/scan/index.js +90 -94
- package/lib/solution/BookingTicket/utils/scan/scanCache.js +90 -43
- 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 +227 -158
- 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 +218 -200
- package/lib/solution/Sales/types.js +27 -33
- package/lib/solution/ScanOrder/index.js +803 -840
- package/lib/solution/ScanOrder/types.js +34 -34
- package/lib/solution/ScanOrder/utils.js +372 -331
- package/lib/solution/ShopDiscount/index.js +230 -236
- package/lib/solution/ShopDiscount/types.js +15 -37
- package/lib/solution/ShopDiscount/utils.js +309 -172
- package/lib/solution/VenueBooking/index.d.ts +5 -0
- package/lib/solution/VenueBooking/index.js +886 -929
- package/lib/solution/VenueBooking/types.js +20 -40
- package/lib/solution/VenueBooking/utils/dateSummary.js +22 -54
- package/lib/solution/VenueBooking/utils/resource.js +31 -54
- package/lib/solution/VenueBooking/utils/slotMerge.js +88 -106
- package/lib/solution/VenueBooking/utils/smartPricing.js +112 -100
- package/lib/solution/VenueBooking/utils/timeSlot.js +133 -132
- package/lib/solution/VenueBooking/utils.js +130 -67
- package/lib/solution/index.js +102 -37
- package/lib/store/createStore.js +32 -29
- package/lib/types/index.js +4 -16
- package/lib/utils/task.js +36 -36
- package/lib/utils/watch.js +81 -47
- package/package.json +2 -1
|
@@ -1,76 +1,51 @@
|
|
|
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 __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
1
|
+
"use strict";
|
|
29
2
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
__export(VenueBooking_exports, {
|
|
33
|
-
VenueBookingImpl: () => VenueBookingImpl
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
34
5
|
});
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
var
|
|
40
|
-
var
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
var
|
|
53
|
-
var
|
|
54
|
-
var
|
|
55
|
-
var
|
|
56
|
-
var
|
|
57
|
-
var
|
|
58
|
-
var
|
|
59
|
-
var
|
|
60
|
-
|
|
61
|
-
var
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
6
|
+
var _exportNames = {
|
|
7
|
+
VenueBookingImpl: true
|
|
8
|
+
};
|
|
9
|
+
exports.VenueBookingImpl = void 0;
|
|
10
|
+
var _BaseModule = require("../../modules/BaseModule");
|
|
11
|
+
var _types = require("./types");
|
|
12
|
+
Object.keys(_types).forEach(function (key) {
|
|
13
|
+
if (key === "default" || key === "__esModule") return;
|
|
14
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
15
|
+
if (key in exports && exports[key] === _types[key]) return;
|
|
16
|
+
Object.defineProperty(exports, key, {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
get: function () {
|
|
19
|
+
return _types[key];
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
var _utils = require("./utils");
|
|
24
|
+
var _types2 = require("../BookingByStep/types");
|
|
25
|
+
var _ProductList = require("../../modules/ProductList");
|
|
26
|
+
var _Date = require("../../modules/Date");
|
|
27
|
+
var _Schedule = require("../../modules/Schedule");
|
|
28
|
+
var _utils2 = require("../../modules/Schedule/utils");
|
|
29
|
+
var _Quotation = require("../../modules/Quotation");
|
|
30
|
+
var _OpenData = require("../../modules/OpenData");
|
|
31
|
+
var _types3 = require("../../modules/Account/types");
|
|
32
|
+
var _dayjs = _interopRequireDefault(require("dayjs"));
|
|
33
|
+
var _itemRule = require("../../model/strategy/adapter/itemRule");
|
|
34
|
+
var _resource = require("./utils/resource");
|
|
35
|
+
var _timeSlot = require("./utils/timeSlot");
|
|
36
|
+
var _dateSummary = require("./utils/dateSummary");
|
|
37
|
+
var _slotMerge = require("./utils/slotMerge");
|
|
38
|
+
var _smartPricing = require("./utils/smartPricing");
|
|
39
|
+
var _utils3 = require("../../modules/Order/utils");
|
|
40
|
+
var _Order = require("../../modules/Order");
|
|
41
|
+
var _types4 = require("../RegisterAndLogin/types");
|
|
42
|
+
var _decimal = _interopRequireDefault(require("decimal.js"));
|
|
43
|
+
var _Holder = require("../../modules/Holder");
|
|
44
|
+
var _utils4 = require("../../modules/Holder/utils");
|
|
45
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
46
|
+
const OPEN_DATA_SECTION_CODES = ['basic', 'fulfillment', 'reservation', 'sale', 'menu', 'availability', 'workflow', 'checkout'];
|
|
71
47
|
function cloneCustomDepositData(customDepositData) {
|
|
72
|
-
if (!customDepositData || typeof customDepositData !==
|
|
73
|
-
return void 0;
|
|
48
|
+
if (!customDepositData || typeof customDepositData !== 'object') return undefined;
|
|
74
49
|
return {
|
|
75
50
|
...customDepositData,
|
|
76
51
|
self_deposit_policy_ids: Array.isArray(customDepositData.self_deposit_policy_ids) ? [...customDepositData.self_deposit_policy_ids] : [],
|
|
@@ -78,73 +53,74 @@ function cloneCustomDepositData(customDepositData) {
|
|
|
78
53
|
deposit_policy_data: Array.isArray(customDepositData.deposit_policy_data) ? [...customDepositData.deposit_policy_data] : []
|
|
79
54
|
};
|
|
80
55
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
56
|
+
class VenueBookingImpl extends _BaseModule.BaseModule {
|
|
57
|
+
defaultName = 'venueBooking';
|
|
58
|
+
defaultVersion = '1.0.0';
|
|
59
|
+
isSolution = true;
|
|
60
|
+
initializeOptions = {};
|
|
61
|
+
store = {
|
|
62
|
+
entryContext: null,
|
|
63
|
+
status: 'idle',
|
|
64
|
+
flow: {},
|
|
65
|
+
error: null,
|
|
66
|
+
products: undefined,
|
|
67
|
+
rawResourceData: [],
|
|
68
|
+
slotConfig: {
|
|
69
|
+
..._types.DEFAULT_SLOT_CONFIG
|
|
70
|
+
},
|
|
71
|
+
itemRuleQuantityLimits: [],
|
|
72
|
+
cartValidation: {
|
|
73
|
+
passed: null,
|
|
74
|
+
failures: []
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
otherParams = {};
|
|
78
|
+
cacheId;
|
|
79
|
+
window;
|
|
80
|
+
request;
|
|
81
|
+
baseSlotConfig = {
|
|
82
|
+
..._types.DEFAULT_SLOT_CONFIG
|
|
83
|
+
};
|
|
84
|
+
itemRuleEvaluator = new _itemRule.ItemRuleEvaluator();
|
|
85
|
+
itemRuleConfigs = [];
|
|
86
|
+
itemRuleConfigsPromise = null;
|
|
87
|
+
itemRulePrefillApplied = false;
|
|
88
|
+
itemRuleRuntimeConfig = {};
|
|
89
|
+
resourceProductMap = new Map();
|
|
90
|
+
loginEffectDisposers = [];
|
|
91
|
+
customerLoginRefreshInFlight = null;
|
|
92
|
+
customerLoginRefreshIdInFlight = null;
|
|
93
|
+
/** 最近一次确认登录的客户;登录事件与 user 插件更新之间可能存在时序差。 */
|
|
94
|
+
smartPricingCustomerId;
|
|
95
|
+
loadAllProductsInFlight = null;
|
|
96
|
+
productsLoaded = false;
|
|
97
|
+
loadOpenDataConfigInFlight = null;
|
|
98
|
+
static OPEN_DATA_CACHE_TTL = 5 * 60 * 1000;
|
|
99
|
+
/** 按日期缓存 slot 智能定价 Map,避免同周重复 resolveProducts */
|
|
100
|
+
slotPriceMapCache = new Map();
|
|
101
|
+
/** loadProducts 后缓存的全量商品(venue + addon),供分段算价复用 */
|
|
102
|
+
smartPricingProductCatalog = [];
|
|
103
|
+
static PISELL1_LOGIN_SUCCESS = 'pisell1.login.success';
|
|
121
104
|
getLoggerContext() {
|
|
122
105
|
return {
|
|
123
106
|
cacheId: this.cacheId,
|
|
124
107
|
solutionName: this.name,
|
|
125
|
-
moduleName:
|
|
108
|
+
moduleName: 'venueBooking'
|
|
126
109
|
};
|
|
127
110
|
}
|
|
128
111
|
safeStringify(value) {
|
|
129
112
|
try {
|
|
130
113
|
return JSON.stringify(value);
|
|
131
114
|
} catch {
|
|
132
|
-
return
|
|
115
|
+
return undefined;
|
|
133
116
|
}
|
|
134
117
|
}
|
|
135
118
|
pickErrorMessage(error) {
|
|
136
|
-
|
|
137
|
-
const candidates = [
|
|
138
|
-
error.message,
|
|
139
|
-
(_a = error.data) == null ? void 0 : _a.message,
|
|
140
|
-
(_c = (_b = error.response) == null ? void 0 : _b.data) == null ? void 0 : _c.message,
|
|
141
|
-
(_d = error.error) == null ? void 0 : _d.message
|
|
142
|
-
];
|
|
119
|
+
const candidates = [error.message, error.data?.message, error.response?.data?.message, error.error?.message];
|
|
143
120
|
for (const candidate of candidates) {
|
|
144
|
-
if (typeof candidate ===
|
|
145
|
-
return candidate;
|
|
121
|
+
if (typeof candidate === 'string' && candidate.trim()) return candidate;
|
|
146
122
|
}
|
|
147
|
-
return
|
|
123
|
+
return undefined;
|
|
148
124
|
}
|
|
149
125
|
serializeError(error) {
|
|
150
126
|
if (error instanceof Error) {
|
|
@@ -154,15 +130,23 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
154
130
|
stack: error.stack
|
|
155
131
|
};
|
|
156
132
|
}
|
|
157
|
-
if (error && typeof error ===
|
|
133
|
+
if (error && typeof error === 'object') {
|
|
158
134
|
const raw = error;
|
|
159
135
|
const message = this.pickErrorMessage(raw) || this.safeStringify(raw) || String(error);
|
|
160
136
|
return {
|
|
161
|
-
...typeof raw.name ===
|
|
137
|
+
...(typeof raw.name === 'string' ? {
|
|
138
|
+
name: raw.name
|
|
139
|
+
} : {}),
|
|
162
140
|
message,
|
|
163
|
-
...
|
|
164
|
-
|
|
165
|
-
|
|
141
|
+
...('code' in raw ? {
|
|
142
|
+
code: raw.code
|
|
143
|
+
} : {}),
|
|
144
|
+
...('status' in raw ? {
|
|
145
|
+
status: raw.status
|
|
146
|
+
} : {}),
|
|
147
|
+
...(this.safeStringify(raw) ? {
|
|
148
|
+
raw: this.safeStringify(raw)
|
|
149
|
+
} : {})
|
|
166
150
|
};
|
|
167
151
|
}
|
|
168
152
|
return {
|
|
@@ -172,18 +156,19 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
172
156
|
async addVenueBookingLog(params) {
|
|
173
157
|
const payload = {
|
|
174
158
|
cacheId: this.cacheId,
|
|
175
|
-
...params.payload || {}
|
|
159
|
+
...(params.payload || {})
|
|
176
160
|
};
|
|
177
161
|
const extra = {
|
|
178
|
-
...params.extra || {}
|
|
162
|
+
...(params.extra || {})
|
|
179
163
|
};
|
|
180
164
|
const logger = this.store.scanOrderLogger;
|
|
181
165
|
if (!logger) {
|
|
182
|
-
if ((params.level ||
|
|
183
|
-
console.error(
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
166
|
+
if ((params.level || 'info') === 'error') {
|
|
167
|
+
console.error('[VenueBooking][log-fallback]', params.title, {
|
|
168
|
+
payload,
|
|
169
|
+
extra
|
|
170
|
+
});
|
|
171
|
+
} else {}
|
|
187
172
|
return;
|
|
188
173
|
}
|
|
189
174
|
await logger.addLog({
|
|
@@ -194,7 +179,7 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
194
179
|
}
|
|
195
180
|
logMethodStart(method, payload = {}) {
|
|
196
181
|
void this.addVenueBookingLog({
|
|
197
|
-
level:
|
|
182
|
+
level: 'info',
|
|
198
183
|
title: `[VenueBooking] ${method} start`,
|
|
199
184
|
payload: {
|
|
200
185
|
method,
|
|
@@ -204,7 +189,7 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
204
189
|
}
|
|
205
190
|
logMethodSuccess(method, payload = {}) {
|
|
206
191
|
void this.addVenueBookingLog({
|
|
207
|
-
level:
|
|
192
|
+
level: 'info',
|
|
208
193
|
title: `[VenueBooking] ${method} success`,
|
|
209
194
|
payload: {
|
|
210
195
|
method,
|
|
@@ -214,7 +199,7 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
214
199
|
}
|
|
215
200
|
logMethodError(method, error, payload = {}) {
|
|
216
201
|
void this.addVenueBookingLog({
|
|
217
|
-
level:
|
|
202
|
+
level: 'error',
|
|
218
203
|
title: `[VenueBooking] ${method} failed`,
|
|
219
204
|
payload: {
|
|
220
205
|
method,
|
|
@@ -227,72 +212,58 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
227
212
|
await this.addVenueBookingLog({
|
|
228
213
|
...params,
|
|
229
214
|
payload: {
|
|
230
|
-
source:
|
|
231
|
-
...params.payload || {}
|
|
215
|
+
source: 'ui-bridge',
|
|
216
|
+
...(params.payload || {})
|
|
232
217
|
}
|
|
233
218
|
});
|
|
234
219
|
}
|
|
220
|
+
constructor(name, version) {
|
|
221
|
+
super(name, version);
|
|
222
|
+
}
|
|
235
223
|
normalizeCustomerId(value) {
|
|
236
224
|
const customerId = Number(value);
|
|
237
|
-
if (!Number.isFinite(customerId) || customerId <= 0)
|
|
238
|
-
return null;
|
|
225
|
+
if (!Number.isFinite(customerId) || customerId <= 0) return null;
|
|
239
226
|
return customerId;
|
|
240
227
|
}
|
|
241
228
|
resolveCustomerIdFromLoginPayload(payload) {
|
|
242
|
-
|
|
243
|
-
const candidates = [
|
|
244
|
-
payload == null ? void 0 : payload.customerId,
|
|
245
|
-
payload == null ? void 0 : payload.customer_id,
|
|
246
|
-
payload == null ? void 0 : payload.id,
|
|
247
|
-
(_a = payload == null ? void 0 : payload.user) == null ? void 0 : _a.customerId,
|
|
248
|
-
(_b = payload == null ? void 0 : payload.user) == null ? void 0 : _b.customer_id,
|
|
249
|
-
(_c = payload == null ? void 0 : payload.user) == null ? void 0 : _c.id,
|
|
250
|
-
(_e = (_d = payload == null ? void 0 : payload.user) == null ? void 0 : _d._origin) == null ? void 0 : _e.customer_id,
|
|
251
|
-
(_f = payload == null ? void 0 : payload.account) == null ? void 0 : _f.customerId,
|
|
252
|
-
(_g = payload == null ? void 0 : payload.account) == null ? void 0 : _g.customer_id,
|
|
253
|
-
(_h = payload == null ? void 0 : payload.account) == null ? void 0 : _h.id,
|
|
254
|
-
(_i = payload == null ? void 0 : payload._origin) == null ? void 0 : _i.customer_id
|
|
255
|
-
];
|
|
229
|
+
const candidates = [payload?.customerId, payload?.customer_id, payload?.id, payload?.user?.customerId, payload?.user?.customer_id, payload?.user?.id, payload?.user?._origin?.customer_id, payload?.account?.customerId, payload?.account?.customer_id, payload?.account?.id, payload?._origin?.customer_id];
|
|
256
230
|
for (const candidate of candidates) {
|
|
257
231
|
const customerId = this.normalizeCustomerId(candidate);
|
|
258
|
-
if (customerId)
|
|
259
|
-
return customerId;
|
|
232
|
+
if (customerId) return customerId;
|
|
260
233
|
}
|
|
261
234
|
return null;
|
|
262
235
|
}
|
|
263
236
|
resolveHolderCustomerId() {
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
return Number(customer.id);
|
|
268
|
-
return void 0;
|
|
237
|
+
const customer = JSON.parse(this.window?.getLocalStorage?.('customer') || '{}');
|
|
238
|
+
if (customer?.id) return Number(customer.id);
|
|
239
|
+
return undefined;
|
|
269
240
|
}
|
|
241
|
+
|
|
270
242
|
/**
|
|
271
243
|
* 按商品 holder_config 预加载表单数据到 holderMap。
|
|
272
244
|
* appointment_booking 在加购时触发;venueBooking 在商品加载后预加载,避免 getHolderFormMap 为空。
|
|
273
245
|
*/
|
|
274
246
|
async preloadHolderForms(products) {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
return;
|
|
278
|
-
const seenFormIds = /* @__PURE__ */ new Set();
|
|
247
|
+
if (!this.store.holder || !products.length) return;
|
|
248
|
+
const seenFormIds = new Set();
|
|
279
249
|
for (const item of products) {
|
|
280
|
-
const holderConfig = (0,
|
|
281
|
-
if (!holderConfig)
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
if (seenFormIds.has(formId))
|
|
285
|
-
continue;
|
|
250
|
+
const holderConfig = (0, _utils4.getProductHolderConfig)(item?._origin?.product);
|
|
251
|
+
if (!holderConfig) continue;
|
|
252
|
+
const formId = (0, _utils4.getFormIdFromHolderConfig)(holderConfig);
|
|
253
|
+
if (seenFormIds.has(formId)) continue;
|
|
286
254
|
seenFormIds.add(formId);
|
|
287
255
|
try {
|
|
288
256
|
await this.store.holder.ensureFormByProduct({
|
|
289
|
-
product:
|
|
257
|
+
product: item?._origin?.product || {},
|
|
290
258
|
customer_id: this.resolveHolderCustomerId(),
|
|
291
|
-
shop_id:
|
|
259
|
+
shop_id: item?._origin?.product?.shop_id,
|
|
292
260
|
useCache: true
|
|
293
261
|
});
|
|
294
262
|
} catch (error) {
|
|
295
|
-
console.error(
|
|
263
|
+
console.error('[VenueBooking] 预加载 holder 表单失败', {
|
|
264
|
+
formId,
|
|
265
|
+
error
|
|
266
|
+
});
|
|
296
267
|
}
|
|
297
268
|
}
|
|
298
269
|
}
|
|
@@ -303,32 +274,30 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
303
274
|
this.loginEffectDisposers = [];
|
|
304
275
|
}
|
|
305
276
|
registerLoginEffect(event, callback) {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
if (!(effects == null ? void 0 : effects.on))
|
|
309
|
-
return;
|
|
277
|
+
const effects = this.core?.effects;
|
|
278
|
+
if (!effects?.on) return;
|
|
310
279
|
effects.on(event, callback);
|
|
311
280
|
this.loginEffectDisposers.push(() => {
|
|
312
|
-
if (typeof effects.off ===
|
|
281
|
+
if (typeof effects.off === 'function') {
|
|
313
282
|
effects.off(event, callback);
|
|
314
283
|
}
|
|
315
284
|
});
|
|
316
285
|
}
|
|
317
286
|
registerCustomerLoginListeners() {
|
|
318
287
|
this.clearLoginEffectListeners();
|
|
319
|
-
const createHandleLogin = () => async
|
|
288
|
+
const createHandleLogin = () => async payload => {
|
|
320
289
|
const customerId = this.resolveCustomerIdFromLoginPayload(payload);
|
|
321
|
-
if (!customerId)
|
|
322
|
-
|
|
323
|
-
|
|
290
|
+
if (!customerId) return;
|
|
291
|
+
await this.refreshOrderMarketingAfterLogin({
|
|
292
|
+
customerId
|
|
293
|
+
});
|
|
324
294
|
};
|
|
325
|
-
this.registerLoginEffect(
|
|
326
|
-
this.registerLoginEffect(
|
|
327
|
-
this.registerLoginEffect(
|
|
295
|
+
this.registerLoginEffect(VenueBookingImpl.PISELL1_LOGIN_SUCCESS, createHandleLogin());
|
|
296
|
+
this.registerLoginEffect(_types3.AccountHooks.OnLogin, createHandleLogin());
|
|
297
|
+
this.registerLoginEffect(_types4.RegisterAndLoginHooks.onLoginSuccess, createHandleLogin());
|
|
328
298
|
}
|
|
329
299
|
async refreshOrderMarketingAfterLogin(params) {
|
|
330
|
-
if (!this.store.order)
|
|
331
|
-
throw new Error("order 模块未初始化");
|
|
300
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
332
301
|
if (this.customerLoginRefreshInFlight) {
|
|
333
302
|
if (this.customerLoginRefreshIdInFlight === params.customerId) {
|
|
334
303
|
await this.customerLoginRefreshInFlight;
|
|
@@ -338,13 +307,14 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
338
307
|
}
|
|
339
308
|
this.customerLoginRefreshIdInFlight = params.customerId;
|
|
340
309
|
const refreshTask = (async () => {
|
|
341
|
-
|
|
310
|
+
// 用户插件可能晚于登录 effect 更新;以已确认的登录 payload 作为本次及后续网格算价的身份来源。
|
|
342
311
|
this.smartPricingCustomerId = params.customerId;
|
|
343
312
|
await this.store.order.loadDiscountConfig({
|
|
344
313
|
customerId: params.customerId
|
|
345
314
|
});
|
|
346
315
|
this.clearSlotPriceMapCache();
|
|
347
316
|
this.recalculateOrderPricesFromSmartPricing();
|
|
317
|
+
// 刷新 holder 表单数据
|
|
348
318
|
if (this.store.holder) {
|
|
349
319
|
await this.store.holder.refreshAllFormRecords({
|
|
350
320
|
customer_id: params.customerId,
|
|
@@ -353,16 +323,18 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
353
323
|
}
|
|
354
324
|
if (this.store.quotation) {
|
|
355
325
|
await this.store.quotation.loadQuotations({
|
|
356
|
-
channel:
|
|
326
|
+
channel: this.otherParams?.channel
|
|
357
327
|
});
|
|
358
328
|
}
|
|
359
|
-
await this.store.order.recalculateSummary({
|
|
329
|
+
await this.store.order.recalculateSummary({
|
|
330
|
+
createIfMissing: true
|
|
331
|
+
});
|
|
360
332
|
this.store.order.persistTempOrder();
|
|
361
333
|
await this.refreshItemRuleQuantityLimits();
|
|
362
334
|
await this.refreshCartValidationPassed();
|
|
363
|
-
await
|
|
335
|
+
await this.core?.effects?.emit?.(_types.VenueBookingHooks.onSmartPricingUpdated, {
|
|
364
336
|
customerId: params.customerId
|
|
365
|
-
})
|
|
337
|
+
});
|
|
366
338
|
})();
|
|
367
339
|
this.customerLoginRefreshInFlight = refreshTask;
|
|
368
340
|
try {
|
|
@@ -377,24 +349,28 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
377
349
|
}
|
|
378
350
|
}
|
|
379
351
|
async initialize(core, options = {}) {
|
|
380
|
-
|
|
381
|
-
this.logMethodStart("initialize");
|
|
352
|
+
this.logMethodStart('initialize');
|
|
382
353
|
this.core = core;
|
|
383
354
|
this.initializeOptions = options || {};
|
|
384
|
-
this.store = {
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
355
|
+
this.store = {
|
|
356
|
+
...this.store,
|
|
357
|
+
...options.store
|
|
358
|
+
};
|
|
359
|
+
this.smartPricingCustomerId = undefined;
|
|
360
|
+
this.store.entryContext = options.otherParams?.entryContext || this.store.entryContext;
|
|
361
|
+
this.store.status = 'initializing';
|
|
388
362
|
this.store.error = null;
|
|
389
363
|
this.store.rawResourceData = [];
|
|
390
364
|
this.baseSlotConfig = {
|
|
391
|
-
...
|
|
392
|
-
...(
|
|
365
|
+
..._types.DEFAULT_SLOT_CONFIG,
|
|
366
|
+
...(options.otherParams?.slotConfig || {})
|
|
367
|
+
};
|
|
368
|
+
this.store.slotConfig = {
|
|
369
|
+
...this.baseSlotConfig
|
|
393
370
|
};
|
|
394
|
-
this.store.slotConfig = { ...this.baseSlotConfig };
|
|
395
371
|
this.otherParams = options.otherParams || {};
|
|
396
|
-
this.cacheId =
|
|
397
|
-
this.itemRuleRuntimeConfig =
|
|
372
|
+
this.cacheId = this.otherParams?.cacheId;
|
|
373
|
+
this.itemRuleRuntimeConfig = this.otherParams?.venueBookingItemRule || this.otherParams?.itemRule || {};
|
|
398
374
|
this.itemRuleConfigs = [];
|
|
399
375
|
this.itemRuleConfigsPromise = null;
|
|
400
376
|
this.itemRulePrefillApplied = false;
|
|
@@ -403,35 +379,31 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
403
379
|
passed: null,
|
|
404
380
|
failures: []
|
|
405
381
|
};
|
|
406
|
-
this.window = core.getPlugin(
|
|
407
|
-
this.request = core.getPlugin(
|
|
382
|
+
this.window = core.getPlugin('window');
|
|
383
|
+
this.request = core.getPlugin('request');
|
|
408
384
|
if (!this.window) {
|
|
409
|
-
this.logMethodError(
|
|
410
|
-
throw new Error(
|
|
385
|
+
this.logMethodError('initialize', 'window plugin missing');
|
|
386
|
+
throw new Error('venueBooking解决方案需要 window 插件支持');
|
|
411
387
|
}
|
|
412
388
|
if (!this.request) {
|
|
413
|
-
this.logMethodError(
|
|
414
|
-
throw new Error(
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
];
|
|
422
|
-
baseModules.forEach((step) => {
|
|
423
|
-
var _a2, _b2, _c2, _d2, _e2, _f2;
|
|
424
|
-
const targetModule = (0, import_types2.createModule)(step, this.name);
|
|
389
|
+
this.logMethodError('initialize', 'request plugin missing');
|
|
390
|
+
throw new Error('venueBooking解决方案需要 request 插件支持');
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// 注册基础模块(order, salesSummary, products, logger)
|
|
394
|
+
const baseModules = ['scanOrderLogger', 'products', 'order', 'salesSummary'];
|
|
395
|
+
baseModules.forEach(step => {
|
|
396
|
+
const targetModule = (0, _types2.createModule)(step, this.name);
|
|
425
397
|
if (targetModule) {
|
|
426
398
|
this.store[step] = targetModule;
|
|
427
|
-
const initialState = step ===
|
|
428
|
-
summary:
|
|
399
|
+
const initialState = step === 'salesSummary' ? {
|
|
400
|
+
summary: this.store.order?.getTempOrder()?.summary || (0, _utils.createEmptySummary)()
|
|
429
401
|
} : {};
|
|
430
|
-
const loggerProvider =
|
|
431
|
-
const loggerConfig =
|
|
402
|
+
const loggerProvider = this.otherParams?.loggerProvider || 'feishu';
|
|
403
|
+
const loggerConfig = this.otherParams?.loggerConfig || {
|
|
432
404
|
feishu: {
|
|
433
|
-
webhook:
|
|
434
|
-
errorHook:
|
|
405
|
+
webhook: 'https://open.feishu.cn/open-apis/bot/v2/hook/8f069b14-9d39-4728-8f78-b56f393bfde8',
|
|
406
|
+
errorHook: 'https://open.feishu.cn/open-apis/bot/v2/hook/bdefae5e-f233-4705-8688-946887d9543d'
|
|
435
407
|
}
|
|
436
408
|
};
|
|
437
409
|
this.core.registerModule(targetModule, {
|
|
@@ -439,8 +411,8 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
439
411
|
otherParams: {
|
|
440
412
|
...this.otherParams,
|
|
441
413
|
fatherModule: this.name,
|
|
442
|
-
openCache:
|
|
443
|
-
cacheId:
|
|
414
|
+
openCache: this.otherParams?.cacheId ? true : false,
|
|
415
|
+
cacheId: this.otherParams?.cacheId,
|
|
444
416
|
salesSummaryModuleName: `${this.name}_salesSummary`,
|
|
445
417
|
provider: loggerProvider,
|
|
446
418
|
providerConfig: loggerConfig,
|
|
@@ -448,11 +420,13 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
448
420
|
}
|
|
449
421
|
});
|
|
450
422
|
} else {
|
|
451
|
-
this.logMethodError(
|
|
423
|
+
this.logMethodError('initialize', `module ${step} missing`);
|
|
452
424
|
throw new Error(`模块 ${step} 不存在`);
|
|
453
425
|
}
|
|
454
426
|
});
|
|
455
|
-
|
|
427
|
+
|
|
428
|
+
// 注册场地商品列表模块
|
|
429
|
+
const venueProductsModule = new _ProductList.ProductList(`${this.name}_venueProducts`);
|
|
456
430
|
this.store.venueProducts = venueProductsModule;
|
|
457
431
|
this.core.registerModule(venueProductsModule, {
|
|
458
432
|
otherParams: {
|
|
@@ -460,7 +434,9 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
460
434
|
fatherModule: this.name
|
|
461
435
|
}
|
|
462
436
|
});
|
|
463
|
-
|
|
437
|
+
|
|
438
|
+
// 注册附加商品列表模块
|
|
439
|
+
const addonProductsModule = new _ProductList.ProductList(`${this.name}_addonProducts`);
|
|
464
440
|
this.store.addonProducts = addonProductsModule;
|
|
465
441
|
this.core.registerModule(addonProductsModule, {
|
|
466
442
|
otherParams: {
|
|
@@ -468,7 +444,9 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
468
444
|
fatherModule: this.name
|
|
469
445
|
}
|
|
470
446
|
});
|
|
471
|
-
|
|
447
|
+
|
|
448
|
+
// 注册日期模块
|
|
449
|
+
const dateModule = new _Date.DateModule(`${this.name}_date`);
|
|
472
450
|
this.store.date = dateModule;
|
|
473
451
|
this.core.registerModule(dateModule, {
|
|
474
452
|
otherParams: {
|
|
@@ -477,7 +455,9 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
477
455
|
cacheId: this.cacheId
|
|
478
456
|
}
|
|
479
457
|
});
|
|
480
|
-
|
|
458
|
+
|
|
459
|
+
// 注册日程模块
|
|
460
|
+
const scheduleModule = new _Schedule.ScheduleModule(`${this.name}_schedule`);
|
|
481
461
|
this.store.schedule = scheduleModule;
|
|
482
462
|
this.core.registerModule(scheduleModule, {
|
|
483
463
|
otherParams: {
|
|
@@ -485,7 +465,9 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
485
465
|
fatherModule: this.name
|
|
486
466
|
}
|
|
487
467
|
});
|
|
488
|
-
|
|
468
|
+
|
|
469
|
+
// 注册报价单模块
|
|
470
|
+
const quotationModule = new _Quotation.QuotationModule(`${this.name}_quotation`);
|
|
489
471
|
this.store.quotation = quotationModule;
|
|
490
472
|
this.core.registerModule(quotationModule, {
|
|
491
473
|
otherParams: {
|
|
@@ -493,108 +475,110 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
493
475
|
fatherModule: this.name
|
|
494
476
|
}
|
|
495
477
|
});
|
|
496
|
-
|
|
478
|
+
|
|
479
|
+
// 注册 OpenData 配置模块
|
|
480
|
+
const openDataModule = new _OpenData.OpenDataModule(`${this.name}_openData`);
|
|
497
481
|
this.store.openData = openDataModule;
|
|
498
482
|
this.core.registerModule(openDataModule, {
|
|
499
483
|
otherParams: {
|
|
500
484
|
...this.otherParams,
|
|
501
485
|
fatherModule: this.name,
|
|
502
|
-
openCache: !!
|
|
503
|
-
cacheId:
|
|
486
|
+
openCache: !!this.otherParams?.cacheId,
|
|
487
|
+
cacheId: this.otherParams?.cacheId
|
|
504
488
|
}
|
|
505
489
|
});
|
|
506
490
|
let holderCacheState;
|
|
507
|
-
if (
|
|
491
|
+
if (this.otherParams?.cacheId) {
|
|
508
492
|
const sessionData = this.window.sessionStorage.getItem(this.name);
|
|
509
493
|
if (sessionData) {
|
|
510
494
|
try {
|
|
511
495
|
const data = JSON.parse(sessionData);
|
|
512
|
-
holderCacheState =
|
|
496
|
+
holderCacheState = data[this.otherParams.cacheId]?.[`${this.name}_holder`];
|
|
513
497
|
} catch {
|
|
498
|
+
// ignore invalid session cache
|
|
514
499
|
}
|
|
515
500
|
}
|
|
516
501
|
}
|
|
517
|
-
const holderModule = new
|
|
502
|
+
const holderModule = new _Holder.HolderModule(`${this.name}_holder`);
|
|
518
503
|
this.store.holder = holderModule;
|
|
519
504
|
this.core.registerModule(holderModule, {
|
|
520
505
|
initialState: holderCacheState,
|
|
521
506
|
otherParams: {
|
|
522
507
|
...this.otherParams,
|
|
523
508
|
fatherModule: this.name,
|
|
524
|
-
openCache: !!
|
|
525
|
-
cacheId:
|
|
509
|
+
openCache: !!this.otherParams?.cacheId,
|
|
510
|
+
cacheId: this.otherParams?.cacheId
|
|
526
511
|
}
|
|
527
512
|
});
|
|
528
513
|
if (this.store.scanOrderLogger) {
|
|
529
514
|
this.store.scanOrderLogger.setContext(this.getLoggerContext());
|
|
530
515
|
}
|
|
531
516
|
this.registerCustomerLoginListeners();
|
|
532
|
-
console.log("[VenueBooking] 初始化开始");
|
|
533
517
|
try {
|
|
534
|
-
await
|
|
535
|
-
|
|
518
|
+
await this.store.order?.recalculateSummary({
|
|
519
|
+
createIfMissing: false
|
|
520
|
+
});
|
|
521
|
+
this.store.order?.persistTempOrder();
|
|
536
522
|
await this.loadRuntimeConfigs();
|
|
537
523
|
if (this.store.schedule) {
|
|
538
524
|
await this.store.schedule.loadAllSchedule();
|
|
539
525
|
}
|
|
540
526
|
await this.refreshItemRuleQuantityLimits();
|
|
541
|
-
this.store.status =
|
|
542
|
-
|
|
543
|
-
await this.core.effects.emit(import_types.VenueBookingHooks.onInited, {
|
|
527
|
+
this.store.status = 'ready';
|
|
528
|
+
await this.core.effects.emit(_types.VenueBookingHooks.onInited, {
|
|
544
529
|
status: this.store.status
|
|
545
530
|
});
|
|
546
|
-
this.logMethodSuccess(
|
|
531
|
+
this.logMethodSuccess('initialize', {
|
|
547
532
|
status: this.store.status
|
|
548
533
|
});
|
|
549
534
|
} catch (error) {
|
|
550
|
-
this.store.status =
|
|
551
|
-
this.store.error = error instanceof Error ? error.message :
|
|
552
|
-
console.error(
|
|
553
|
-
this.logMethodError(
|
|
535
|
+
this.store.status = 'error';
|
|
536
|
+
this.store.error = error instanceof Error ? error.message : '初始化失败';
|
|
537
|
+
console.error('[VenueBooking] 初始化失败', error);
|
|
538
|
+
this.logMethodError('initialize', error, {
|
|
554
539
|
status: this.store.status
|
|
555
540
|
});
|
|
556
541
|
throw error;
|
|
557
542
|
}
|
|
558
543
|
}
|
|
559
544
|
async destroy() {
|
|
560
|
-
this.logMethodStart(
|
|
545
|
+
this.logMethodStart('destroy');
|
|
561
546
|
this.clearLoginEffectListeners();
|
|
562
|
-
await this.core.effects.emit(
|
|
563
|
-
|
|
564
|
-
this.logMethodSuccess("destroy");
|
|
547
|
+
await this.core.effects.emit(_types.VenueBookingHooks.onDestroy, {});
|
|
548
|
+
this.logMethodSuccess('destroy');
|
|
565
549
|
}
|
|
566
550
|
async retryInit() {
|
|
567
|
-
this.logMethodStart(
|
|
568
|
-
|
|
569
|
-
await this.core.effects.emit(import_types.VenueBookingHooks.onRetryInit, {});
|
|
551
|
+
this.logMethodStart('retryInit');
|
|
552
|
+
await this.core.effects.emit(_types.VenueBookingHooks.onRetryInit, {});
|
|
570
553
|
try {
|
|
571
554
|
await this.initialize(this.core, this.initializeOptions);
|
|
572
|
-
this.logMethodSuccess(
|
|
555
|
+
this.logMethodSuccess('retryInit');
|
|
573
556
|
} catch (error) {
|
|
574
|
-
this.logMethodError(
|
|
557
|
+
this.logMethodError('retryInit', error);
|
|
575
558
|
throw error;
|
|
576
559
|
}
|
|
577
560
|
}
|
|
578
561
|
async refresh() {
|
|
579
|
-
this.logMethodStart(
|
|
580
|
-
console.log("[VenueBooking] refresh 调用");
|
|
562
|
+
this.logMethodStart('refresh');
|
|
581
563
|
try {
|
|
582
|
-
this.store.status =
|
|
564
|
+
this.store.status = 'initializing';
|
|
583
565
|
await this.loadRuntimeConfigs();
|
|
584
566
|
await this.refreshItemRuleQuantityLimits();
|
|
585
|
-
this.store.status =
|
|
586
|
-
await this.core.effects.emit(
|
|
567
|
+
this.store.status = 'ready';
|
|
568
|
+
await this.core.effects.emit(_types.VenueBookingHooks.onRefresh, {
|
|
587
569
|
status: this.store.status
|
|
588
570
|
});
|
|
589
|
-
this.logMethodSuccess(
|
|
571
|
+
this.logMethodSuccess('refresh', {
|
|
590
572
|
status: this.store.status
|
|
591
573
|
});
|
|
592
574
|
} catch (error) {
|
|
593
|
-
this.logMethodError(
|
|
575
|
+
this.logMethodError('refresh', error);
|
|
594
576
|
throw error;
|
|
595
577
|
}
|
|
596
578
|
}
|
|
579
|
+
|
|
597
580
|
// ─── 状态查询 ───
|
|
581
|
+
|
|
598
582
|
getStatus() {
|
|
599
583
|
return this.store.status;
|
|
600
584
|
}
|
|
@@ -605,62 +589,63 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
605
589
|
return this.store.itemRuleQuantityLimits || [];
|
|
606
590
|
}
|
|
607
591
|
getCartValidationPassed() {
|
|
608
|
-
|
|
609
|
-
return ((_a = this.store.cartValidation) == null ? void 0 : _a.passed) ?? null;
|
|
592
|
+
return this.store.cartValidation?.passed ?? null;
|
|
610
593
|
}
|
|
611
594
|
getCartValidation() {
|
|
612
|
-
return this.store.cartValidation || {
|
|
595
|
+
return this.store.cartValidation || {
|
|
596
|
+
passed: null,
|
|
597
|
+
failures: []
|
|
598
|
+
};
|
|
613
599
|
}
|
|
600
|
+
|
|
614
601
|
/** 清除 slot 价格分段缓存(商品重载 / 登录后 customerId 变化时调用) */
|
|
615
602
|
clearSlotPriceMapCache() {
|
|
616
603
|
this.slotPriceMapCache.clear();
|
|
617
604
|
}
|
|
605
|
+
|
|
618
606
|
/** 读取当前登录 customerId */
|
|
619
607
|
resolveCustomerIdForSmartPricing() {
|
|
620
|
-
|
|
621
|
-
if (this.smartPricingCustomerId)
|
|
622
|
-
return this.smartPricingCustomerId;
|
|
608
|
+
if (this.smartPricingCustomerId) return this.smartPricingCustomerId;
|
|
623
609
|
try {
|
|
624
|
-
const userPlugin =
|
|
625
|
-
const customerId = Number(
|
|
626
|
-
return Number.isFinite(customerId) && customerId > 0 ? customerId :
|
|
610
|
+
const userPlugin = this.core?.getPlugin('user');
|
|
611
|
+
const customerId = Number(userPlugin?.get?.()?.id);
|
|
612
|
+
return Number.isFinite(customerId) && customerId > 0 ? customerId : undefined;
|
|
627
613
|
} catch {
|
|
628
|
-
return
|
|
614
|
+
return undefined;
|
|
629
615
|
}
|
|
630
616
|
}
|
|
631
617
|
resolveAvailableWalletIdsForSmartPricing() {
|
|
632
|
-
|
|
633
|
-
const
|
|
634
|
-
const fallbackWalletIds = ((_c = this.otherParams) == null ? void 0 : _c.available_wallet_ids) || ((_d = this.otherParams) == null ? void 0 : _d.availableWalletIds) || ((_f = (_e = this.otherParams) == null ? void 0 : _e.strategy_context) == null ? void 0 : _f.available_wallet_ids) || ((_h = (_g = this.otherParams) == null ? void 0 : _g.strategy_context) == null ? void 0 : _h.availableWalletIds);
|
|
618
|
+
const orderWalletIds = this.store.order?.getAvailableWalletIds?.();
|
|
619
|
+
const fallbackWalletIds = this.otherParams?.available_wallet_ids || this.otherParams?.availableWalletIds || this.otherParams?.strategy_context?.available_wallet_ids || this.otherParams?.strategy_context?.availableWalletIds;
|
|
635
620
|
const source = Array.isArray(orderWalletIds) && orderWalletIds.length ? orderWalletIds : fallbackWalletIds;
|
|
636
|
-
if (!Array.isArray(source))
|
|
637
|
-
|
|
638
|
-
const ids = source.map((item) => Number(item)).filter((item) => Number.isFinite(item) && item > 0);
|
|
621
|
+
if (!Array.isArray(source)) return [];
|
|
622
|
+
const ids = source.map(item => Number(item)).filter(item => Number.isFinite(item) && item > 0);
|
|
639
623
|
return Array.from(new Set(ids));
|
|
640
624
|
}
|
|
625
|
+
|
|
641
626
|
/** 读取 schedule 全量列表,供智能定价 schedule_match 使用 */
|
|
642
627
|
getScheduleListForSmartPricing() {
|
|
643
|
-
var _a;
|
|
644
628
|
const scheduleModule = this.store.schedule;
|
|
645
|
-
const list =
|
|
629
|
+
const list = scheduleModule?.store?.scheduleList;
|
|
646
630
|
return Array.isArray(list) ? list : [];
|
|
647
631
|
}
|
|
632
|
+
|
|
648
633
|
/** 构建智能定价上下文,对齐 OS Server buildProductFormatterContext */
|
|
649
634
|
buildSmartPricingContext(customerId) {
|
|
650
|
-
|
|
651
|
-
const evaluator = (_b = (_a = this.core) == null ? void 0 : _a.context) == null ? void 0 : _b.dataVariantEvaluator;
|
|
635
|
+
const evaluator = this.core?.context?.dataVariantEvaluator;
|
|
652
636
|
return {
|
|
653
637
|
evaluator,
|
|
654
638
|
scheduleList: this.getScheduleListForSmartPricing(),
|
|
655
|
-
menuList:
|
|
639
|
+
menuList: this.otherParams?.menuList || this.otherParams?.openData?.menuList || [],
|
|
656
640
|
customerId: customerId ?? this.resolveCustomerIdForSmartPricing(),
|
|
657
641
|
availableWalletIds: this.resolveAvailableWalletIdsForSmartPricing(),
|
|
658
|
-
channel:
|
|
659
|
-
businessCode:
|
|
660
|
-
orderType:
|
|
661
|
-
strategy_context:
|
|
642
|
+
channel: this.otherParams?.channel,
|
|
643
|
+
businessCode: this.otherParams?.businessCode,
|
|
644
|
+
orderType: this.otherParams?.orderType || this.otherParams?.type,
|
|
645
|
+
strategy_context: this.otherParams?.strategy_context
|
|
662
646
|
};
|
|
663
647
|
}
|
|
648
|
+
|
|
664
649
|
/** venue + addon 全量商品,供智能定价评估 */
|
|
665
650
|
getAllProductsForSmartPricing() {
|
|
666
651
|
if (this.smartPricingProductCatalog.length) {
|
|
@@ -671,14 +656,9 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
671
656
|
return [...venueList, ...addonList];
|
|
672
657
|
}
|
|
673
658
|
getSlotPriceMapCacheKey(date, context) {
|
|
674
|
-
return [
|
|
675
|
-
date,
|
|
676
|
-
context.customerId ?? "",
|
|
677
|
-
(context.availableWalletIds || []).join(","),
|
|
678
|
-
context.channel ?? "",
|
|
679
|
-
context.businessCode ?? ""
|
|
680
|
-
].join("|");
|
|
659
|
+
return [date, context.customerId ?? '', (context.availableWalletIds || []).join(','), context.channel ?? '', context.businessCode ?? ''].join('|');
|
|
681
660
|
}
|
|
661
|
+
|
|
682
662
|
/**
|
|
683
663
|
* 按 schedule 分段构建 slot 价格 Map,带实例级缓存。
|
|
684
664
|
*/
|
|
@@ -686,10 +666,9 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
686
666
|
const context = this.buildSmartPricingContext();
|
|
687
667
|
const cacheKey = this.getSlotPriceMapCacheKey(date, context);
|
|
688
668
|
const cached = this.slotPriceMapCache.get(cacheKey);
|
|
689
|
-
if (cached)
|
|
690
|
-
|
|
691
|
-
const
|
|
692
|
-
const slotPriceMap = (0, import_smartPricing.buildSlotPriceMapByScheduleSegments)({
|
|
669
|
+
if (cached) return cached;
|
|
670
|
+
const timeLabels = (0, _timeSlot.generateTimeLabels)(config);
|
|
671
|
+
const slotPriceMap = (0, _smartPricing.buildSlotPriceMapByScheduleSegments)({
|
|
693
672
|
products: this.getAllProductsForSmartPricing(),
|
|
694
673
|
productIds,
|
|
695
674
|
date,
|
|
@@ -700,68 +679,67 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
700
679
|
this.slotPriceMapCache.set(cacheKey, slotPriceMap);
|
|
701
680
|
return slotPriceMap;
|
|
702
681
|
}
|
|
682
|
+
|
|
703
683
|
// ─── 场地商品 & 附加商品 ───
|
|
684
|
+
|
|
704
685
|
async loadAllProducts() {
|
|
705
|
-
if (this.loadAllProductsInFlight)
|
|
706
|
-
return this.loadAllProductsInFlight;
|
|
686
|
+
if (this.loadAllProductsInFlight) return this.loadAllProductsInFlight;
|
|
707
687
|
this.loadAllProductsInFlight = this._doLoadAllProducts().finally(() => {
|
|
708
688
|
this.loadAllProductsInFlight = null;
|
|
709
689
|
});
|
|
710
690
|
return this.loadAllProductsInFlight;
|
|
711
691
|
}
|
|
712
692
|
async _doLoadAllProducts() {
|
|
713
|
-
|
|
714
|
-
this.logMethodStart("loadAllProducts");
|
|
693
|
+
this.logMethodStart('loadAllProducts');
|
|
715
694
|
try {
|
|
716
|
-
if (!this.store.venueProducts)
|
|
717
|
-
|
|
718
|
-
if (!this.store.addonProducts)
|
|
719
|
-
throw new Error("addonProducts 模块未初始化");
|
|
695
|
+
if (!this.store.venueProducts) throw new Error('venueProducts 模块未初始化');
|
|
696
|
+
if (!this.store.addonProducts) throw new Error('addonProducts 模块未初始化');
|
|
720
697
|
await this.loadOpenDataConfig();
|
|
721
|
-
const associatedMenus =
|
|
698
|
+
const associatedMenus = this.otherParams?.openData?.['menu.associated_menus'] || [];
|
|
722
699
|
if (!associatedMenus.length) {
|
|
723
|
-
this.logMethodError(
|
|
724
|
-
throw new Error(
|
|
700
|
+
this.logMethodError('loadAllProducts', new Error('未获取到餐牌配置(menu.associated_menus),请检查 OpenData 配置'));
|
|
701
|
+
throw new Error('未获取到餐牌配置(menu.associated_menus),请检查 OpenData 配置');
|
|
725
702
|
}
|
|
726
|
-
const menuListIds = associatedMenus.map(
|
|
703
|
+
const menuListIds = associatedMenus.map(n => Number(n.value));
|
|
727
704
|
const allProducts = await this.store.venueProducts.loadProducts({
|
|
728
705
|
menu_list_ids: menuListIds,
|
|
729
706
|
cacheId: this.cacheId,
|
|
730
|
-
schedule_date: (0,
|
|
731
|
-
schedule_datetime: (0,
|
|
732
|
-
with_extra: [
|
|
707
|
+
schedule_date: (0, _dayjs.default)().format('YYYY-MM-DD'),
|
|
708
|
+
schedule_datetime: (0, _dayjs.default)().format('YYYY-MM-DD HH:mm:ss'),
|
|
709
|
+
with_extra: ['dataVariants']
|
|
733
710
|
});
|
|
734
711
|
const rawList = Array.isArray(allProducts) ? allProducts : [];
|
|
735
712
|
let list = rawList;
|
|
736
713
|
this.smartPricingProductCatalog = rawList.slice();
|
|
737
|
-
list = (0,
|
|
738
|
-
list,
|
|
739
|
-
this.buildSmartPricingContext(),
|
|
740
|
-
(0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
|
|
741
|
-
);
|
|
714
|
+
list = (0, _smartPricing.formatProductsWithDataVariant)(list, this.buildSmartPricingContext(), (0, _dayjs.default)().format('YYYY-MM-DD HH:mm:ss'));
|
|
742
715
|
this.clearSlotPriceMapCache();
|
|
743
|
-
const venueList = list.filter(
|
|
744
|
-
const addonList = list.filter(
|
|
745
|
-
const venueStore =
|
|
716
|
+
const venueList = list.filter(p => p.duration != null);
|
|
717
|
+
const addonList = list.filter(p => p.duration == null);
|
|
718
|
+
const venueStore = this.store.venueProducts?.store;
|
|
746
719
|
if (venueStore) {
|
|
747
720
|
venueStore.list = venueList.slice().sort((a, b) => Number(b.sort) - Number(a.sort));
|
|
748
721
|
}
|
|
749
722
|
this.store.addonProducts.addProduct(addonList);
|
|
750
|
-
this.resourceProductMap = (0,
|
|
723
|
+
this.resourceProductMap = (0, _resource.buildResourceProductMap)(venueList);
|
|
724
|
+
|
|
725
|
+
// 加载 holder 表单
|
|
751
726
|
if (this.store.order) {
|
|
752
|
-
const products =
|
|
727
|
+
const products = this.store.order?.getOrderProducts?.() || [];
|
|
753
728
|
await this.preloadHolderForms(products);
|
|
754
729
|
}
|
|
755
730
|
this.productsLoaded = true;
|
|
756
|
-
this.logMethodSuccess(
|
|
731
|
+
this.logMethodSuccess('loadAllProducts', {
|
|
757
732
|
total: list.length,
|
|
758
733
|
venueCount: venueList.length,
|
|
759
734
|
addonCount: addonList.length,
|
|
760
735
|
resourceCount: this.resourceProductMap.size
|
|
761
736
|
});
|
|
762
|
-
return {
|
|
737
|
+
return {
|
|
738
|
+
venueProducts: venueList,
|
|
739
|
+
addonProducts: addonList
|
|
740
|
+
};
|
|
763
741
|
} catch (error) {
|
|
764
|
-
this.logMethodError(
|
|
742
|
+
this.logMethodError('loadAllProducts', error);
|
|
765
743
|
throw error;
|
|
766
744
|
}
|
|
767
745
|
}
|
|
@@ -774,49 +752,55 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
774
752
|
return result.addonProducts;
|
|
775
753
|
}
|
|
776
754
|
getVenueProducts() {
|
|
777
|
-
|
|
778
|
-
return ((_b = (_a = this.store.venueProducts) == null ? void 0 : _a.store) == null ? void 0 : _b.list) || [];
|
|
755
|
+
return this.store.venueProducts?.store?.list || [];
|
|
779
756
|
}
|
|
780
757
|
getAddonProductsList() {
|
|
781
|
-
|
|
782
|
-
return ((_b = (_a = this.store.addonProducts) == null ? void 0 : _a.store) == null ? void 0 : _b.list) || [];
|
|
758
|
+
return this.store.addonProducts?.store?.list || [];
|
|
783
759
|
}
|
|
760
|
+
|
|
784
761
|
// ─── 报价单 ───
|
|
762
|
+
|
|
785
763
|
async loadQuotations(params) {
|
|
786
|
-
this.logMethodStart(
|
|
764
|
+
this.logMethodStart('loadQuotations');
|
|
787
765
|
try {
|
|
788
|
-
if (!this.store.quotation)
|
|
789
|
-
throw new Error("quotation 模块未初始化");
|
|
766
|
+
if (!this.store.quotation) throw new Error('quotation 模块未初始化');
|
|
790
767
|
await this.store.quotation.loadQuotations(params);
|
|
791
|
-
this.logMethodSuccess(
|
|
768
|
+
this.logMethodSuccess('loadQuotations', {
|
|
792
769
|
count: this.store.quotation.getQuotationList().length
|
|
793
770
|
});
|
|
794
771
|
} catch (error) {
|
|
795
|
-
this.logMethodError(
|
|
772
|
+
this.logMethodError('loadQuotations', error);
|
|
796
773
|
throw error;
|
|
797
774
|
}
|
|
798
775
|
}
|
|
776
|
+
|
|
799
777
|
// ─── 资源可用性 ───
|
|
778
|
+
|
|
800
779
|
async fetchResourceAvailability(params) {
|
|
801
|
-
this.logMethodStart(
|
|
780
|
+
this.logMethodStart('fetchResourceAvailability', params);
|
|
802
781
|
try {
|
|
803
782
|
const venueProducts = this.getVenueProducts();
|
|
804
783
|
if (!venueProducts.length) {
|
|
805
784
|
this.store.rawResourceData = [];
|
|
806
|
-
this.logMethodSuccess(
|
|
785
|
+
this.logMethodSuccess('fetchResourceAvailability', {
|
|
786
|
+
resourceCount: 0
|
|
787
|
+
});
|
|
807
788
|
return;
|
|
808
789
|
}
|
|
809
|
-
const resourceIds = (0,
|
|
790
|
+
const resourceIds = (0, _resource.extractResourceIds)(venueProducts);
|
|
810
791
|
if (!resourceIds.length) {
|
|
811
792
|
this.store.rawResourceData = [];
|
|
812
|
-
this.logMethodSuccess(
|
|
793
|
+
this.logMethodSuccess('fetchResourceAvailability', {
|
|
794
|
+
resourceIds: []
|
|
795
|
+
});
|
|
813
796
|
return;
|
|
814
797
|
}
|
|
798
|
+
|
|
799
|
+
// 跨天营业时,endDate 扩展一天以覆盖次日凌晨时段
|
|
815
800
|
const config = this.store.slotConfig;
|
|
816
|
-
const crossDay = (0,
|
|
817
|
-
const effectiveEndDate = crossDay ? (0,
|
|
818
|
-
if (!this.store.date)
|
|
819
|
-
throw new Error("date 模块未初始化");
|
|
801
|
+
const crossDay = (0, _timeSlot.isBusinessHoursCrossDay)(config);
|
|
802
|
+
const effectiveEndDate = crossDay ? (0, _dayjs.default)(params.endDate).add(1, 'day').format('YYYY-MM-DD') : params.endDate;
|
|
803
|
+
if (!this.store.date) throw new Error('date 模块未初始化');
|
|
820
804
|
const res = await this.store.date.fetchResourceDates({
|
|
821
805
|
query: {
|
|
822
806
|
start_date: params.startDate,
|
|
@@ -826,7 +810,7 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
826
810
|
useCache: false
|
|
827
811
|
});
|
|
828
812
|
const rawData = [];
|
|
829
|
-
if (
|
|
813
|
+
if (res?.data && Array.isArray(res.data)) {
|
|
830
814
|
for (const item of res.data) {
|
|
831
815
|
rawData.push({
|
|
832
816
|
resourceId: item.id,
|
|
@@ -839,63 +823,49 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
839
823
|
this.store.rawResourceData = rawData;
|
|
840
824
|
for (const item of rawData) {
|
|
841
825
|
const mappings = this.resourceProductMap.get(item.resourceId);
|
|
842
|
-
if (!mappings)
|
|
843
|
-
continue;
|
|
826
|
+
if (!mappings) continue;
|
|
844
827
|
for (const mapping of mappings) {
|
|
845
|
-
if (item.main_field)
|
|
846
|
-
|
|
847
|
-
if (item.resource_form_id)
|
|
848
|
-
mapping.formId = item.resource_form_id;
|
|
828
|
+
if (item.main_field) mapping.resourceName = item.main_field;
|
|
829
|
+
if (item.resource_form_id) mapping.formId = item.resource_form_id;
|
|
849
830
|
}
|
|
850
831
|
}
|
|
851
|
-
this.logMethodSuccess(
|
|
832
|
+
this.logMethodSuccess('fetchResourceAvailability', {
|
|
852
833
|
resourceCount: rawData.length,
|
|
853
834
|
totalTimes: rawData.reduce((sum, r) => sum + r.times.length, 0)
|
|
854
835
|
});
|
|
855
836
|
} catch (error) {
|
|
856
837
|
this.store.rawResourceData = [];
|
|
857
|
-
this.logMethodError(
|
|
838
|
+
this.logMethodError('fetchResourceAvailability', error);
|
|
858
839
|
throw error;
|
|
859
840
|
}
|
|
860
841
|
}
|
|
842
|
+
|
|
861
843
|
// ─── 日期概览 & 时间槽矩阵(纯计算,不发请求) ───
|
|
844
|
+
|
|
862
845
|
getOperatingHoursScheduleIds() {
|
|
863
|
-
|
|
864
|
-
const
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
return [];
|
|
868
|
-
return [...new Set(
|
|
869
|
-
rawIds.map((id) => Number(id)).filter((id) => Number.isFinite(id) && id > 0).map((id) => Math.floor(id))
|
|
870
|
-
)];
|
|
846
|
+
const openData = this.otherParams.openData || this.store.openData?.getOpenData?.() || null;
|
|
847
|
+
const rawIds = openData?.['availability.operating_hours'];
|
|
848
|
+
if (!Array.isArray(rawIds)) return [];
|
|
849
|
+
return [...new Set(rawIds.map(id => Number(id)).filter(id => Number.isFinite(id) && id > 0).map(id => Math.floor(id)))];
|
|
871
850
|
}
|
|
872
851
|
resolveSlotConfigForDate(date) {
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
852
|
+
const nextSlotConfig = {
|
|
853
|
+
...this.baseSlotConfig
|
|
854
|
+
};
|
|
855
|
+
if (!date || !this.store.schedule) return nextSlotConfig;
|
|
877
856
|
const operatingHoursScheduleIds = this.getOperatingHoursScheduleIds();
|
|
878
|
-
if (!operatingHoursScheduleIds.length)
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
);
|
|
883
|
-
if (!scheduleList.length)
|
|
884
|
-
return nextSlotConfig;
|
|
885
|
-
const timeRangeMap = (0, import_utils2.calcMinTimeMaxTimeBySchedules)(
|
|
886
|
-
scheduleList,
|
|
887
|
-
void 0,
|
|
888
|
-
date
|
|
889
|
-
);
|
|
857
|
+
if (!operatingHoursScheduleIds.length) return nextSlotConfig;
|
|
858
|
+
const scheduleList = this.store.schedule.getScheduleListByIds(operatingHoursScheduleIds);
|
|
859
|
+
if (!scheduleList.length) return nextSlotConfig;
|
|
860
|
+
const timeRangeMap = (0, _utils2.calcMinTimeMaxTimeBySchedules)(scheduleList, undefined, date);
|
|
890
861
|
let earliestStart = null;
|
|
891
862
|
let latestEnd = null;
|
|
892
863
|
for (const schedule of scheduleList) {
|
|
893
|
-
const dateRangeList =
|
|
864
|
+
const dateRangeList = timeRangeMap?.[schedule.id]?.dateRangeFormat || [];
|
|
894
865
|
for (const range of dateRangeList) {
|
|
895
|
-
const start = (0,
|
|
896
|
-
const end = (0,
|
|
897
|
-
if (!start.isValid() || !end.isValid())
|
|
898
|
-
continue;
|
|
866
|
+
const start = (0, _dayjs.default)(range?.start);
|
|
867
|
+
const end = (0, _dayjs.default)(range?.end);
|
|
868
|
+
if (!start.isValid() || !end.isValid()) continue;
|
|
899
869
|
if (!earliestStart || start.isBefore(earliestStart)) {
|
|
900
870
|
earliestStart = start;
|
|
901
871
|
}
|
|
@@ -904,12 +874,11 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
904
874
|
}
|
|
905
875
|
}
|
|
906
876
|
}
|
|
907
|
-
if (!earliestStart || !latestEnd)
|
|
908
|
-
return nextSlotConfig;
|
|
877
|
+
if (!earliestStart || !latestEnd) return nextSlotConfig;
|
|
909
878
|
return {
|
|
910
879
|
...nextSlotConfig,
|
|
911
|
-
businessStartTime: earliestStart.format(
|
|
912
|
-
businessEndTime: latestEnd.format(
|
|
880
|
+
businessStartTime: earliestStart.format('HH:mm'),
|
|
881
|
+
businessEndTime: latestEnd.format('HH:mm')
|
|
913
882
|
};
|
|
914
883
|
}
|
|
915
884
|
syncOperatingHoursToSlotConfig(date) {
|
|
@@ -918,25 +887,21 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
918
887
|
return resolvedSlotConfig;
|
|
919
888
|
}
|
|
920
889
|
getDateRangeSummary(params) {
|
|
921
|
-
return (0,
|
|
890
|
+
return (0, _dateSummary.buildDateRangeSummary)({
|
|
922
891
|
startDate: params.startDate,
|
|
923
892
|
endDate: params.endDate,
|
|
924
893
|
config: this.baseSlotConfig,
|
|
925
894
|
rawResources: this.store.rawResourceData,
|
|
926
895
|
resourceProductMap: this.resourceProductMap,
|
|
927
|
-
resolveConfig:
|
|
896
|
+
resolveConfig: date => this.resolveSlotConfigForDate(date),
|
|
928
897
|
buildSlotPriceMap: (date, config, productIds) => this.buildSlotPriceMapForDate(date, config, productIds)
|
|
929
898
|
});
|
|
930
899
|
}
|
|
931
900
|
getTimeSlotGrid(date) {
|
|
932
901
|
const resolvedSlotConfig = this.syncOperatingHoursToSlotConfig(date);
|
|
933
|
-
const productIds = [
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
)
|
|
937
|
-
];
|
|
938
|
-
const slotPriceMap = productIds.length ? this.buildSlotPriceMapForDate(date, resolvedSlotConfig, productIds) : void 0;
|
|
939
|
-
return (0, import_timeSlot.buildTimeSlotGrid)({
|
|
902
|
+
const productIds = [...new Set([...this.resourceProductMap.values()].flat().map(m => m.productId))];
|
|
903
|
+
const slotPriceMap = productIds.length ? this.buildSlotPriceMapForDate(date, resolvedSlotConfig, productIds) : undefined;
|
|
904
|
+
return (0, _timeSlot.buildTimeSlotGrid)({
|
|
940
905
|
date,
|
|
941
906
|
config: resolvedSlotConfig,
|
|
942
907
|
rawResources: this.store.rawResourceData,
|
|
@@ -944,7 +909,9 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
944
909
|
slotPriceMap
|
|
945
910
|
});
|
|
946
911
|
}
|
|
912
|
+
|
|
947
913
|
// ─── 时间槽订单操作 ───
|
|
914
|
+
|
|
948
915
|
/**
|
|
949
916
|
* 切换单个时段的选中状态(选中/取消)。
|
|
950
917
|
* 内部自动处理连续时段的合并与拆分,订单是唯一真相源。
|
|
@@ -953,7 +920,7 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
953
920
|
* 同一资源下不同 productId 之间互相隔离,不会相互合并。
|
|
954
921
|
*/
|
|
955
922
|
async toggleSlot(slot) {
|
|
956
|
-
this.logMethodStart(
|
|
923
|
+
this.logMethodStart('toggleSlot', {
|
|
957
924
|
resourceId: slot.resourceId,
|
|
958
925
|
productId: slot.productId,
|
|
959
926
|
startTime: slot.startTime
|
|
@@ -963,85 +930,73 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
963
930
|
if (!mappings || !mappings.length) {
|
|
964
931
|
throw new Error(`未找到资源 ${slot.resourceId} 的商品映射`);
|
|
965
932
|
}
|
|
966
|
-
const mapping = mappings.find(
|
|
933
|
+
const mapping = mappings.find(m => m.productId === slot.productId);
|
|
967
934
|
if (!mapping) {
|
|
968
935
|
throw new Error(`资源 ${slot.resourceId} 未关联商品 ${slot.productId}`);
|
|
969
936
|
}
|
|
970
|
-
if (!this.store.order)
|
|
971
|
-
|
|
972
|
-
const
|
|
973
|
-
slot.resourceId,
|
|
974
|
-
slot.productId
|
|
975
|
-
);
|
|
976
|
-
const existIndex = currentSlots.findIndex((s) => s.startTime === slot.startTime);
|
|
937
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
938
|
+
const currentSlots = this.getSelectedSlotsForResourceProduct(slot.resourceId, slot.productId);
|
|
939
|
+
const existIndex = currentSlots.findIndex(s => s.startTime === slot.startTime);
|
|
977
940
|
let nextSlots;
|
|
978
941
|
if (existIndex !== -1) {
|
|
979
942
|
nextSlots = currentSlots.filter((_, i) => i !== existIndex);
|
|
980
943
|
} else {
|
|
981
944
|
nextSlots = [...currentSlots, slot];
|
|
982
945
|
}
|
|
983
|
-
await this.reconcileOrderForResourceProduct(
|
|
984
|
-
slot.resourceId,
|
|
985
|
-
slot.productId,
|
|
986
|
-
nextSlots
|
|
987
|
-
);
|
|
946
|
+
await this.reconcileOrderForResourceProduct(slot.resourceId, slot.productId, nextSlots);
|
|
988
947
|
const products = this.store.order.getOrderProducts();
|
|
989
948
|
await this.refreshItemRuleQuantityLimits();
|
|
990
949
|
await this.refreshCartValidationPassed();
|
|
991
|
-
this.logMethodSuccess(
|
|
992
|
-
action: existIndex !== -1 ?
|
|
950
|
+
this.logMethodSuccess('toggleSlot', {
|
|
951
|
+
action: existIndex !== -1 ? 'remove' : 'add',
|
|
993
952
|
resourceId: slot.resourceId,
|
|
994
953
|
productId: slot.productId,
|
|
995
954
|
slotCount: nextSlots.length
|
|
996
955
|
});
|
|
997
956
|
return products;
|
|
998
957
|
} catch (error) {
|
|
999
|
-
this.logMethodError(
|
|
958
|
+
this.logMethodError('toggleSlot', error);
|
|
1000
959
|
throw error;
|
|
1001
960
|
}
|
|
1002
961
|
}
|
|
962
|
+
|
|
1003
963
|
/**
|
|
1004
964
|
* 获取某资源当前选中的所有独立时段(从订单中解析)。
|
|
1005
965
|
* 不传 productId 时返回该资源下所有商品的选中时段;传了则精确匹配。
|
|
1006
966
|
*/
|
|
1007
967
|
getSelectedSlotsForResource(resourceId, productId) {
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
return
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
if (!((_a2 = p.metadata) == null ? void 0 : _a2.venue_booking))
|
|
1015
|
-
return false;
|
|
1016
|
-
if (String((_b = p.metadata) == null ? void 0 : _b.resource_id) !== String(resourceId))
|
|
1017
|
-
return false;
|
|
1018
|
-
if (productId != null && Number(p.product_id) !== Number(productId))
|
|
1019
|
-
return false;
|
|
968
|
+
const tempOrder = this.store.order?.getTempOrder();
|
|
969
|
+
if (!tempOrder) return [];
|
|
970
|
+
const venueProducts = tempOrder.products.filter(p => {
|
|
971
|
+
if (!p.metadata?.venue_booking) return false;
|
|
972
|
+
if (String(p.metadata?.resource_id) !== String(resourceId)) return false;
|
|
973
|
+
if (productId != null && Number(p.product_id) !== Number(productId)) return false;
|
|
1020
974
|
return true;
|
|
1021
975
|
});
|
|
1022
976
|
const slotDuration = this.store.slotConfig.slotDurationMinutes;
|
|
1023
977
|
const slots = [];
|
|
1024
978
|
for (const product of venueProducts) {
|
|
1025
|
-
slots.push(
|
|
1026
|
-
...
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
}))
|
|
1030
|
-
);
|
|
979
|
+
slots.push(...(0, _slotMerge.expandMergedSlotToIndividual)(product, slotDuration).map(s => ({
|
|
980
|
+
...s,
|
|
981
|
+
productId: Number(product.product_id)
|
|
982
|
+
})));
|
|
1031
983
|
}
|
|
1032
984
|
return slots.sort((a, b) => a.startTime.localeCompare(b.startTime));
|
|
1033
985
|
}
|
|
986
|
+
|
|
1034
987
|
/** getSelectedSlotsForResource 的 (resourceId, productId) 精确版,内部使用。 */
|
|
1035
988
|
getSelectedSlotsForResourceProduct(resourceId, productId) {
|
|
1036
989
|
return this.getSelectedSlotsForResource(resourceId, productId);
|
|
1037
990
|
}
|
|
991
|
+
|
|
1038
992
|
/**
|
|
1039
993
|
* 判断某个时段是否已选中。
|
|
1040
994
|
* 不传 productId 时:只要该资源下任一商品在 startTime 被选中即返回 true;传了则精确匹配。
|
|
1041
995
|
*/
|
|
1042
996
|
isSlotSelected(resourceId, startTime, productId) {
|
|
1043
|
-
return this.getSelectedSlotsForResource(resourceId, productId).some(
|
|
997
|
+
return this.getSelectedSlotsForResource(resourceId, productId).some(s => s.startTime === startTime);
|
|
1044
998
|
}
|
|
999
|
+
|
|
1045
1000
|
/**
|
|
1046
1001
|
* 判断指定 (resourceId, productId, startTime) 格子是否应因其它已选项而被禁用。
|
|
1047
1002
|
* 规则:
|
|
@@ -1051,21 +1006,27 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1051
1006
|
* 4) 两个组合资源的 child 集合有交集,且对方在该 startTime 被选中 → 禁用
|
|
1052
1007
|
*/
|
|
1053
1008
|
isSlotDisabledBySelection(params) {
|
|
1054
|
-
const {
|
|
1009
|
+
const {
|
|
1010
|
+
resourceId,
|
|
1011
|
+
productId,
|
|
1012
|
+
startTime
|
|
1013
|
+
} = params;
|
|
1055
1014
|
const allSelected = this.getAllSelectedSlots();
|
|
1056
|
-
const getSelectedAt =
|
|
1015
|
+
const getSelectedAt = resId => {
|
|
1057
1016
|
const list = allSelected.get(resId) || [];
|
|
1058
|
-
return list.filter(
|
|
1017
|
+
return list.filter(s => s.startTime === startTime);
|
|
1059
1018
|
};
|
|
1019
|
+
|
|
1020
|
+
// 规则 1:同场地、不同 productId 的已选
|
|
1060
1021
|
const sameResourceSelections = getSelectedAt(resourceId);
|
|
1061
|
-
if (sameResourceSelections.some(
|
|
1022
|
+
if (sameResourceSelections.some(s => Number(s.productId) !== Number(productId))) {
|
|
1062
1023
|
return true;
|
|
1063
1024
|
}
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
);
|
|
1068
|
-
const combined = raw
|
|
1025
|
+
|
|
1026
|
+
// 组合资源字段缓存
|
|
1027
|
+
const getCombinedChildIds = resId => {
|
|
1028
|
+
const raw = this.store.rawResourceData.find(r => String(r.resourceId) === String(resId));
|
|
1029
|
+
const combined = raw?.combined_resource;
|
|
1069
1030
|
if (combined && combined.status === 1 && Array.isArray(combined.resource_ids)) {
|
|
1070
1031
|
return combined.resource_ids;
|
|
1071
1032
|
}
|
|
@@ -1073,59 +1034,53 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1073
1034
|
};
|
|
1074
1035
|
const currentChildIds = getCombinedChildIds(resourceId);
|
|
1075
1036
|
const currentIsCombined = currentChildIds.length > 0;
|
|
1037
|
+
|
|
1038
|
+
// 规则 2:当前是组合资源,任一子资源被选 → 禁用
|
|
1076
1039
|
if (currentIsCombined) {
|
|
1077
1040
|
for (const childId of currentChildIds) {
|
|
1078
|
-
if (getSelectedAt(childId).length > 0)
|
|
1079
|
-
return true;
|
|
1041
|
+
if (getSelectedAt(childId).length > 0) return true;
|
|
1080
1042
|
}
|
|
1081
1043
|
}
|
|
1044
|
+
|
|
1045
|
+
// 规则 3 & 4:扫描所有已选的 (resId),若是组合资源,检查其 children 是否包含当前 resourceId 或与当前 child 集合有交集
|
|
1082
1046
|
for (const [selectedResId, slots] of allSelected) {
|
|
1083
|
-
if (!slots.some(
|
|
1084
|
-
|
|
1085
|
-
if (String(selectedResId) === String(resourceId))
|
|
1086
|
-
continue;
|
|
1047
|
+
if (!slots.some(s => s.startTime === startTime)) continue;
|
|
1048
|
+
if (String(selectedResId) === String(resourceId)) continue;
|
|
1087
1049
|
const selectedChildIds = getCombinedChildIds(selectedResId);
|
|
1088
|
-
if (selectedChildIds.length === 0)
|
|
1089
|
-
|
|
1090
|
-
|
|
1050
|
+
if (selectedChildIds.length === 0) continue;
|
|
1051
|
+
|
|
1052
|
+
// 对方是组合资源,其 children 包含当前 resourceId(规则 3)
|
|
1053
|
+
if (selectedChildIds.some(id => String(id) === String(resourceId))) {
|
|
1091
1054
|
return true;
|
|
1092
1055
|
}
|
|
1056
|
+
|
|
1057
|
+
// 双方都是组合资源,child 集合有交集(规则 4)
|
|
1093
1058
|
if (currentIsCombined) {
|
|
1094
|
-
const intersect = selectedChildIds.some(
|
|
1095
|
-
|
|
1096
|
-
);
|
|
1097
|
-
if (intersect)
|
|
1098
|
-
return true;
|
|
1059
|
+
const intersect = selectedChildIds.some(id => currentChildIds.some(cid => String(cid) === String(id)));
|
|
1060
|
+
if (intersect) return true;
|
|
1099
1061
|
}
|
|
1100
1062
|
}
|
|
1101
1063
|
return false;
|
|
1102
1064
|
}
|
|
1065
|
+
|
|
1103
1066
|
/**
|
|
1104
1067
|
* 获取所有已选时段(按资源分组)。每个 slot 上带 productId,便于 UI 做 per-product 判定。
|
|
1105
1068
|
*/
|
|
1106
1069
|
getAllSelectedSlots() {
|
|
1107
|
-
|
|
1108
|
-
const
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
return result;
|
|
1112
|
-
const venueProducts = tempOrder.products.filter((p) => {
|
|
1113
|
-
var _a2;
|
|
1114
|
-
return (_a2 = p.metadata) == null ? void 0 : _a2.venue_booking;
|
|
1115
|
-
});
|
|
1070
|
+
const result = new Map();
|
|
1071
|
+
const tempOrder = this.store.order?.getTempOrder();
|
|
1072
|
+
if (!tempOrder) return result;
|
|
1073
|
+
const venueProducts = tempOrder.products.filter(p => p.metadata?.venue_booking);
|
|
1116
1074
|
const slotDuration = this.store.slotConfig.slotDurationMinutes;
|
|
1117
1075
|
for (const product of venueProducts) {
|
|
1118
|
-
const resourceId =
|
|
1119
|
-
if (resourceId == null)
|
|
1120
|
-
continue;
|
|
1076
|
+
const resourceId = product.metadata?.resource_id;
|
|
1077
|
+
if (resourceId == null) continue;
|
|
1121
1078
|
const productId = Number(product.product_id);
|
|
1122
1079
|
const existing = result.get(resourceId) || [];
|
|
1123
|
-
existing.push(
|
|
1124
|
-
...
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
}))
|
|
1128
|
-
);
|
|
1080
|
+
existing.push(...(0, _slotMerge.expandMergedSlotToIndividual)(product, slotDuration).map(s => ({
|
|
1081
|
+
...s,
|
|
1082
|
+
productId
|
|
1083
|
+
})));
|
|
1129
1084
|
result.set(resourceId, existing);
|
|
1130
1085
|
}
|
|
1131
1086
|
for (const [key, slots] of result) {
|
|
@@ -1133,144 +1088,135 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1133
1088
|
}
|
|
1134
1089
|
return result;
|
|
1135
1090
|
}
|
|
1091
|
+
|
|
1136
1092
|
/**
|
|
1137
1093
|
* 对指定 (resourceId, productId) 的订单商品进行 reconcile:
|
|
1138
1094
|
* 清除旧商品 → 合并连续时段 → 重新写入。
|
|
1139
1095
|
* 同一场地下不同商品互不干扰,各自单独 reconcile。
|
|
1140
1096
|
*/
|
|
1141
1097
|
async reconcileOrderForResourceProduct(resourceId, productId, slots) {
|
|
1142
|
-
var _a, _b;
|
|
1143
1098
|
const mappings = this.resourceProductMap.get(resourceId);
|
|
1144
|
-
if (!mappings || !mappings.length || !this.store.order)
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
if (!mapping)
|
|
1148
|
-
return;
|
|
1099
|
+
if (!mappings || !mappings.length || !this.store.order) return;
|
|
1100
|
+
const mapping = mappings.find(m => m.productId === productId);
|
|
1101
|
+
if (!mapping) return;
|
|
1149
1102
|
const tempOrder = this.store.order.ensureTempOrder();
|
|
1150
|
-
const matchesCurrent = (meta, pid) => !!
|
|
1151
|
-
tempOrder.products = tempOrder.products.filter(
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
if (String((_b2 = b.metadata) == null ? void 0 : _b2.resource_id) !== String(resourceId))
|
|
1160
|
-
return true;
|
|
1161
|
-
const bookingProductId = ((_c = b.metadata) == null ? void 0 : _c.product_id) ?? ((_d = b == null ? void 0 : b.product) == null ? void 0 : _d.product_id);
|
|
1162
|
-
if (bookingProductId == null)
|
|
1163
|
-
return false;
|
|
1164
|
-
return Number(bookingProductId) !== Number(productId);
|
|
1165
|
-
}
|
|
1166
|
-
);
|
|
1103
|
+
const matchesCurrent = (meta, pid) => !!meta?.venue_booking && String(meta?.resource_id) === String(resourceId) && Number(pid) === Number(productId);
|
|
1104
|
+
tempOrder.products = tempOrder.products.filter(p => !matchesCurrent(p.metadata, p.product_id));
|
|
1105
|
+
tempOrder.bookings = (tempOrder.bookings || []).filter(b => {
|
|
1106
|
+
if (!b.metadata?.venue_booking) return true;
|
|
1107
|
+
if (String(b.metadata?.resource_id) !== String(resourceId)) return true;
|
|
1108
|
+
const bookingProductId = b.metadata?.product_id ?? b?.product?.product_id;
|
|
1109
|
+
if (bookingProductId == null) return false;
|
|
1110
|
+
return Number(bookingProductId) !== Number(productId);
|
|
1111
|
+
});
|
|
1167
1112
|
if (!slots.length) {
|
|
1168
1113
|
this.store.order.applyDiscount();
|
|
1169
|
-
await this.store.order.recalculateSummary({
|
|
1114
|
+
await this.store.order.recalculateSummary({
|
|
1115
|
+
createIfMissing: true
|
|
1116
|
+
});
|
|
1170
1117
|
this.store.order.persistTempOrder();
|
|
1171
1118
|
return;
|
|
1172
1119
|
}
|
|
1173
|
-
const merged = (0,
|
|
1174
|
-
const rawResource = this.store.rawResourceData.find(
|
|
1175
|
-
(r) => String(r.resourceId) === String(resourceId)
|
|
1176
|
-
);
|
|
1120
|
+
const merged = (0, _slotMerge.mergeConsecutiveSlots)(slots);
|
|
1121
|
+
const rawResource = this.store.rawResourceData.find(r => String(r.resourceId) === String(resourceId));
|
|
1177
1122
|
const childRawResources = this.getCombinedChildRawResources(rawResource);
|
|
1178
|
-
const venueProduct = this.getVenueProducts().find(
|
|
1123
|
+
const venueProduct = this.getVenueProducts().find(p => p.id === mapping.productId);
|
|
1179
1124
|
tempOrder.bookings = tempOrder.bookings || [];
|
|
1180
1125
|
for (let i = 0; i < merged.length; i++) {
|
|
1181
1126
|
const group = merged[i];
|
|
1182
|
-
const identityKey = (0,
|
|
1183
|
-
const bookingUuid = (0,
|
|
1184
|
-
const startMoment = (0,
|
|
1185
|
-
const endMoment = (0,
|
|
1186
|
-
const duration = endMoment.diff(startMoment,
|
|
1187
|
-
const customDepositData = cloneCustomDepositData(venueProduct
|
|
1127
|
+
const identityKey = (0, _slotMerge.buildVenueIdentityKey)(resourceId, i);
|
|
1128
|
+
const bookingUuid = (0, _utils3.createUuidV4)();
|
|
1129
|
+
const startMoment = (0, _dayjs.default)(group.startTime, 'YYYY-MM-DD HH:mm');
|
|
1130
|
+
const endMoment = (0, _dayjs.default)(group.endTime, 'YYYY-MM-DD HH:mm');
|
|
1131
|
+
const duration = endMoment.diff(startMoment, 'minute');
|
|
1132
|
+
const customDepositData = cloneCustomDepositData(venueProduct?.custom_deposit_data);
|
|
1188
1133
|
const resourceEntry = {
|
|
1189
|
-
relation_type:
|
|
1190
|
-
like_status:
|
|
1134
|
+
relation_type: 'form',
|
|
1135
|
+
like_status: 'common',
|
|
1191
1136
|
id: resourceId,
|
|
1192
1137
|
main_field: mapping.resourceName,
|
|
1193
|
-
form_id:
|
|
1138
|
+
form_id: rawResource?.form_id ?? mapping.formId,
|
|
1194
1139
|
relation_id: resourceId,
|
|
1195
1140
|
capacity: 1,
|
|
1196
|
-
metadata: (0,
|
|
1141
|
+
metadata: (0, _slotMerge.buildVenueResourceMetadata)({
|
|
1142
|
+
mapping,
|
|
1143
|
+
rawResource
|
|
1144
|
+
})
|
|
1197
1145
|
};
|
|
1198
1146
|
if (childRawResources && childRawResources.length) {
|
|
1199
|
-
resourceEntry.children = childRawResources.map(
|
|
1200
|
-
relation_type:
|
|
1201
|
-
like_status:
|
|
1147
|
+
resourceEntry.children = childRawResources.map(child => ({
|
|
1148
|
+
relation_type: 'form',
|
|
1149
|
+
like_status: 'common',
|
|
1202
1150
|
id: child.resourceId,
|
|
1203
|
-
main_field: child.main_field ||
|
|
1151
|
+
main_field: child.main_field || '',
|
|
1204
1152
|
form_id: child.form_id ?? child.formId,
|
|
1205
1153
|
relation_id: child.resourceId,
|
|
1206
1154
|
capacity: child.capacity ?? 1,
|
|
1207
1155
|
metadata: {}
|
|
1208
1156
|
}));
|
|
1209
1157
|
}
|
|
1210
|
-
tempOrder.products.push(
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1158
|
+
tempOrder.products.push((0, _utils.normalizeOrderProduct)({
|
|
1159
|
+
product_id: mapping.productId,
|
|
1160
|
+
product_variant_id: 0,
|
|
1161
|
+
identity_key: identityKey,
|
|
1162
|
+
num: 1,
|
|
1163
|
+
selling_price: group.totalPrice,
|
|
1164
|
+
original_price: group.totalPrice,
|
|
1165
|
+
is_charge_tax: venueProduct?.is_charge_tax ?? 0,
|
|
1166
|
+
metadata: {
|
|
1167
|
+
venue_booking: true,
|
|
1168
|
+
resource_id: resourceId,
|
|
1169
|
+
resource_form_id: mapping.formId,
|
|
1170
|
+
resource_name: mapping.resourceName,
|
|
1171
|
+
start_time: group.startTime,
|
|
1172
|
+
end_time: group.endTime,
|
|
1173
|
+
slot_count: group.slotCount,
|
|
1174
|
+
booking_uid: bookingUuid,
|
|
1175
|
+
price_breakdown: (0, _slotMerge.buildPriceBreakdown)({
|
|
1176
|
+
group,
|
|
1177
|
+
productId: mapping.productId
|
|
1178
|
+
})
|
|
1179
|
+
},
|
|
1180
|
+
_origin: {
|
|
1181
|
+
name: mapping.productTitle,
|
|
1182
|
+
cover: venueProduct?.cover || '',
|
|
1183
|
+
custom_deposit_data: customDepositData,
|
|
1184
|
+
id: 0,
|
|
1185
|
+
number: 1,
|
|
1186
|
+
registration_type: 'all',
|
|
1187
|
+
relation_products: [],
|
|
1188
|
+
is_all: false,
|
|
1189
|
+
product: {
|
|
1190
|
+
product_id: mapping.productId,
|
|
1191
|
+
product_variant_id: 0,
|
|
1192
|
+
num: 1,
|
|
1193
|
+
product_bundle: [],
|
|
1194
|
+
product_option_item: [],
|
|
1195
|
+
discount_list: [],
|
|
1196
|
+
custom_deposit_data: customDepositData,
|
|
1197
|
+
metadata: {},
|
|
1198
|
+
holder_config: venueProduct?.holder_config,
|
|
1199
|
+
bookingUuid: bookingUuid,
|
|
1200
|
+
shop_id: venueProduct?.shop_id || 0
|
|
1201
|
+
},
|
|
1202
|
+
sub_type: 'minutes',
|
|
1203
|
+
duration,
|
|
1204
|
+
like_status: 'common',
|
|
1205
|
+
resources: [resourceEntry],
|
|
1206
|
+
schedule_id: 0,
|
|
1207
|
+
select_date: startMoment.format('YYYY-MM-DD'),
|
|
1208
|
+
start_date: startMoment.format('YYYY-MM-DD'),
|
|
1209
|
+
start_time: startMoment.format('HH:mm'),
|
|
1210
|
+
end_date: endMoment.format('YYYY-MM-DD'),
|
|
1211
|
+
end_time: endMoment.format('HH:mm'),
|
|
1219
1212
|
metadata: {
|
|
1220
1213
|
venue_booking: true,
|
|
1221
|
-
|
|
1222
|
-
resource_form_id: mapping.formId,
|
|
1223
|
-
resource_name: mapping.resourceName,
|
|
1224
|
-
start_time: group.startTime,
|
|
1225
|
-
end_time: group.endTime,
|
|
1226
|
-
slot_count: group.slotCount,
|
|
1227
|
-
booking_uid: bookingUuid,
|
|
1228
|
-
price_breakdown: (0, import_slotMerge.buildPriceBreakdown)({
|
|
1229
|
-
group,
|
|
1230
|
-
productId: mapping.productId
|
|
1231
|
-
})
|
|
1214
|
+
slot_count: group.slotCount
|
|
1232
1215
|
},
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
id: 0,
|
|
1238
|
-
number: 1,
|
|
1239
|
-
registration_type: "all",
|
|
1240
|
-
relation_products: [],
|
|
1241
|
-
is_all: false,
|
|
1242
|
-
product: {
|
|
1243
|
-
product_id: mapping.productId,
|
|
1244
|
-
product_variant_id: 0,
|
|
1245
|
-
num: 1,
|
|
1246
|
-
product_bundle: [],
|
|
1247
|
-
product_option_item: [],
|
|
1248
|
-
discount_list: [],
|
|
1249
|
-
custom_deposit_data: customDepositData,
|
|
1250
|
-
metadata: {},
|
|
1251
|
-
holder_config: venueProduct == null ? void 0 : venueProduct.holder_config,
|
|
1252
|
-
bookingUuid,
|
|
1253
|
-
shop_id: (venueProduct == null ? void 0 : venueProduct.shop_id) || 0
|
|
1254
|
-
},
|
|
1255
|
-
sub_type: "minutes",
|
|
1256
|
-
duration,
|
|
1257
|
-
like_status: "common",
|
|
1258
|
-
resources: [resourceEntry],
|
|
1259
|
-
schedule_id: 0,
|
|
1260
|
-
select_date: startMoment.format("YYYY-MM-DD"),
|
|
1261
|
-
start_date: startMoment.format("YYYY-MM-DD"),
|
|
1262
|
-
start_time: startMoment.format("HH:mm"),
|
|
1263
|
-
end_date: endMoment.format("YYYY-MM-DD"),
|
|
1264
|
-
end_time: endMoment.format("HH:mm"),
|
|
1265
|
-
metadata: {
|
|
1266
|
-
venue_booking: true,
|
|
1267
|
-
slot_count: group.slotCount
|
|
1268
|
-
},
|
|
1269
|
-
holder: null
|
|
1270
|
-
}
|
|
1271
|
-
})
|
|
1272
|
-
);
|
|
1273
|
-
const booking = (0, import_slotMerge.buildVenueBookingEntry)({
|
|
1216
|
+
holder: null
|
|
1217
|
+
}
|
|
1218
|
+
}));
|
|
1219
|
+
const booking = (0, _slotMerge.buildVenueBookingEntry)({
|
|
1274
1220
|
group,
|
|
1275
1221
|
resourceId,
|
|
1276
1222
|
mapping,
|
|
@@ -1281,31 +1227,34 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1281
1227
|
});
|
|
1282
1228
|
tempOrder.bookings.push(booking);
|
|
1283
1229
|
}
|
|
1284
|
-
|
|
1230
|
+
|
|
1231
|
+
// 获取表单信息
|
|
1232
|
+
const products = this.store.order?.getOrderProducts?.() || [];
|
|
1285
1233
|
await this.preloadHolderForms(products);
|
|
1286
1234
|
this.store.order.applyDiscount();
|
|
1287
|
-
await this.store.order.recalculateSummary({
|
|
1235
|
+
await this.store.order.recalculateSummary({
|
|
1236
|
+
createIfMissing: true
|
|
1237
|
+
});
|
|
1288
1238
|
this.store.order.persistTempOrder();
|
|
1289
1239
|
}
|
|
1240
|
+
|
|
1290
1241
|
/** 给定一个父 rawResource,返回其 combined_resource.resource_ids 对应的子 rawResource 列表。 */
|
|
1291
1242
|
getCombinedChildRawResources(rawResource) {
|
|
1292
|
-
if (!rawResource)
|
|
1293
|
-
return void 0;
|
|
1243
|
+
if (!rawResource) return undefined;
|
|
1294
1244
|
const combined = rawResource.combined_resource;
|
|
1295
1245
|
if (!combined || combined.status !== 1 || !Array.isArray(combined.resource_ids) || !combined.resource_ids.length) {
|
|
1296
|
-
return
|
|
1246
|
+
return undefined;
|
|
1297
1247
|
}
|
|
1298
1248
|
const children = [];
|
|
1299
1249
|
for (const id of combined.resource_ids) {
|
|
1300
|
-
const child = this.store.rawResourceData.find(
|
|
1301
|
-
|
|
1302
|
-
);
|
|
1303
|
-
if (child)
|
|
1304
|
-
children.push(child);
|
|
1250
|
+
const child = this.store.rawResourceData.find(r => String(r.resourceId) === String(id));
|
|
1251
|
+
if (child) children.push(child);
|
|
1305
1252
|
}
|
|
1306
|
-
return children.length ? children :
|
|
1253
|
+
return children.length ? children : undefined;
|
|
1307
1254
|
}
|
|
1255
|
+
|
|
1308
1256
|
// ─── 配置 ───
|
|
1257
|
+
|
|
1309
1258
|
setSlotConfig(config) {
|
|
1310
1259
|
this.baseSlotConfig = {
|
|
1311
1260
|
...this.baseSlotConfig,
|
|
@@ -1316,98 +1265,89 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1316
1265
|
};
|
|
1317
1266
|
}
|
|
1318
1267
|
getSlotConfig() {
|
|
1319
|
-
return {
|
|
1268
|
+
return {
|
|
1269
|
+
...this.store.slotConfig
|
|
1270
|
+
};
|
|
1320
1271
|
}
|
|
1272
|
+
|
|
1321
1273
|
// ─── 日程 ───
|
|
1274
|
+
|
|
1322
1275
|
async loadSchedules() {
|
|
1323
|
-
this.logMethodStart(
|
|
1276
|
+
this.logMethodStart('loadSchedules');
|
|
1324
1277
|
try {
|
|
1325
|
-
if (!this.store.schedule)
|
|
1326
|
-
throw new Error("schedule 模块未初始化");
|
|
1278
|
+
if (!this.store.schedule) throw new Error('schedule 模块未初始化');
|
|
1327
1279
|
await this.store.schedule.loadAllSchedule();
|
|
1328
|
-
this.logMethodSuccess(
|
|
1280
|
+
this.logMethodSuccess('loadSchedules');
|
|
1329
1281
|
} catch (error) {
|
|
1330
|
-
this.logMethodError(
|
|
1282
|
+
this.logMethodError('loadSchedules', error);
|
|
1331
1283
|
throw error;
|
|
1332
1284
|
}
|
|
1333
1285
|
}
|
|
1334
1286
|
getScheduleListByIds(ids) {
|
|
1335
|
-
if (!this.store.schedule)
|
|
1336
|
-
return [];
|
|
1287
|
+
if (!this.store.schedule) return [];
|
|
1337
1288
|
return this.store.schedule.getScheduleListByIds(ids);
|
|
1338
1289
|
}
|
|
1290
|
+
|
|
1339
1291
|
// ─── 临时订单操作(保留原有能力) ───
|
|
1292
|
+
|
|
1340
1293
|
getTempOrder() {
|
|
1341
|
-
|
|
1342
|
-
const result = ((_a = this.store.order) == null ? void 0 : _a.getTempOrder()) || null;
|
|
1294
|
+
const result = this.store.order?.getTempOrder() || null;
|
|
1343
1295
|
return result;
|
|
1344
1296
|
}
|
|
1345
1297
|
updateTempOrderNote(note) {
|
|
1346
|
-
if (!this.store.order)
|
|
1347
|
-
throw new Error("order 模块未初始化");
|
|
1298
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1348
1299
|
return this.store.order.updateTempOrderNote(note);
|
|
1349
1300
|
}
|
|
1350
1301
|
updateTempOrderContactsInfo(contactsInfo) {
|
|
1351
|
-
if (!this.store.order)
|
|
1352
|
-
throw new Error("order 模块未初始化");
|
|
1302
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1353
1303
|
return this.store.order.updateTempOrderContactsInfo(contactsInfo);
|
|
1354
1304
|
}
|
|
1355
1305
|
ensureTempOrder() {
|
|
1356
|
-
if (!this.store.order)
|
|
1357
|
-
throw new Error("order 模块未初始化");
|
|
1306
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1358
1307
|
return this.store.order.ensureTempOrder();
|
|
1359
1308
|
}
|
|
1360
1309
|
async onCustomerLogin(params) {
|
|
1361
|
-
this.logMethodStart(
|
|
1310
|
+
this.logMethodStart('onCustomerLogin', {
|
|
1311
|
+
customerId: params.customerId
|
|
1312
|
+
});
|
|
1362
1313
|
try {
|
|
1363
1314
|
await this.refreshOrderMarketingAfterLogin({
|
|
1364
1315
|
customerId: params.customerId
|
|
1365
1316
|
});
|
|
1366
|
-
this.logMethodSuccess(
|
|
1317
|
+
this.logMethodSuccess('onCustomerLogin', {
|
|
1318
|
+
customerId: params.customerId
|
|
1319
|
+
});
|
|
1367
1320
|
} catch (error) {
|
|
1368
|
-
this.logMethodError(
|
|
1321
|
+
this.logMethodError('onCustomerLogin', error);
|
|
1369
1322
|
throw error;
|
|
1370
1323
|
}
|
|
1371
1324
|
}
|
|
1372
1325
|
recalculateOrderPricesFromSmartPricing() {
|
|
1373
|
-
|
|
1374
|
-
if (!this.store.order)
|
|
1375
|
-
return;
|
|
1326
|
+
if (!this.store.order) return;
|
|
1376
1327
|
const tempOrder = this.store.order.getTempOrder();
|
|
1377
|
-
if (!
|
|
1378
|
-
|
|
1379
|
-
const now = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
|
|
1328
|
+
if (!tempOrder?.products?.length) return;
|
|
1329
|
+
const now = (0, _dayjs.default)().format('YYYY-MM-DD HH:mm:ss');
|
|
1380
1330
|
const catalog = this.getAllProductsForSmartPricing();
|
|
1381
1331
|
const context = this.buildSmartPricingContext();
|
|
1382
1332
|
for (const product of tempOrder.products) {
|
|
1383
|
-
if (
|
|
1333
|
+
if (product.metadata?.venue_booking) {
|
|
1384
1334
|
const mappings = this.resourceProductMap.get(product.metadata.resource_id);
|
|
1385
|
-
if (!mappings || !mappings.length)
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
const
|
|
1391
|
-
product,
|
|
1392
|
-
this.store.slotConfig.slotDurationMinutes
|
|
1393
|
-
);
|
|
1394
|
-
const uniqueDates = [
|
|
1395
|
-
...new Set(slots.map((slot) => (0, import_dayjs.default)(slot.startTime).format("YYYY-MM-DD")))
|
|
1396
|
-
];
|
|
1397
|
-
const slotPriceMaps = /* @__PURE__ */ new Map();
|
|
1335
|
+
if (!mappings || !mappings.length) continue;
|
|
1336
|
+
const mapping = mappings.find(m => Number(m.productId) === Number(product.product_id)) || mappings[0];
|
|
1337
|
+
if (!mapping) continue;
|
|
1338
|
+
const slots = (0, _slotMerge.expandMergedSlotToIndividual)(product, this.store.slotConfig.slotDurationMinutes);
|
|
1339
|
+
const uniqueDates = [...new Set(slots.map(slot => (0, _dayjs.default)(slot.startTime).format('YYYY-MM-DD')))];
|
|
1340
|
+
const slotPriceMaps = new Map();
|
|
1398
1341
|
for (const slotDate of uniqueDates) {
|
|
1399
|
-
slotPriceMaps.set(
|
|
1400
|
-
slotDate,
|
|
1401
|
-
this.buildSlotPriceMapForDate(slotDate, this.store.slotConfig, [mapping.productId])
|
|
1402
|
-
);
|
|
1342
|
+
slotPriceMaps.set(slotDate, this.buildSlotPriceMapForDate(slotDate, this.store.slotConfig, [mapping.productId]));
|
|
1403
1343
|
}
|
|
1404
|
-
const updatedSlots = slots.map(
|
|
1405
|
-
const slotDate = (0,
|
|
1344
|
+
const updatedSlots = slots.map(slot => {
|
|
1345
|
+
const slotDate = (0, _dayjs.default)(slot.startTime).format('YYYY-MM-DD');
|
|
1406
1346
|
const slotPriceMap = slotPriceMaps.get(slotDate);
|
|
1407
1347
|
return {
|
|
1408
1348
|
...slot,
|
|
1409
1349
|
productId: mapping.productId,
|
|
1410
|
-
price: slotPriceMap ? (0,
|
|
1350
|
+
price: slotPriceMap ? (0, _smartPricing.getSlotPriceFromMap)({
|
|
1411
1351
|
slotPriceMap,
|
|
1412
1352
|
productId: mapping.productId,
|
|
1413
1353
|
slotStartTime: slot.startTime,
|
|
@@ -1415,17 +1355,17 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1415
1355
|
}) : mapping.price
|
|
1416
1356
|
};
|
|
1417
1357
|
});
|
|
1418
|
-
const merged = (0,
|
|
1358
|
+
const merged = (0, _slotMerge.mergeConsecutiveSlots)(updatedSlots);
|
|
1419
1359
|
if (merged.length === 1) {
|
|
1420
1360
|
product.selling_price = merged[0].totalPrice;
|
|
1421
1361
|
product.original_price = merged[0].totalPrice;
|
|
1422
|
-
product.metadata.price_breakdown = (0,
|
|
1362
|
+
product.metadata.price_breakdown = (0, _slotMerge.buildPriceBreakdown)({
|
|
1423
1363
|
group: merged[0],
|
|
1424
1364
|
productId: mapping.productId
|
|
1425
1365
|
});
|
|
1426
1366
|
}
|
|
1427
1367
|
} else if (product.product_id != null) {
|
|
1428
|
-
const smartPrice = (0,
|
|
1368
|
+
const smartPrice = (0, _smartPricing.getPriceForProductAtDatetime)({
|
|
1429
1369
|
products: catalog,
|
|
1430
1370
|
context,
|
|
1431
1371
|
productId: Number(product.product_id),
|
|
@@ -1438,74 +1378,76 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1438
1378
|
}
|
|
1439
1379
|
}
|
|
1440
1380
|
async scanCode(code, customerId) {
|
|
1441
|
-
this.logMethodStart(
|
|
1381
|
+
this.logMethodStart('scanCode', {
|
|
1382
|
+
code
|
|
1383
|
+
});
|
|
1442
1384
|
try {
|
|
1443
|
-
if (!this.store.order)
|
|
1444
|
-
throw new Error("order 模块未初始化");
|
|
1385
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1445
1386
|
const result = await this.store.order.scanCode(code, customerId);
|
|
1446
1387
|
if (result.isAvailable) {
|
|
1447
|
-
await this.store.order.recalculateSummary({
|
|
1388
|
+
await this.store.order.recalculateSummary({
|
|
1389
|
+
createIfMissing: true
|
|
1390
|
+
});
|
|
1448
1391
|
this.store.order.persistTempOrder();
|
|
1449
1392
|
}
|
|
1450
|
-
this.logMethodSuccess(
|
|
1393
|
+
this.logMethodSuccess('scanCode', {
|
|
1394
|
+
isAvailable: result.isAvailable
|
|
1395
|
+
});
|
|
1451
1396
|
return result;
|
|
1452
1397
|
} catch (error) {
|
|
1453
|
-
this.logMethodError(
|
|
1398
|
+
this.logMethodError('scanCode', error);
|
|
1454
1399
|
throw error;
|
|
1455
1400
|
}
|
|
1456
1401
|
}
|
|
1402
|
+
|
|
1457
1403
|
/** 获取当前折扣列表(包装 order.getDiscountList) */
|
|
1458
1404
|
getDiscountList() {
|
|
1459
|
-
if (!this.store.order)
|
|
1460
|
-
return [];
|
|
1405
|
+
if (!this.store.order) return [];
|
|
1461
1406
|
return this.store.order.getDiscountList();
|
|
1462
1407
|
}
|
|
1408
|
+
|
|
1463
1409
|
/** 勾选/取消勾选某张折扣券,重新计算折扣并持久化 */
|
|
1464
1410
|
async setDiscountSelected(params) {
|
|
1465
|
-
|
|
1466
|
-
this.logMethodStart("setDiscountSelected", params);
|
|
1411
|
+
this.logMethodStart('setDiscountSelected', params);
|
|
1467
1412
|
try {
|
|
1468
|
-
if (!this.store.order)
|
|
1469
|
-
throw new Error("order 模块未初始化");
|
|
1413
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1470
1414
|
const list = this.store.order.getDiscountList();
|
|
1471
|
-
const beforeTarget = list.find(
|
|
1472
|
-
const updated = list.map(
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
);
|
|
1479
|
-
const updatedTarget = updated.find((d) => d.id === params.discountId) || null;
|
|
1415
|
+
const beforeTarget = list.find(d => d.id === params.discountId) || null;
|
|
1416
|
+
const updated = list.map(d => d.id === params.discountId ? {
|
|
1417
|
+
...d,
|
|
1418
|
+
isSelected: params.isSelected,
|
|
1419
|
+
isManualSelect: !params.isSelected
|
|
1420
|
+
} : d);
|
|
1421
|
+
const updatedTarget = updated.find(d => d.id === params.discountId) || null;
|
|
1480
1422
|
const tempOrder = this.store.order.ensureTempOrder();
|
|
1481
1423
|
const orderStore = this.store.order.store || {};
|
|
1482
1424
|
const discountModule = orderStore.discount;
|
|
1483
1425
|
const rulesModule = orderStore.rules;
|
|
1484
|
-
const holders =
|
|
1426
|
+
const holders = tempOrder.holder?.form_record_id ? [{
|
|
1427
|
+
form_record_id: tempOrder.holder.form_record_id
|
|
1428
|
+
}] : [];
|
|
1485
1429
|
let nextDiscountList = updated;
|
|
1486
|
-
await
|
|
1430
|
+
await discountModule?.setDiscountList(updated);
|
|
1487
1431
|
if (rulesModule) {
|
|
1488
|
-
const result = rulesModule.calcDiscount(
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
if (result
|
|
1432
|
+
const result = rulesModule.calcDiscount({
|
|
1433
|
+
productList: tempOrder.products,
|
|
1434
|
+
discountList: updated,
|
|
1435
|
+
holders,
|
|
1436
|
+
isFormSubject: !!tempOrder.holder?.type && tempOrder.holder.type === 'form'
|
|
1437
|
+
}, {
|
|
1438
|
+
discountId: params.discountId,
|
|
1439
|
+
isSelected: params.isSelected
|
|
1440
|
+
}) || {
|
|
1441
|
+
productList: tempOrder.products,
|
|
1442
|
+
discountList: updated
|
|
1443
|
+
};
|
|
1444
|
+
if (result?.productList) {
|
|
1501
1445
|
tempOrder.products = result.productList;
|
|
1502
1446
|
}
|
|
1503
|
-
if (result
|
|
1447
|
+
if (result?.discountList) {
|
|
1504
1448
|
nextDiscountList = result.discountList;
|
|
1505
1449
|
if (!params.isSelected) {
|
|
1506
|
-
const beforeSelectedIds = new Set(
|
|
1507
|
-
updated.filter((d) => d.isSelected).map((d) => d.id)
|
|
1508
|
-
);
|
|
1450
|
+
const beforeSelectedIds = new Set(updated.filter(d => d.isSelected).map(d => d.id));
|
|
1509
1451
|
for (const d of nextDiscountList) {
|
|
1510
1452
|
if (d.isSelected && !beforeSelectedIds.has(d.id)) {
|
|
1511
1453
|
d.isSelected = false;
|
|
@@ -1514,243 +1456,251 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1514
1456
|
}
|
|
1515
1457
|
}
|
|
1516
1458
|
}
|
|
1517
|
-
const selectedResourceIds = new Set(
|
|
1518
|
-
|
|
1519
|
-
)
|
|
1459
|
+
const selectedResourceIds = new Set(nextDiscountList.filter(d => d.isSelected).map(d => d.id));
|
|
1460
|
+
// 无条件归一化:不论 Rules 是否清空 discount_list、长度是否变化,
|
|
1461
|
+
// 都以 original_price - Σ (当前选中 discount_list.amount) 重算 selling_price。
|
|
1462
|
+
// 目的:避免 unselect 后 selling_price 残留、reselect 时把残留价带进下一轮 Rules 造成双折扣。
|
|
1463
|
+
// 手动改价商品(_origin.isManualDiscount=true)不参与券流程归一化,保留手工价。
|
|
1520
1464
|
for (const product of tempOrder.products) {
|
|
1521
|
-
if (
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
const rid =
|
|
1465
|
+
if (product._origin?.isManualDiscount) continue;
|
|
1466
|
+
|
|
1467
|
+
// 1. 把 product.discount_list 和当前选中的 discount 对齐(剔除已取消的券)
|
|
1468
|
+
product.discount_list = (product.discount_list || []).filter(pd => {
|
|
1469
|
+
const rid = pd.discount?.resource_id ?? pd.id;
|
|
1526
1470
|
return rid != null && selectedResourceIds.has(rid);
|
|
1527
1471
|
});
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
);
|
|
1532
|
-
const optionSum = (0,
|
|
1533
|
-
const sourcePrice =
|
|
1534
|
-
const newSourceSellingPrice = new
|
|
1535
|
-
const newMainSellingPrice = new
|
|
1472
|
+
|
|
1473
|
+
// 2. 以 source_product_price 为券作用基准:券作用于 source(不含 option),
|
|
1474
|
+
// 再把 option 加回得到含 option 的 main_product_selling_price,最后合成 composite。
|
|
1475
|
+
const totalPerUnitDiscount = (product.discount_list || []).reduce((sum, pd) => sum + (pd.amount || 0), 0);
|
|
1476
|
+
const optionSum = (0, _utils3.sumOptionUnitPrice)(product.product_option_item);
|
|
1477
|
+
const sourcePrice = product.metadata?.source_product_price ?? (product.metadata?.main_product_original_price != null ? new _decimal.default(Number(product.metadata.main_product_original_price) || 0).minus(optionSum).toFixed(2) : product.original_price ?? '0');
|
|
1478
|
+
const newSourceSellingPrice = new _decimal.default(Number(sourcePrice) || 0).minus(totalPerUnitDiscount).toDecimalPlaces(2).toString();
|
|
1479
|
+
const newMainSellingPrice = new _decimal.default(Number(newSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
|
|
1536
1480
|
if (product.metadata) {
|
|
1537
1481
|
product.metadata.main_product_selling_price = newMainSellingPrice;
|
|
1538
1482
|
product.metadata.price_schema_version = 2;
|
|
1539
1483
|
}
|
|
1540
|
-
product.selling_price = (0,
|
|
1484
|
+
product.selling_price = (0, _utils3.composeLinePrice)({
|
|
1541
1485
|
mainPrice: newMainSellingPrice,
|
|
1542
1486
|
bundle: product.product_bundle
|
|
1543
1487
|
});
|
|
1544
1488
|
}
|
|
1545
|
-
|
|
1546
|
-
await
|
|
1547
|
-
tempOrder.discount_list = (nextDiscountList || []).filter(
|
|
1548
|
-
const afterApplyTarget = this.store.order.getDiscountList().find(
|
|
1549
|
-
await this.store.order.recalculateSummary({
|
|
1489
|
+
_Order.OrderModule.populateSavedAmounts(tempOrder.products, nextDiscountList);
|
|
1490
|
+
await discountModule?.setDiscountList(nextDiscountList);
|
|
1491
|
+
tempOrder.discount_list = (nextDiscountList || []).filter(d => d.isSelected);
|
|
1492
|
+
const afterApplyTarget = this.store.order.getDiscountList().find(d => d.id === params.discountId) || null;
|
|
1493
|
+
await this.store.order.recalculateSummary({
|
|
1494
|
+
createIfMissing: true
|
|
1495
|
+
});
|
|
1550
1496
|
this.store.order.persistTempOrder();
|
|
1551
|
-
const finalSummary =
|
|
1552
|
-
const finalProduct =
|
|
1553
|
-
this.logMethodSuccess(
|
|
1554
|
-
const finalTarget = this.store.order.getDiscountList().find(
|
|
1497
|
+
const finalSummary = this.store.order.getTempOrder()?.summary || null;
|
|
1498
|
+
const finalProduct = this.store.order.getTempOrder()?.products?.[0] || null;
|
|
1499
|
+
this.logMethodSuccess('setDiscountSelected', params);
|
|
1500
|
+
const finalTarget = this.store.order.getDiscountList().find(d => d.id === params.discountId) || null;
|
|
1555
1501
|
return this.store.order.getDiscountList();
|
|
1556
1502
|
} catch (error) {
|
|
1557
|
-
this.logMethodError(
|
|
1503
|
+
this.logMethodError('setDiscountSelected', error);
|
|
1558
1504
|
throw error;
|
|
1559
1505
|
}
|
|
1560
1506
|
}
|
|
1561
1507
|
async addNewOrder() {
|
|
1562
|
-
this.logMethodStart(
|
|
1508
|
+
this.logMethodStart('addNewOrder');
|
|
1563
1509
|
try {
|
|
1564
|
-
if (!this.store.order)
|
|
1565
|
-
throw new Error("order 模块未初始化");
|
|
1510
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1566
1511
|
const tempOrder = await this.store.order.addNewOrder();
|
|
1567
|
-
this.logMethodSuccess(
|
|
1512
|
+
this.logMethodSuccess('addNewOrder', {
|
|
1568
1513
|
productCount: tempOrder.products.length
|
|
1569
1514
|
});
|
|
1570
1515
|
return tempOrder;
|
|
1571
1516
|
} catch (error) {
|
|
1572
|
-
this.logMethodError(
|
|
1517
|
+
this.logMethodError('addNewOrder', error);
|
|
1573
1518
|
throw error;
|
|
1574
1519
|
}
|
|
1575
1520
|
}
|
|
1576
1521
|
getOrderProducts() {
|
|
1577
|
-
if (!this.store.order)
|
|
1578
|
-
throw new Error("order 模块未初始化");
|
|
1522
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1579
1523
|
return this.store.order.getOrderProducts();
|
|
1580
1524
|
}
|
|
1581
1525
|
async getSummary() {
|
|
1582
|
-
this.logMethodStart(
|
|
1526
|
+
this.logMethodStart('getSummary');
|
|
1583
1527
|
try {
|
|
1584
|
-
if (!this.store.order)
|
|
1585
|
-
throw new Error("order 模块未初始化");
|
|
1528
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1586
1529
|
const summary = await this.store.order.getScanOrderSummary();
|
|
1587
|
-
this.logMethodSuccess(
|
|
1530
|
+
this.logMethodSuccess('getSummary', {
|
|
1588
1531
|
totalAmount: summary.total_amount
|
|
1589
1532
|
});
|
|
1590
1533
|
return summary;
|
|
1591
1534
|
} catch (error) {
|
|
1592
|
-
this.logMethodError(
|
|
1535
|
+
this.logMethodError('getSummary', error);
|
|
1593
1536
|
throw error;
|
|
1594
1537
|
}
|
|
1595
1538
|
}
|
|
1596
1539
|
async submitOrder() {
|
|
1597
|
-
|
|
1598
|
-
this.logMethodStart("submitOrder");
|
|
1540
|
+
this.logMethodStart('submitOrder');
|
|
1599
1541
|
try {
|
|
1600
1542
|
await this.validateBeforeSubmitByItemRule();
|
|
1601
1543
|
if (!this.store.order) {
|
|
1602
|
-
throw new Error(
|
|
1544
|
+
throw new Error('venueBooking解决方案需要 order 模块支持');
|
|
1603
1545
|
}
|
|
1604
1546
|
const result = await this.store.order.submitTempOrder({
|
|
1605
1547
|
cacheId: this.cacheId,
|
|
1606
|
-
platform:
|
|
1607
|
-
businessCode:
|
|
1608
|
-
channel:
|
|
1609
|
-
type:
|
|
1548
|
+
platform: this.otherParams?.platform,
|
|
1549
|
+
businessCode: this.otherParams?.businessCode,
|
|
1550
|
+
channel: this.otherParams?.channel,
|
|
1551
|
+
type: this.otherParams?.type
|
|
1610
1552
|
});
|
|
1611
1553
|
const tempOrder = this.store.order.getTempOrder();
|
|
1612
|
-
this.logMethodSuccess(
|
|
1613
|
-
productCount:
|
|
1554
|
+
this.logMethodSuccess('submitOrder', {
|
|
1555
|
+
productCount: tempOrder?.products?.length || 0
|
|
1614
1556
|
});
|
|
1615
1557
|
return result;
|
|
1616
1558
|
} catch (error) {
|
|
1617
|
-
this.logMethodError(
|
|
1559
|
+
this.logMethodError('submitOrder', error);
|
|
1560
|
+
throw error;
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1564
|
+
/**
|
|
1565
|
+
* 0 元订单免费领取(非定金场景)
|
|
1566
|
+
* 与 appointment getFreeProduct 同接口:POST /pay/order/free-pay/:id
|
|
1567
|
+
*/
|
|
1568
|
+
async submitFreeOrder(id) {
|
|
1569
|
+
this.logMethodStart('submitFreeOrder', {
|
|
1570
|
+
id
|
|
1571
|
+
});
|
|
1572
|
+
try {
|
|
1573
|
+
if (!id) {
|
|
1574
|
+
throw new Error('订单 ID 不能为空');
|
|
1575
|
+
}
|
|
1576
|
+
const res = await this.request.post(`/pay/order/free-pay/${id}`);
|
|
1577
|
+
this.logMethodSuccess('submitFreeOrder', {
|
|
1578
|
+
id,
|
|
1579
|
+
status: res?.status
|
|
1580
|
+
});
|
|
1581
|
+
return res;
|
|
1582
|
+
} catch (error) {
|
|
1583
|
+
this.logMethodError('submitFreeOrder', error);
|
|
1618
1584
|
throw error;
|
|
1619
1585
|
}
|
|
1620
1586
|
}
|
|
1621
1587
|
async addProductToOrder(product) {
|
|
1622
|
-
|
|
1623
|
-
this.logMethodStart("addProductToOrder", {
|
|
1588
|
+
this.logMethodStart('addProductToOrder', {
|
|
1624
1589
|
product_id: product.product_id,
|
|
1625
1590
|
product_variant_id: product.product_variant_id
|
|
1626
1591
|
});
|
|
1627
1592
|
try {
|
|
1628
|
-
if (!this.store.order)
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
const smartPrice = (0, import_smartPricing.getPriceForProductAtDatetime)({
|
|
1593
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1594
|
+
if (!product.metadata?.venue_booking && product.product_id != null) {
|
|
1595
|
+
const smartPrice = (0, _smartPricing.getPriceForProductAtDatetime)({
|
|
1632
1596
|
products: this.getAllProductsForSmartPricing(),
|
|
1633
1597
|
context: this.buildSmartPricingContext(),
|
|
1634
1598
|
productId: Number(product.product_id),
|
|
1635
|
-
datetime: (0,
|
|
1599
|
+
datetime: (0, _dayjs.default)().format('YYYY-MM-DD HH:mm:ss'),
|
|
1636
1600
|
fallbackPrice: product.selling_price
|
|
1637
1601
|
});
|
|
1638
1602
|
product.selling_price = smartPrice;
|
|
1639
1603
|
product.original_price = smartPrice;
|
|
1640
|
-
} else if (product.selling_price != null && !
|
|
1604
|
+
} else if (product.selling_price != null && !product.metadata?.venue_booking) {
|
|
1641
1605
|
product.original_price = product.selling_price;
|
|
1642
1606
|
}
|
|
1643
1607
|
const products = await this.store.order.addProductToOrder(product);
|
|
1644
1608
|
await this.refreshItemRuleQuantityLimits();
|
|
1645
1609
|
await this.refreshCartValidationPassed();
|
|
1646
|
-
this.logMethodSuccess(
|
|
1610
|
+
this.logMethodSuccess('addProductToOrder', {
|
|
1647
1611
|
productCount: products.length
|
|
1648
1612
|
});
|
|
1649
1613
|
return products;
|
|
1650
1614
|
} catch (error) {
|
|
1651
|
-
this.logMethodError(
|
|
1615
|
+
this.logMethodError('addProductToOrder', error);
|
|
1652
1616
|
throw error;
|
|
1653
1617
|
}
|
|
1654
1618
|
}
|
|
1655
1619
|
async updateProductInOrder(params) {
|
|
1656
|
-
this.logMethodStart(
|
|
1620
|
+
this.logMethodStart('updateProductInOrder', {
|
|
1657
1621
|
product_id: params.product_id,
|
|
1658
1622
|
product_variant_id: params.product_variant_id
|
|
1659
1623
|
});
|
|
1660
1624
|
try {
|
|
1661
|
-
if (!this.store.order)
|
|
1662
|
-
throw new Error("order 模块未初始化");
|
|
1625
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1663
1626
|
const products = await this.store.order.updateProductInOrder(params);
|
|
1664
1627
|
await this.refreshItemRuleQuantityLimits();
|
|
1665
1628
|
await this.refreshCartValidationPassed();
|
|
1666
|
-
this.logMethodSuccess(
|
|
1629
|
+
this.logMethodSuccess('updateProductInOrder', {
|
|
1667
1630
|
productCount: products.length
|
|
1668
1631
|
});
|
|
1669
1632
|
return products;
|
|
1670
1633
|
} catch (error) {
|
|
1671
|
-
this.logMethodError(
|
|
1634
|
+
this.logMethodError('updateProductInOrder', error);
|
|
1672
1635
|
throw error;
|
|
1673
1636
|
}
|
|
1674
1637
|
}
|
|
1675
1638
|
async removeProductFromOrder(identity) {
|
|
1676
|
-
|
|
1677
|
-
this.logMethodStart("removeProductFromOrder", {
|
|
1639
|
+
this.logMethodStart('removeProductFromOrder', {
|
|
1678
1640
|
product_id: identity.product_id,
|
|
1679
1641
|
product_variant_id: identity.product_variant_id
|
|
1680
1642
|
});
|
|
1681
1643
|
try {
|
|
1682
|
-
if (!this.store.order)
|
|
1683
|
-
|
|
1684
|
-
const tempOrder = ((_b = (_a = this.store.order).getTempOrder) == null ? void 0 : _b.call(_a)) || ((_d = (_c = this.store.order).ensureTempOrder) == null ? void 0 : _d.call(_c));
|
|
1644
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1645
|
+
const tempOrder = this.store.order.getTempOrder?.() || this.store.order.ensureTempOrder?.();
|
|
1685
1646
|
const products = await this.store.order.removeProductFromOrder(identity);
|
|
1686
|
-
if (
|
|
1687
|
-
const venueProductUids =
|
|
1688
|
-
const venueBookingUids =
|
|
1647
|
+
if (tempOrder?.bookings?.length) {
|
|
1648
|
+
const venueProductUids = new Set();
|
|
1649
|
+
const venueBookingUids = new Set();
|
|
1689
1650
|
for (const product of tempOrder.products || []) {
|
|
1690
|
-
if (!
|
|
1691
|
-
|
|
1692
|
-
if (product.
|
|
1693
|
-
venueProductUids.add(String(product.identity_key));
|
|
1694
|
-
if ((_g = product.metadata) == null ? void 0 : _g.booking_uid) {
|
|
1651
|
+
if (!product?.metadata?.venue_booking) continue;
|
|
1652
|
+
if (product.identity_key) venueProductUids.add(String(product.identity_key));
|
|
1653
|
+
if (product.metadata?.booking_uid) {
|
|
1695
1654
|
venueBookingUids.add(String(product.metadata.booking_uid));
|
|
1696
1655
|
}
|
|
1697
1656
|
}
|
|
1698
|
-
const beforeBookingCount =
|
|
1699
|
-
tempOrder.bookings = (tempOrder.bookings || []).filter(
|
|
1700
|
-
|
|
1701
|
-
if (!((_a2 = booking == null ? void 0 : booking.metadata) == null ? void 0 : _a2.venue_booking))
|
|
1702
|
-
return true;
|
|
1657
|
+
const beforeBookingCount = tempOrder.bookings?.length || 0;
|
|
1658
|
+
tempOrder.bookings = (tempOrder.bookings || []).filter(booking => {
|
|
1659
|
+
if (!booking?.metadata?.venue_booking) return true;
|
|
1703
1660
|
if (booking.product_uid) {
|
|
1704
1661
|
return venueProductUids.has(String(booking.product_uid));
|
|
1705
1662
|
}
|
|
1706
|
-
const bookingUid =
|
|
1707
|
-
if (bookingUid)
|
|
1708
|
-
return venueBookingUids.has(String(bookingUid));
|
|
1663
|
+
const bookingUid = booking.metadata?.unique_identification_number;
|
|
1664
|
+
if (bookingUid) return venueBookingUids.has(String(bookingUid));
|
|
1709
1665
|
return true;
|
|
1710
1666
|
});
|
|
1711
|
-
if ((
|
|
1712
|
-
|
|
1667
|
+
if ((tempOrder.bookings?.length || 0) !== beforeBookingCount) {
|
|
1668
|
+
this.store.order.persistTempOrder?.();
|
|
1713
1669
|
}
|
|
1714
1670
|
}
|
|
1715
1671
|
await this.refreshItemRuleQuantityLimits();
|
|
1716
1672
|
await this.refreshCartValidationPassed();
|
|
1717
|
-
this.logMethodSuccess(
|
|
1673
|
+
this.logMethodSuccess('removeProductFromOrder', {
|
|
1718
1674
|
productCount: products.length
|
|
1719
1675
|
});
|
|
1720
1676
|
return products;
|
|
1721
1677
|
} catch (error) {
|
|
1722
|
-
this.logMethodError(
|
|
1678
|
+
this.logMethodError('removeProductFromOrder', error);
|
|
1723
1679
|
throw error;
|
|
1724
1680
|
}
|
|
1725
1681
|
}
|
|
1726
1682
|
async getProductList() {
|
|
1727
1683
|
if (this.productsLoaded) {
|
|
1728
|
-
return (0,
|
|
1729
|
-
this.getAddonProductsList(),
|
|
1730
|
-
this.store.itemRuleQuantityLimits || []
|
|
1731
|
-
);
|
|
1684
|
+
return (0, _utils.attachItemRuleLimitsToTopLevelProducts)(this.getAddonProductsList(), this.store.itemRuleQuantityLimits || []);
|
|
1732
1685
|
}
|
|
1733
1686
|
const result = await this.loadAllProducts();
|
|
1734
|
-
return (0,
|
|
1735
|
-
result.addonProducts,
|
|
1736
|
-
this.store.itemRuleQuantityLimits || []
|
|
1737
|
-
);
|
|
1687
|
+
return (0, _utils.attachItemRuleLimitsToTopLevelProducts)(result.addonProducts, this.store.itemRuleQuantityLimits || []);
|
|
1738
1688
|
}
|
|
1689
|
+
|
|
1739
1690
|
// ─── ItemRule 引擎 ───
|
|
1691
|
+
|
|
1740
1692
|
async loadOpenDataConfig() {
|
|
1741
|
-
if (!this.store.openData)
|
|
1742
|
-
throw new Error("openData 模块未初始化");
|
|
1693
|
+
if (!this.store.openData) throw new Error('openData 模块未初始化');
|
|
1743
1694
|
const lastFetchedAt = this.store.openData.getLastFetchedAt();
|
|
1744
1695
|
const cachedData = this.store.openData.getOpenData();
|
|
1745
|
-
if (cachedData && lastFetchedAt && Date.now() - lastFetchedAt <
|
|
1696
|
+
if (cachedData && lastFetchedAt && Date.now() - lastFetchedAt < VenueBookingImpl.OPEN_DATA_CACHE_TTL) {
|
|
1746
1697
|
this.otherParams.openData = cachedData;
|
|
1747
1698
|
return cachedData;
|
|
1748
1699
|
}
|
|
1749
|
-
if (this.loadOpenDataConfigInFlight)
|
|
1750
|
-
return await this.loadOpenDataConfigInFlight;
|
|
1700
|
+
if (this.loadOpenDataConfigInFlight) return await this.loadOpenDataConfigInFlight;
|
|
1751
1701
|
this.loadOpenDataConfigInFlight = this.store.openData.fetchOpenData({
|
|
1752
|
-
scope:
|
|
1753
|
-
target:
|
|
1702
|
+
scope: 'board',
|
|
1703
|
+
target: 'venue_booking+online_store',
|
|
1754
1704
|
section_code: [...OPEN_DATA_SECTION_CODES]
|
|
1755
1705
|
});
|
|
1756
1706
|
try {
|
|
@@ -1764,52 +1714,53 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1764
1714
|
async loadRuntimeConfigs() {
|
|
1765
1715
|
await this.loadOpenDataConfig();
|
|
1766
1716
|
const itemRuleConfigs = await this.ensureItemRuleConfigsLoaded();
|
|
1767
|
-
this.logMethodSuccess(
|
|
1717
|
+
this.logMethodSuccess('loadRuntimeConfigs', {
|
|
1768
1718
|
itemRuleCount: itemRuleConfigs.length
|
|
1769
1719
|
});
|
|
1770
|
-
return {
|
|
1720
|
+
return {
|
|
1721
|
+
itemRuleConfigs
|
|
1722
|
+
};
|
|
1771
1723
|
}
|
|
1772
1724
|
async fetchItemRuleConfigsByModelIds(strategyModelIds) {
|
|
1773
|
-
this.logMethodStart(
|
|
1774
|
-
|
|
1775
|
-
|
|
1725
|
+
this.logMethodStart('fetchItemRuleConfigsByModelIds', {
|
|
1726
|
+
strategyModelIds
|
|
1727
|
+
});
|
|
1728
|
+
if (!strategyModelIds.length) return [];
|
|
1776
1729
|
try {
|
|
1777
|
-
const result = await this.request.get(
|
|
1730
|
+
const result = await this.request.get('/promotion', {
|
|
1778
1731
|
skip: 1,
|
|
1779
1732
|
num: 99,
|
|
1780
|
-
status:
|
|
1733
|
+
status: 'active',
|
|
1781
1734
|
ids: strategyModelIds
|
|
1782
1735
|
});
|
|
1783
1736
|
let configs = [];
|
|
1784
1737
|
if (result.code === 200) {
|
|
1785
|
-
configs = result.data.list.map(
|
|
1738
|
+
configs = result.data.list.map(item => item.metadata);
|
|
1786
1739
|
}
|
|
1787
|
-
this.logMethodSuccess(
|
|
1740
|
+
this.logMethodSuccess('fetchItemRuleConfigsByModelIds', {
|
|
1788
1741
|
strategyModelIds,
|
|
1789
1742
|
strategyCount: configs.length
|
|
1790
1743
|
});
|
|
1791
1744
|
return configs;
|
|
1792
1745
|
} catch (error) {
|
|
1793
|
-
this.logMethodError(
|
|
1746
|
+
this.logMethodError('fetchItemRuleConfigsByModelIds', error, {
|
|
1747
|
+
strategyModelIds
|
|
1748
|
+
});
|
|
1794
1749
|
return [];
|
|
1795
1750
|
}
|
|
1796
1751
|
}
|
|
1797
1752
|
async buildPrefillProductSourceMap() {
|
|
1798
|
-
const sourceMap =
|
|
1753
|
+
const sourceMap = new Map();
|
|
1799
1754
|
try {
|
|
1800
1755
|
const productList = await this.getProductList();
|
|
1801
|
-
if (!Array.isArray(productList))
|
|
1802
|
-
|
|
1803
|
-
const
|
|
1804
|
-
|
|
1805
|
-
if (
|
|
1806
|
-
return;
|
|
1807
|
-
if (visited.has(value))
|
|
1808
|
-
return;
|
|
1756
|
+
if (!Array.isArray(productList)) return sourceMap;
|
|
1757
|
+
const visited = new Set();
|
|
1758
|
+
const collectFromValue = value => {
|
|
1759
|
+
if (!value || typeof value !== 'object') return;
|
|
1760
|
+
if (visited.has(value)) return;
|
|
1809
1761
|
visited.add(value);
|
|
1810
1762
|
if (Array.isArray(value)) {
|
|
1811
|
-
for (const item of value)
|
|
1812
|
-
collectFromValue(item);
|
|
1763
|
+
for (const item of value) collectFromValue(item);
|
|
1813
1764
|
return;
|
|
1814
1765
|
}
|
|
1815
1766
|
const node = value;
|
|
@@ -1818,18 +1769,16 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1818
1769
|
if (Number.isFinite(productId) && productId > 0) {
|
|
1819
1770
|
const productVariantId = Number(node.product_variant_id ?? node.variant_id ?? 0);
|
|
1820
1771
|
const normalizedVariantId = Number.isNaN(productVariantId) ? 0 : productVariantId;
|
|
1821
|
-
const key = (0,
|
|
1822
|
-
if (!sourceMap.has(key))
|
|
1823
|
-
sourceMap.set(key, node);
|
|
1772
|
+
const key = (0, _utils.buildProductKey)(productId, normalizedVariantId);
|
|
1773
|
+
if (!sourceMap.has(key)) sourceMap.set(key, node);
|
|
1824
1774
|
}
|
|
1825
1775
|
for (const childValue of Object.values(node)) {
|
|
1826
|
-
if (childValue && typeof childValue ===
|
|
1827
|
-
collectFromValue(childValue);
|
|
1776
|
+
if (childValue && typeof childValue === 'object') collectFromValue(childValue);
|
|
1828
1777
|
}
|
|
1829
1778
|
};
|
|
1830
1779
|
collectFromValue(productList);
|
|
1831
1780
|
} catch (error) {
|
|
1832
|
-
this.logMethodError(
|
|
1781
|
+
this.logMethodError('buildPrefillProductSourceMap', error);
|
|
1833
1782
|
}
|
|
1834
1783
|
return sourceMap;
|
|
1835
1784
|
}
|
|
@@ -1837,13 +1786,11 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1837
1786
|
return this.itemRuleRuntimeConfig || {};
|
|
1838
1787
|
}
|
|
1839
1788
|
async ensureItemRuleConfigsLoaded() {
|
|
1840
|
-
if (this.itemRuleConfigs.length > 0)
|
|
1841
|
-
|
|
1842
|
-
if (this.itemRuleConfigsPromise)
|
|
1843
|
-
return this.itemRuleConfigsPromise;
|
|
1789
|
+
if (this.itemRuleConfigs.length > 0) return this.itemRuleConfigs;
|
|
1790
|
+
if (this.itemRuleConfigsPromise) return this.itemRuleConfigsPromise;
|
|
1844
1791
|
this.itemRuleConfigsPromise = (async () => {
|
|
1845
1792
|
const runtimeConfig = this.getItemRuleRuntimeConfig();
|
|
1846
|
-
const staticConfigs = (0,
|
|
1793
|
+
const staticConfigs = (0, _utils.normalizeItemRuleStrategies)(runtimeConfig.strategyConfigs);
|
|
1847
1794
|
if (staticConfigs.length > 0) {
|
|
1848
1795
|
this.itemRuleConfigs = staticConfigs;
|
|
1849
1796
|
this.itemRuleEvaluator.setStrategyConfigs(staticConfigs);
|
|
@@ -1862,31 +1809,29 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1862
1809
|
this.store.itemRuleQuantityLimits = [];
|
|
1863
1810
|
return [];
|
|
1864
1811
|
}
|
|
1865
|
-
const businessData = (0,
|
|
1812
|
+
const businessData = (0, _utils.buildItemRuleBusinessData)({
|
|
1866
1813
|
tempOrder: this.ensureTempOrder(),
|
|
1867
1814
|
runtimeConfig: this.getItemRuleRuntimeConfig(),
|
|
1868
1815
|
itemRuleConfigs: this.itemRuleConfigs
|
|
1869
1816
|
});
|
|
1870
1817
|
const limits = this.itemRuleEvaluator.getQuantityLimits(businessData);
|
|
1871
1818
|
this.store.itemRuleQuantityLimits = limits;
|
|
1872
|
-
this.logMethodSuccess(
|
|
1819
|
+
this.logMethodSuccess('refreshItemRuleQuantityLimits', {
|
|
1820
|
+
limitCount: limits.length
|
|
1821
|
+
});
|
|
1873
1822
|
return limits;
|
|
1874
1823
|
} catch (error) {
|
|
1875
1824
|
this.store.itemRuleQuantityLimits = [];
|
|
1876
|
-
this.logMethodError(
|
|
1825
|
+
this.logMethodError('refreshItemRuleQuantityLimits', error);
|
|
1877
1826
|
return [];
|
|
1878
1827
|
}
|
|
1879
1828
|
}
|
|
1880
1829
|
async applyPrefillByItemRule() {
|
|
1881
|
-
|
|
1882
|
-
if (this.
|
|
1883
|
-
return;
|
|
1884
|
-
if (!this.store.order)
|
|
1885
|
-
return;
|
|
1830
|
+
if (this.itemRulePrefillApplied) return;
|
|
1831
|
+
if (!this.store.order) return;
|
|
1886
1832
|
const strategyConfigs = await this.ensureItemRuleConfigsLoaded();
|
|
1887
|
-
if (!strategyConfigs.length)
|
|
1888
|
-
|
|
1889
|
-
const businessData = (0, import_utils.buildItemRuleBusinessData)({
|
|
1833
|
+
if (!strategyConfigs.length) return;
|
|
1834
|
+
const businessData = (0, _utils.buildItemRuleBusinessData)({
|
|
1890
1835
|
tempOrder: this.ensureTempOrder(),
|
|
1891
1836
|
runtimeConfig: this.getItemRuleRuntimeConfig(),
|
|
1892
1837
|
itemRuleConfigs: this.itemRuleConfigs
|
|
@@ -1902,69 +1847,86 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1902
1847
|
for (const prefillItem of prefillItems) {
|
|
1903
1848
|
const productId = Number(prefillItem.product_id);
|
|
1904
1849
|
const productVariantId = Number(prefillItem.product_variant_id ?? 0);
|
|
1905
|
-
const targetQuantity = (0,
|
|
1906
|
-
if (!Number.isFinite(productId) || targetQuantity <= 0)
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
const sourceItem = productSourceMap.get((0, import_utils.buildProductKey)(productId, productVariantId)) || productSourceMap.get((0, import_utils.buildProductKey)(productId, 0)) || null;
|
|
1911
|
-
const productIndex = (0, import_utils.getProductIdentityIndex)(tempOrder.products, {
|
|
1850
|
+
const targetQuantity = (0, _utils.toNonNegativeInt)(prefillItem.quantity);
|
|
1851
|
+
if (!Number.isFinite(productId) || targetQuantity <= 0) continue;
|
|
1852
|
+
if (Number.isNaN(productVariantId)) continue;
|
|
1853
|
+
const sourceItem = productSourceMap.get((0, _utils.buildProductKey)(productId, productVariantId)) || productSourceMap.get((0, _utils.buildProductKey)(productId, 0)) || null;
|
|
1854
|
+
const productIndex = (0, _utils.getProductIdentityIndex)(tempOrder.products, {
|
|
1912
1855
|
product_id: productId,
|
|
1913
1856
|
product_variant_id: productVariantId
|
|
1914
1857
|
});
|
|
1915
1858
|
if (productIndex === -1) {
|
|
1916
|
-
const sellingPrice = (0,
|
|
1917
|
-
tempOrder.products.push(
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
}
|
|
1927
|
-
|
|
1859
|
+
const sellingPrice = (0, _utils.toPriceString)(sourceItem?.price ?? sourceItem?.selling_price, '0.00');
|
|
1860
|
+
tempOrder.products.push((0, _utils.normalizeOrderProduct)({
|
|
1861
|
+
product_id: productId,
|
|
1862
|
+
product_variant_id: productVariantId,
|
|
1863
|
+
num: targetQuantity,
|
|
1864
|
+
selling_price: sellingPrice,
|
|
1865
|
+
original_price: sellingPrice,
|
|
1866
|
+
metadata: {
|
|
1867
|
+
item_rule_prefill: true,
|
|
1868
|
+
item_rule_id: prefillItem.ruleId
|
|
1869
|
+
},
|
|
1870
|
+
_origin: {
|
|
1871
|
+
...(sourceItem || {}),
|
|
1872
|
+
item_rule_prefill: true,
|
|
1873
|
+
item_rule_id: prefillItem.ruleId
|
|
1874
|
+
}
|
|
1875
|
+
}));
|
|
1928
1876
|
hasChanges = true;
|
|
1929
1877
|
continue;
|
|
1930
1878
|
}
|
|
1931
1879
|
const targetProduct = tempOrder.products[productIndex];
|
|
1932
|
-
const existedQuantity = (0,
|
|
1880
|
+
const existedQuantity = (0, _utils.toNonNegativeInt)(targetProduct.num);
|
|
1933
1881
|
const delta = targetQuantity - existedQuantity;
|
|
1934
1882
|
const nextProduct = {
|
|
1935
1883
|
...targetProduct,
|
|
1936
|
-
...delta > 0 ? {
|
|
1937
|
-
|
|
1938
|
-
|
|
1884
|
+
...(delta > 0 ? {
|
|
1885
|
+
num: (0, _utils.getSafeProductNum)(existedQuantity + delta)
|
|
1886
|
+
} : {}),
|
|
1887
|
+
metadata: {
|
|
1888
|
+
...(targetProduct.metadata || {}),
|
|
1889
|
+
item_rule_prefill: true,
|
|
1890
|
+
item_rule_id: prefillItem.ruleId
|
|
1891
|
+
},
|
|
1892
|
+
_origin: sourceItem ? {
|
|
1893
|
+
...(targetProduct._origin || {}),
|
|
1894
|
+
...sourceItem
|
|
1895
|
+
} : targetProduct._origin
|
|
1939
1896
|
};
|
|
1940
|
-
if (delta > 0 || Boolean(sourceItem && (!targetProduct._origin ||
|
|
1897
|
+
if (delta > 0 || Boolean(sourceItem && (!targetProduct._origin || targetProduct._origin?.price !== sourceItem?.price))) {
|
|
1941
1898
|
tempOrder.products[productIndex] = nextProduct;
|
|
1942
1899
|
hasChanges = true;
|
|
1943
1900
|
}
|
|
1944
1901
|
}
|
|
1945
1902
|
if (hasChanges) {
|
|
1903
|
+
// Prefill 属于 products CRUD 的一种形式:新增后让 Rules 重算,以支持自动应用可用优惠券。
|
|
1946
1904
|
this.store.order.applyDiscount();
|
|
1947
|
-
await this.store.order.recalculateSummary({
|
|
1905
|
+
await this.store.order.recalculateSummary({
|
|
1906
|
+
createIfMissing: true
|
|
1907
|
+
});
|
|
1948
1908
|
this.store.order.persistTempOrder();
|
|
1949
1909
|
}
|
|
1950
1910
|
await this.refreshItemRuleQuantityLimits();
|
|
1951
1911
|
this.itemRulePrefillApplied = true;
|
|
1952
|
-
this.logMethodSuccess(
|
|
1912
|
+
this.logMethodSuccess('applyPrefillByItemRule', {
|
|
1953
1913
|
prefillCount: prefillItems.length,
|
|
1954
1914
|
hasChanges
|
|
1955
1915
|
});
|
|
1956
1916
|
}
|
|
1957
1917
|
async applyItemRulePrefill() {
|
|
1958
|
-
this.logMethodStart(
|
|
1918
|
+
this.logMethodStart('applyItemRulePrefill');
|
|
1959
1919
|
await this.applyPrefillByItemRule();
|
|
1960
1920
|
await this.refreshItemRuleQuantityLimits();
|
|
1961
1921
|
await this.refreshCartValidationPassed();
|
|
1962
1922
|
}
|
|
1963
1923
|
async evaluateCartValidationByItemRule() {
|
|
1964
1924
|
const strategyConfigs = await this.ensureItemRuleConfigsLoaded();
|
|
1965
|
-
if (!strategyConfigs.length)
|
|
1966
|
-
|
|
1967
|
-
|
|
1925
|
+
if (!strategyConfigs.length) return {
|
|
1926
|
+
passed: true,
|
|
1927
|
+
failures: []
|
|
1928
|
+
};
|
|
1929
|
+
const businessData = (0, _utils.buildItemRuleBusinessData)({
|
|
1968
1930
|
tempOrder: this.ensureTempOrder(),
|
|
1969
1931
|
runtimeConfig: this.getItemRuleRuntimeConfig(),
|
|
1970
1932
|
itemRuleConfigs: this.itemRuleConfigs
|
|
@@ -1973,16 +1935,18 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1973
1935
|
}
|
|
1974
1936
|
async validateBeforeSubmitByItemRule() {
|
|
1975
1937
|
const validationResult = await this.evaluateCartValidationByItemRule();
|
|
1976
|
-
if (validationResult.passed)
|
|
1977
|
-
return;
|
|
1938
|
+
if (validationResult.passed) return;
|
|
1978
1939
|
const firstFailure = validationResult.failures[0];
|
|
1979
|
-
const errorMessage =
|
|
1940
|
+
const errorMessage = firstFailure?.validationMessage || '当前购物车未满足商品规则,请调整后再提交';
|
|
1980
1941
|
const error = new Error(String(errorMessage));
|
|
1981
1942
|
error.failures = validationResult.failures;
|
|
1982
1943
|
throw error;
|
|
1983
1944
|
}
|
|
1984
1945
|
async refreshCartValidationPassed() {
|
|
1985
|
-
const previous = this.store.cartValidation || {
|
|
1946
|
+
const previous = this.store.cartValidation || {
|
|
1947
|
+
passed: null,
|
|
1948
|
+
failures: []
|
|
1949
|
+
};
|
|
1986
1950
|
let nextState = {
|
|
1987
1951
|
passed: null,
|
|
1988
1952
|
failures: []
|
|
@@ -1994,12 +1958,15 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1994
1958
|
failures: validationResult.failures || []
|
|
1995
1959
|
};
|
|
1996
1960
|
} catch {
|
|
1997
|
-
nextState = {
|
|
1961
|
+
nextState = {
|
|
1962
|
+
passed: false,
|
|
1963
|
+
failures: []
|
|
1964
|
+
};
|
|
1998
1965
|
}
|
|
1999
1966
|
this.store.cartValidation = nextState;
|
|
2000
1967
|
const changed = previous.passed !== nextState.passed || previous.failures !== nextState.failures;
|
|
2001
1968
|
if (changed) {
|
|
2002
|
-
await this.core.effects.emit(
|
|
1969
|
+
await this.core.effects.emit(_types.VenueBookingHooks.onCartValidationChanged, {
|
|
2003
1970
|
cartValidation: nextState,
|
|
2004
1971
|
cartValidationPassed: nextState.passed
|
|
2005
1972
|
});
|
|
@@ -2007,15 +1974,20 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
2007
1974
|
return nextState.passed;
|
|
2008
1975
|
}
|
|
2009
1976
|
async setItemRuleRuntimeConfig(config = {}) {
|
|
2010
|
-
|
|
2011
|
-
this.logMethodStart("setItemRuleRuntimeConfig");
|
|
1977
|
+
this.logMethodStart('setItemRuleRuntimeConfig');
|
|
2012
1978
|
this.itemRuleRuntimeConfig = {
|
|
2013
1979
|
...this.itemRuleRuntimeConfig,
|
|
2014
1980
|
...config,
|
|
2015
|
-
pax: {
|
|
2016
|
-
|
|
1981
|
+
pax: {
|
|
1982
|
+
...(this.itemRuleRuntimeConfig?.pax || {}),
|
|
1983
|
+
...(config?.pax || {})
|
|
1984
|
+
},
|
|
1985
|
+
custom: {
|
|
1986
|
+
...(this.itemRuleRuntimeConfig?.custom || {}),
|
|
1987
|
+
...(config?.custom || {})
|
|
1988
|
+
}
|
|
2017
1989
|
};
|
|
2018
|
-
if (
|
|
1990
|
+
if ('strategyConfigs' in config) {
|
|
2019
1991
|
this.itemRuleConfigs = [];
|
|
2020
1992
|
this.itemRuleConfigsPromise = null;
|
|
2021
1993
|
this.itemRuleEvaluator.setStrategyConfigs([]);
|
|
@@ -2023,54 +1995,54 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
2023
1995
|
this.itemRulePrefillApplied = false;
|
|
2024
1996
|
await this.refreshItemRuleQuantityLimits();
|
|
2025
1997
|
await this.refreshCartValidationPassed();
|
|
2026
|
-
this.logMethodSuccess(
|
|
1998
|
+
this.logMethodSuccess('setItemRuleRuntimeConfig', {
|
|
2027
1999
|
strategyCount: Array.isArray(this.itemRuleRuntimeConfig.strategyConfigs) ? this.itemRuleRuntimeConfig.strategyConfigs.length : 0
|
|
2028
2000
|
});
|
|
2029
2001
|
}
|
|
2030
2002
|
getOtherParams() {
|
|
2031
2003
|
return this.otherParams;
|
|
2032
2004
|
}
|
|
2005
|
+
|
|
2006
|
+
// ─── UI 状态缓存(按 cacheId 分桶,sessionStorage) ───
|
|
2007
|
+
//
|
|
2008
|
+
// 用于物料层持久化 UI 层面的轻量状态(如当前步骤、登录回跳意图等)。
|
|
2009
|
+
// 桶键:pisell.venueBooking.uiState:<cacheId>;内部以 JSON object 形式存储多个字段。
|
|
2010
|
+
// 无 cacheId 时所有方法自动降级为 no-op,上层不用判空。
|
|
2011
|
+
|
|
2012
|
+
static UI_STATE_KEY_PREFIX = 'pisell.venueBooking.uiState:';
|
|
2033
2013
|
getUIStateBucketKey() {
|
|
2034
|
-
if (!this.cacheId)
|
|
2035
|
-
|
|
2036
|
-
return `${_VenueBookingImpl.UI_STATE_KEY_PREFIX}${this.cacheId}`;
|
|
2014
|
+
if (!this.cacheId) return null;
|
|
2015
|
+
return `${VenueBookingImpl.UI_STATE_KEY_PREFIX}${this.cacheId}`;
|
|
2037
2016
|
}
|
|
2038
2017
|
readUIStateBucket() {
|
|
2039
|
-
var _a;
|
|
2040
2018
|
const key = this.getUIStateBucketKey();
|
|
2041
|
-
if (!key || !
|
|
2042
|
-
return {};
|
|
2019
|
+
if (!key || !this.window?.sessionStorage) return {};
|
|
2043
2020
|
try {
|
|
2044
|
-
const raw = this.window.sessionStorage.getItem(key) ||
|
|
2021
|
+
const raw = this.window.sessionStorage.getItem(key) || '{}';
|
|
2045
2022
|
const parsed = JSON.parse(raw);
|
|
2046
|
-
return parsed && typeof parsed ===
|
|
2023
|
+
return parsed && typeof parsed === 'object' ? parsed : {};
|
|
2047
2024
|
} catch {
|
|
2048
2025
|
return {};
|
|
2049
2026
|
}
|
|
2050
2027
|
}
|
|
2051
2028
|
writeUIStateBucket(bucket) {
|
|
2052
|
-
var _a;
|
|
2053
2029
|
const key = this.getUIStateBucketKey();
|
|
2054
|
-
if (!key || !
|
|
2055
|
-
return;
|
|
2030
|
+
if (!key || !this.window?.sessionStorage) return;
|
|
2056
2031
|
this.window.sessionStorage.setItem(key, JSON.stringify(bucket));
|
|
2057
2032
|
}
|
|
2058
2033
|
setUIState(key, value) {
|
|
2059
|
-
if (!this.getUIStateBucketKey())
|
|
2060
|
-
return;
|
|
2034
|
+
if (!this.getUIStateBucketKey()) return;
|
|
2061
2035
|
const bucket = this.readUIStateBucket();
|
|
2062
2036
|
bucket[key] = value;
|
|
2063
2037
|
this.writeUIStateBucket(bucket);
|
|
2064
2038
|
}
|
|
2065
2039
|
getUIState(key) {
|
|
2066
|
-
if (!this.getUIStateBucketKey())
|
|
2067
|
-
return void 0;
|
|
2040
|
+
if (!this.getUIStateBucketKey()) return undefined;
|
|
2068
2041
|
const bucket = this.readUIStateBucket();
|
|
2069
2042
|
return bucket[key];
|
|
2070
2043
|
}
|
|
2071
2044
|
deleteUIState(key) {
|
|
2072
|
-
if (!this.getUIStateBucketKey())
|
|
2073
|
-
return;
|
|
2045
|
+
if (!this.getUIStateBucketKey()) return;
|
|
2074
2046
|
const bucket = this.readUIStateBucket();
|
|
2075
2047
|
if (key in bucket) {
|
|
2076
2048
|
delete bucket[key];
|
|
@@ -2078,84 +2050,69 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
2078
2050
|
}
|
|
2079
2051
|
}
|
|
2080
2052
|
setBookingHolder(bookingUid, holder) {
|
|
2081
|
-
|
|
2082
|
-
if (!this.store.order)
|
|
2083
|
-
return;
|
|
2053
|
+
if (!this.store.order) return;
|
|
2084
2054
|
const tempOrder = this.store.order.ensureTempOrder();
|
|
2085
|
-
const booking =
|
|
2086
|
-
(b) => {
|
|
2087
|
-
var _a2;
|
|
2088
|
-
return ((_a2 = b.metadata) == null ? void 0 : _a2.unique_identification_number) === bookingUid;
|
|
2089
|
-
}
|
|
2090
|
-
);
|
|
2055
|
+
const booking = tempOrder.bookings?.find(b => b.metadata?.unique_identification_number === bookingUid);
|
|
2091
2056
|
if (booking) {
|
|
2092
2057
|
booking.holder = holder;
|
|
2093
2058
|
}
|
|
2094
2059
|
for (const product of tempOrder.products) {
|
|
2095
|
-
const productBookingUid =
|
|
2096
|
-
if (String(productBookingUid) !== String(bookingUid))
|
|
2097
|
-
|
|
2098
|
-
const origin = product._origin && typeof product._origin === "object" ? product._origin : {};
|
|
2060
|
+
const productBookingUid = product.metadata?.booking_uid ?? product._origin?.product?.bookingUuid;
|
|
2061
|
+
if (String(productBookingUid) !== String(bookingUid)) continue;
|
|
2062
|
+
const origin = product._origin && typeof product._origin === 'object' ? product._origin : {};
|
|
2099
2063
|
origin.holder = holder;
|
|
2100
2064
|
product._origin = origin;
|
|
2101
2065
|
}
|
|
2102
2066
|
this.store.order.notifyTempOrderChanged();
|
|
2103
2067
|
}
|
|
2068
|
+
|
|
2104
2069
|
/**
|
|
2105
2070
|
* 获取 holder 表单 map
|
|
2106
2071
|
*/
|
|
2107
2072
|
getHolderFormMap() {
|
|
2108
|
-
if (!this.store.holder)
|
|
2109
|
-
throw new Error("[VenueBooking] holder 模块未初始化");
|
|
2073
|
+
if (!this.store.holder) throw new Error('[VenueBooking] holder 模块未初始化');
|
|
2110
2074
|
return this.store.holder.getHolderFormMap();
|
|
2111
2075
|
}
|
|
2076
|
+
|
|
2112
2077
|
/**
|
|
2113
2078
|
* UI 层触发:按当前 holderMap 批量刷新所有表单的 records
|
|
2114
2079
|
*/
|
|
2115
2080
|
async refreshAllHolderFormRecords(params) {
|
|
2116
|
-
if (!this.store.holder)
|
|
2117
|
-
|
|
2118
|
-
const customer_id = (params == null ? void 0 : params.customer_id) ?? this.resolveHolderCustomerId();
|
|
2081
|
+
if (!this.store.holder) throw new Error('[VenueBooking] holder 模块未初始化');
|
|
2082
|
+
const customer_id = params?.customer_id ?? this.resolveHolderCustomerId();
|
|
2119
2083
|
return this.store.holder.refreshAllFormRecords({
|
|
2120
2084
|
...params,
|
|
2121
2085
|
customer_id,
|
|
2122
|
-
useCache:
|
|
2086
|
+
useCache: params?.useCache ?? false
|
|
2123
2087
|
});
|
|
2124
2088
|
}
|
|
2089
|
+
|
|
2125
2090
|
/**
|
|
2126
2091
|
* 添加表单记录
|
|
2127
2092
|
*/
|
|
2128
2093
|
appendFormRecord(params) {
|
|
2129
|
-
if (!this.store.holder)
|
|
2130
|
-
throw new Error("[VenueBooking] holder 模块未初始化");
|
|
2094
|
+
if (!this.store.holder) throw new Error('[VenueBooking] holder 模块未初始化');
|
|
2131
2095
|
return this.store.holder.appendFormRecord(params);
|
|
2132
2096
|
}
|
|
2097
|
+
|
|
2133
2098
|
// ─── OpenData 可用性 ───
|
|
2099
|
+
|
|
2134
2100
|
async checkOpenDataAvailability() {
|
|
2135
|
-
if (!this.store.openData)
|
|
2136
|
-
throw new Error("openData 模块未初始化");
|
|
2101
|
+
if (!this.store.openData) throw new Error('openData 模块未初始化');
|
|
2137
2102
|
await this.loadOpenDataConfig();
|
|
2138
2103
|
return this.store.openData.checkAvailability(this.store.schedule);
|
|
2139
2104
|
}
|
|
2140
|
-
async setOtherParams(params, {
|
|
2105
|
+
async setOtherParams(params, {
|
|
2106
|
+
cover = false
|
|
2107
|
+
} = {}) {
|
|
2141
2108
|
if (cover) {
|
|
2142
2109
|
this.otherParams = params;
|
|
2143
2110
|
} else {
|
|
2144
|
-
this.otherParams = {
|
|
2111
|
+
this.otherParams = {
|
|
2112
|
+
...this.otherParams,
|
|
2113
|
+
...params
|
|
2114
|
+
};
|
|
2145
2115
|
}
|
|
2146
2116
|
}
|
|
2147
|
-
}
|
|
2148
|
-
|
|
2149
|
-
VenueBookingImpl.OPEN_DATA_CACHE_TTL = 5 * 60 * 1e3;
|
|
2150
|
-
VenueBookingImpl.PISELL1_LOGIN_SUCCESS = "pisell1.login.success";
|
|
2151
|
-
// ─── UI 状态缓存(按 cacheId 分桶,sessionStorage) ───
|
|
2152
|
-
//
|
|
2153
|
-
// 用于物料层持久化 UI 层面的轻量状态(如当前步骤、登录回跳意图等)。
|
|
2154
|
-
// 桶键:pisell.venueBooking.uiState:<cacheId>;内部以 JSON object 形式存储多个字段。
|
|
2155
|
-
// 无 cacheId 时所有方法自动降级为 no-op,上层不用判空。
|
|
2156
|
-
VenueBookingImpl.UI_STATE_KEY_PREFIX = "pisell.venueBooking.uiState:";
|
|
2157
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
2158
|
-
0 && (module.exports = {
|
|
2159
|
-
VenueBookingImpl,
|
|
2160
|
-
...require("./types")
|
|
2161
|
-
});
|
|
2117
|
+
}
|
|
2118
|
+
exports.VenueBookingImpl = VenueBookingImpl;
|