@pisell/pisellos 2.2.314 → 2.2.315
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/index.d.ts +2 -0
- package/dist/index.js +3 -1
- package/dist/model/strategy/adapter/itemRule/adapter.d.ts +3 -1
- package/dist/model/strategy/adapter/itemRule/adapter.js +74 -7
- package/dist/model/strategy/adapter/itemRule/evaluator.d.ts +3 -1
- package/dist/model/strategy/adapter/itemRule/evaluator.js +13 -0
- package/dist/model/strategy/adapter/itemRule/type.d.ts +40 -1
- package/dist/model/strategy/adapter/itemRule/type.js +10 -0
- package/dist/modules/BookingContext/utils/productExtend.d.ts +7 -0
- package/dist/modules/BookingContext/utils/productExtend.js +62 -18
- package/dist/modules/BookingContext/utils/resources.js +1 -1
- package/dist/modules/BusinessAvailability/index.d.ts +30 -0
- package/dist/modules/BusinessAvailability/index.js +204 -0
- package/dist/modules/Cart/index.js +4 -3
- package/dist/modules/Cart/types.d.ts +2 -0
- package/dist/modules/Cart/utils/cartProduct.d.ts +3 -1
- package/dist/modules/Cart/utils/cartProduct.js +59 -32
- package/dist/modules/FulfillmentTiming/index.d.ts +11 -0
- package/dist/modules/FulfillmentTiming/index.js +407 -0
- package/dist/modules/FulfillmentTiming/types.d.ts +67 -0
- package/dist/modules/FulfillmentTiming/types.js +1 -0
- package/dist/modules/OpenData/types.d.ts +14 -0
- package/dist/modules/Order/index.d.ts +14 -2
- package/dist/modules/Order/index.js +856 -486
- package/dist/modules/Order/localEftposState.d.ts +13 -0
- package/dist/modules/Order/localEftposState.js +39 -0
- package/dist/modules/Order/pickupTiming.d.ts +46 -0
- package/dist/modules/Order/pickupTiming.js +53 -0
- package/dist/modules/Order/types.d.ts +30 -2
- package/dist/modules/Order/utils.js +25 -7
- package/dist/modules/Payment/index.js +9 -10
- package/dist/modules/Product/types.d.ts +11 -0
- package/dist/modules/ProductList/index.js +1 -1
- package/dist/modules/ResourcePlanner/planner.d.ts +2 -0
- package/dist/modules/ResourcePlanner/planner.js +332 -23
- package/dist/modules/ResourcePlanner/types.d.ts +29 -0
- package/dist/modules/Schedule/index.d.ts +8 -0
- package/dist/modules/Schedule/index.js +141 -39
- package/dist/modules/index.d.ts +1 -0
- package/dist/modules/index.js +1 -0
- package/dist/plugins/request.d.ts +7 -0
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +1536 -1309
- package/dist/server/modules/form/index.d.ts +19 -0
- package/dist/server/modules/form/index.js +205 -0
- package/dist/server/modules/form/types.d.ts +13 -0
- package/dist/server/modules/form/types.js +3 -0
- package/dist/server/modules/index.d.ts +3 -0
- package/dist/server/modules/index.js +4 -0
- package/dist/server/modules/order/index.d.ts +15 -0
- package/dist/server/modules/order/index.js +920 -688
- package/dist/server/modules/order/types.d.ts +1 -0
- package/dist/server/test.json +1 -1
- package/dist/server/utils/small-ticket.d.ts +1 -85
- package/dist/server/utils/small-ticket.js +2 -2542
- package/dist/shared/payment/loadPaymentMethods.d.ts +9 -0
- package/dist/shared/payment/loadPaymentMethods.js +66 -0
- package/dist/shared/receipt/customerInvoiceLanguages.d.ts +8 -0
- package/dist/shared/receipt/customerInvoiceLanguages.js +60 -0
- package/dist/shared/receipt/loadCustomerInvoiceLayout.d.ts +27 -0
- package/dist/shared/receipt/loadCustomerInvoiceLayout.js +184 -0
- package/dist/shared/receipt/small-ticket.d.ts +96 -0
- package/dist/shared/receipt/small-ticket.js +2751 -0
- package/dist/shared/receipt/templateVisibility.d.ts +23 -0
- package/dist/shared/receipt/templateVisibility.js +64 -0
- package/dist/shared/sales/loadSalesOrderSnapshot.d.ts +9 -0
- package/dist/shared/sales/loadSalesOrderSnapshot.js +21 -0
- package/dist/solution/BaseSales/fulfillmentItemRules.d.ts +27 -0
- package/dist/solution/BaseSales/fulfillmentItemRules.js +750 -0
- package/dist/solution/BaseSales/index.d.ts +39 -16
- package/dist/solution/BaseSales/index.js +1754 -1154
- package/dist/solution/BaseSales/pickupTiming.d.ts +47 -0
- package/dist/solution/BaseSales/pickupTiming.js +616 -0
- package/dist/solution/BaseSales/types.d.ts +11 -0
- package/dist/solution/BaseSales/utils/parseSalesResponse.js +3 -0
- package/dist/solution/BookingByStep/index.d.ts +3 -1
- package/dist/solution/BookingByStep/index.js +8 -3
- package/dist/solution/BookingTicket/index.d.ts +8 -2
- package/dist/solution/BookingTicket/index.js +513 -436
- package/dist/solution/BookingTicket/utils/addProductDecision.d.ts +0 -1
- package/dist/solution/BookingTicket/utils/addProductDecision.js +1 -1
- package/dist/solution/BookingTicket/utils/cartView.js +3 -1
- package/dist/solution/OrderInvoicePreview/index.d.ts +66 -0
- package/dist/solution/OrderInvoicePreview/index.js +340 -0
- package/dist/solution/RegisterAndLogin/config.js +54 -11
- package/dist/solution/RegisterAndLogin/index.d.ts +2 -0
- package/dist/solution/RegisterAndLogin/index.js +1 -1
- package/dist/solution/RegisterAndLogin/utils.d.ts +12 -4
- package/dist/solution/RegisterAndLogin/utils.js +36 -16
- package/dist/solution/UnifiedBookingSales/businessAvailability.d.ts +27 -0
- package/dist/solution/UnifiedBookingSales/businessAvailability.js +292 -0
- package/dist/solution/UnifiedBookingSales/index.d.ts +36 -4
- package/dist/solution/UnifiedBookingSales/index.js +1714 -905
- package/dist/solution/UnifiedBookingSales/types.d.ts +16 -2
- package/dist/solution/VenueBooking/index.d.ts +15 -2
- package/dist/solution/VenueBooking/index.js +1062 -785
- package/dist/solution/VenueBooking/types.d.ts +2 -1
- package/dist/solution/VenueBooking/types.js +1 -0
- package/dist/solution/VenueBooking/utils/dateSummary.d.ts +1 -0
- package/dist/solution/VenueBooking/utils/dateSummary.js +7 -4
- package/dist/solution/VenueBooking/utils/smartPricing.d.ts +71 -0
- package/dist/solution/VenueBooking/utils/smartPricing.js +273 -0
- package/dist/solution/VenueBooking/utils/timeSlot.d.ts +1 -0
- package/dist/solution/VenueBooking/utils/timeSlot.js +6 -3
- package/dist/solution/index.d.ts +1 -0
- package/dist/solution/index.js +2 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.js +21 -1
- package/lib/model/strategy/adapter/itemRule/adapter.d.ts +3 -1
- package/lib/model/strategy/adapter/itemRule/adapter.js +54 -4
- package/lib/model/strategy/adapter/itemRule/evaluator.d.ts +3 -1
- package/lib/model/strategy/adapter/itemRule/evaluator.js +9 -0
- package/lib/model/strategy/adapter/itemRule/type.d.ts +40 -1
- package/lib/model/strategy/adapter/itemRule/type.js +10 -0
- package/lib/model/strategy/adapter/promotion/index.js +46 -1
- package/lib/modules/BookingContext/utils/productExtend.d.ts +7 -0
- package/lib/modules/BookingContext/utils/productExtend.js +45 -2
- package/lib/modules/BookingContext/utils/resources.js +1 -1
- package/lib/modules/BusinessAvailability/index.d.ts +30 -0
- package/lib/modules/BusinessAvailability/index.js +146 -0
- package/lib/modules/Cart/index.js +4 -2
- package/lib/modules/Cart/types.d.ts +2 -0
- package/lib/modules/Cart/utils/cartProduct.d.ts +3 -1
- package/lib/modules/Cart/utils/cartProduct.js +39 -20
- package/lib/modules/FulfillmentTiming/index.d.ts +11 -0
- package/lib/modules/FulfillmentTiming/index.js +359 -0
- package/lib/modules/FulfillmentTiming/types.d.ts +67 -0
- package/lib/modules/FulfillmentTiming/types.js +5 -0
- package/lib/modules/OpenData/types.d.ts +14 -0
- package/lib/modules/Order/index.d.ts +14 -2
- package/lib/modules/Order/index.js +240 -38
- package/lib/modules/Order/localEftposState.d.ts +13 -0
- package/lib/modules/Order/localEftposState.js +44 -0
- package/lib/modules/Order/pickupTiming.d.ts +46 -0
- package/lib/modules/Order/pickupTiming.js +61 -0
- package/lib/modules/Order/types.d.ts +30 -2
- package/lib/modules/Order/utils.js +21 -5
- package/lib/modules/Payment/index.js +3 -4
- package/lib/modules/Product/types.d.ts +11 -0
- package/lib/modules/ProductList/index.js +1 -1
- package/lib/modules/ResourcePlanner/planner.d.ts +2 -0
- package/lib/modules/ResourcePlanner/planner.js +252 -8
- package/lib/modules/ResourcePlanner/types.d.ts +29 -0
- package/lib/modules/Schedule/index.d.ts +8 -0
- package/lib/modules/Schedule/index.js +68 -12
- package/lib/modules/index.d.ts +1 -0
- package/lib/modules/index.js +11 -0
- package/lib/plugins/request.d.ts +7 -0
- package/lib/server/index.d.ts +1 -0
- package/lib/server/index.js +158 -37
- package/lib/server/modules/form/index.d.ts +19 -0
- package/lib/server/modules/form/index.js +73 -0
- package/lib/server/modules/form/types.d.ts +13 -0
- package/lib/server/modules/form/types.js +9 -0
- package/lib/server/modules/index.d.ts +3 -0
- package/lib/server/modules/index.js +15 -1
- package/lib/server/modules/order/index.d.ts +15 -0
- package/lib/server/modules/order/index.js +114 -3
- package/lib/server/modules/order/types.d.ts +1 -0
- package/lib/server/test.json +1 -1
- package/lib/server/utils/small-ticket.d.ts +1 -85
- package/lib/server/utils/small-ticket.js +9 -2305
- package/lib/shared/payment/loadPaymentMethods.d.ts +9 -0
- package/lib/shared/payment/loadPaymentMethods.js +40 -0
- package/lib/shared/receipt/customerInvoiceLanguages.d.ts +8 -0
- package/lib/shared/receipt/customerInvoiceLanguages.js +58 -0
- package/lib/shared/receipt/loadCustomerInvoiceLayout.d.ts +27 -0
- package/lib/shared/receipt/loadCustomerInvoiceLayout.js +124 -0
- package/lib/shared/receipt/small-ticket.d.ts +96 -0
- package/lib/shared/receipt/small-ticket.js +2546 -0
- package/lib/shared/receipt/templateVisibility.d.ts +23 -0
- package/lib/shared/receipt/templateVisibility.js +63 -0
- package/lib/shared/sales/loadSalesOrderSnapshot.d.ts +9 -0
- package/lib/shared/sales/loadSalesOrderSnapshot.js +22 -0
- package/lib/solution/BaseSales/fulfillmentItemRules.d.ts +27 -0
- package/lib/solution/BaseSales/fulfillmentItemRules.js +259 -0
- package/lib/solution/BaseSales/index.d.ts +39 -16
- package/lib/solution/BaseSales/index.js +333 -31
- package/lib/solution/BaseSales/pickupTiming.d.ts +47 -0
- package/lib/solution/BaseSales/pickupTiming.js +290 -0
- package/lib/solution/BaseSales/types.d.ts +11 -0
- package/lib/solution/BaseSales/utils/parseSalesResponse.js +3 -0
- package/lib/solution/BookingByStep/index.d.ts +3 -1
- package/lib/solution/BookingByStep/index.js +7 -3
- package/lib/solution/BookingTicket/index.d.ts +8 -2
- package/lib/solution/BookingTicket/index.js +65 -6
- package/lib/solution/BookingTicket/utils/addProductDecision.d.ts +0 -1
- package/lib/solution/BookingTicket/utils/addProductDecision.js +1 -1
- package/lib/solution/BookingTicket/utils/cartView.js +3 -1
- package/lib/solution/OrderInvoicePreview/index.d.ts +66 -0
- package/lib/solution/OrderInvoicePreview/index.js +246 -0
- package/lib/solution/RegisterAndLogin/config.js +57 -11
- package/lib/solution/RegisterAndLogin/index.d.ts +2 -0
- package/lib/solution/RegisterAndLogin/index.js +9 -1
- package/lib/solution/RegisterAndLogin/utils.d.ts +12 -4
- package/lib/solution/RegisterAndLogin/utils.js +24 -17
- package/lib/solution/UnifiedBookingSales/businessAvailability.d.ts +27 -0
- package/lib/solution/UnifiedBookingSales/businessAvailability.js +138 -0
- package/lib/solution/UnifiedBookingSales/index.d.ts +36 -4
- package/lib/solution/UnifiedBookingSales/index.js +561 -74
- package/lib/solution/UnifiedBookingSales/types.d.ts +16 -2
- package/lib/solution/VenueBooking/index.d.ts +15 -2
- package/lib/solution/VenueBooking/index.js +243 -96
- package/lib/solution/VenueBooking/types.d.ts +2 -1
- package/lib/solution/VenueBooking/types.js +1 -0
- package/lib/solution/VenueBooking/utils/dateSummary.d.ts +1 -0
- package/lib/solution/VenueBooking/utils/dateSummary.js +7 -4
- package/lib/solution/VenueBooking/utils/smartPricing.d.ts +71 -0
- package/lib/solution/VenueBooking/utils/smartPricing.js +224 -0
- package/lib/solution/VenueBooking/utils/timeSlot.d.ts +1 -0
- package/lib/solution/VenueBooking/utils/timeSlot.js +5 -2
- package/lib/solution/index.d.ts +1 -0
- package/lib/solution/index.js +11 -0
- package/package.json +1 -1
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.PickupTimingController = void 0;
|
|
7
|
+
var _lodashEs = require("lodash-es");
|
|
8
|
+
var _FulfillmentTiming = require("../../modules/FulfillmentTiming");
|
|
9
|
+
async function withTimeout(request) {
|
|
10
|
+
let timer;
|
|
11
|
+
try {
|
|
12
|
+
return await Promise.race([request, new Promise((_, reject) => {
|
|
13
|
+
timer = setTimeout(() => reject(new Error('Unable to load pickup times. Please try again.')), 30000);
|
|
14
|
+
})]);
|
|
15
|
+
} finally {
|
|
16
|
+
if (timer !== undefined) clearTimeout(timer);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Reuses runtime configuration and schedules; every calculation still uses the live clock. */
|
|
21
|
+
class PickupTimingController {
|
|
22
|
+
latest;
|
|
23
|
+
runtime;
|
|
24
|
+
writeSequence = 0;
|
|
25
|
+
constructor(host) {
|
|
26
|
+
this.host = host;
|
|
27
|
+
}
|
|
28
|
+
now() {
|
|
29
|
+
return this.host.now?.() ?? new Date();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** A new solution context or an explicit settings refresh invalidates pending work too. */
|
|
33
|
+
invalidate() {
|
|
34
|
+
this.runtime = undefined;
|
|
35
|
+
this.latest = undefined;
|
|
36
|
+
this.writeSequence += 1;
|
|
37
|
+
}
|
|
38
|
+
assertCurrentRuntime(runtime) {
|
|
39
|
+
if (this.runtime !== runtime || runtime.scope !== this.host.getScope()) {
|
|
40
|
+
throw new Error('Store settings changed. Please try again.');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
getRuntime() {
|
|
44
|
+
const scope = this.host.getScope();
|
|
45
|
+
if (this.runtime?.scope !== scope) {
|
|
46
|
+
this.latest = undefined;
|
|
47
|
+
this.runtime = {
|
|
48
|
+
scope
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
return this.runtime;
|
|
52
|
+
}
|
|
53
|
+
async loadConfig(runtime) {
|
|
54
|
+
if (runtime.config) return runtime.config;
|
|
55
|
+
if (!runtime.configRequest) {
|
|
56
|
+
const request = (async () => {
|
|
57
|
+
const config = (0, _FulfillmentTiming.normalizePickupTimingConfig)(await withTimeout(this.host.loadOpenData(false)));
|
|
58
|
+
this.assertCurrentRuntime(runtime);
|
|
59
|
+
runtime.config = config;
|
|
60
|
+
return config;
|
|
61
|
+
})();
|
|
62
|
+
runtime.configRequest = request;
|
|
63
|
+
}
|
|
64
|
+
const request = runtime.configRequest;
|
|
65
|
+
try {
|
|
66
|
+
return await request;
|
|
67
|
+
} finally {
|
|
68
|
+
if (runtime.configRequest === request) runtime.configRequest = undefined;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async loadSchedules(runtime, config) {
|
|
72
|
+
if (runtime.schedules) return runtime.schedules;
|
|
73
|
+
if (!runtime.scheduleRequest) {
|
|
74
|
+
const request = (async () => {
|
|
75
|
+
const schedule = this.host.getSchedule();
|
|
76
|
+
if (!schedule) throw new Error('Pickup schedule is unavailable. Please try again.');
|
|
77
|
+
// Reuse the catalog loaded by solution initialization, including its in-flight request.
|
|
78
|
+
await withTimeout(schedule.loadAllSchedule({
|
|
79
|
+
useCache: true
|
|
80
|
+
}));
|
|
81
|
+
this.assertCurrentRuntime(runtime);
|
|
82
|
+
const ids = [...new Set([...config.scheduleIds, ...(config.operatingHoursScheduleIds || [])])];
|
|
83
|
+
const schedules = (0, _lodashEs.cloneDeep)(schedule.getScheduleListByIds(ids) || []);
|
|
84
|
+
runtime.schedules = schedules;
|
|
85
|
+
return schedules;
|
|
86
|
+
})();
|
|
87
|
+
runtime.scheduleRequest = request;
|
|
88
|
+
}
|
|
89
|
+
const request = runtime.scheduleRequest;
|
|
90
|
+
try {
|
|
91
|
+
return await request;
|
|
92
|
+
} finally {
|
|
93
|
+
if (runtime.scheduleRequest === request) runtime.scheduleRequest = undefined;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Preserve an existing POS choice without adding it to the shared settings cache. */
|
|
98
|
+
getEffectiveConfig(config) {
|
|
99
|
+
if (!this.host.isPos()) return config;
|
|
100
|
+
const serviceType = this.host.getOrder().getTempOrder()?.metadata?.shop_service_data?.service_type;
|
|
101
|
+
if (serviceType !== 'dine_in' && serviceType !== 'takeaway' || config.handoverModes.includes(serviceType)) {
|
|
102
|
+
return config;
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
...config,
|
|
106
|
+
handoverModes: [...config.handoverModes, serviceType]
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
async snapshot(includeSchedule, tolerateScheduleError = false) {
|
|
110
|
+
const runtime = this.getRuntime();
|
|
111
|
+
const config = await this.loadConfig(runtime);
|
|
112
|
+
this.assertCurrentRuntime(runtime);
|
|
113
|
+
let schedules = [];
|
|
114
|
+
let error;
|
|
115
|
+
if (includeSchedule && config.handoverModes.includes('pick_up') && config.timingMode !== 'asap_only' && config.scheduleIds.length) {
|
|
116
|
+
try {
|
|
117
|
+
schedules = await this.loadSchedules(runtime, config);
|
|
118
|
+
} catch (reason) {
|
|
119
|
+
if (!tolerateScheduleError) throw reason;
|
|
120
|
+
error = reason instanceof Error ? reason.message : 'Pickup schedule is unavailable. Please try again.';
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
this.assertCurrentRuntime(runtime);
|
|
124
|
+
const result = {
|
|
125
|
+
config,
|
|
126
|
+
timezone: this.host.getTimezone(),
|
|
127
|
+
schedules,
|
|
128
|
+
scope: runtime.scope,
|
|
129
|
+
error
|
|
130
|
+
};
|
|
131
|
+
this.latest = result;
|
|
132
|
+
// Read the live order after async loading; cached snapshots retain only configured modes.
|
|
133
|
+
return {
|
|
134
|
+
...result,
|
|
135
|
+
config: this.getEffectiveConfig(config)
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
async getAvailability(params = {}) {
|
|
139
|
+
// `force` remains accepted for older callers; refresh recomputes time using the runtime catalog.
|
|
140
|
+
const snapshot = await this.snapshot(true, true);
|
|
141
|
+
const now = this.now();
|
|
142
|
+
try {
|
|
143
|
+
return {
|
|
144
|
+
...(0, _FulfillmentTiming.computePickupTimingAvailability)({
|
|
145
|
+
...snapshot,
|
|
146
|
+
date: params.date,
|
|
147
|
+
now
|
|
148
|
+
}),
|
|
149
|
+
error: snapshot.error
|
|
150
|
+
};
|
|
151
|
+
} catch (reason) {
|
|
152
|
+
// Keep the handover selector usable when only Pickup's timezone is unavailable.
|
|
153
|
+
return {
|
|
154
|
+
config: snapshot.config,
|
|
155
|
+
timezone: snapshot.timezone,
|
|
156
|
+
now: now.toISOString(),
|
|
157
|
+
today: '',
|
|
158
|
+
maxDate: '',
|
|
159
|
+
date: params.date || '',
|
|
160
|
+
dates: [],
|
|
161
|
+
slots: [],
|
|
162
|
+
error: reason instanceof Error ? reason.message : 'Pickup times are unavailable. Please try again.'
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
getSelection() {
|
|
167
|
+
const order = this.host.getOrder();
|
|
168
|
+
const tempOrder = order.getTempOrder();
|
|
169
|
+
const booking = order.getPickupTimingBooking();
|
|
170
|
+
const config = this.latest?.scope === this.host.getScope() ? this.getEffectiveConfig(this.latest.config) : undefined;
|
|
171
|
+
const storedServiceType = String(tempOrder?.metadata?.shop_service_data?.service_type || '');
|
|
172
|
+
const serviceType = config?.handoverModes.length ? config.handoverModes.includes(storedServiceType) ? storedServiceType : config.handoverModes[0] : storedServiceType;
|
|
173
|
+
const details = serviceType === 'pick_up' ? booking?.metadata.fulfillment_timing : undefined;
|
|
174
|
+
const mode = config?.timingMode === 'asap_only' ? 'asap' : config?.timingMode === 'scheduled_only' ? 'scheduled' : details?.mode ?? 'asap';
|
|
175
|
+
const sameMode = details?.mode === mode;
|
|
176
|
+
return {
|
|
177
|
+
serviceType,
|
|
178
|
+
mode,
|
|
179
|
+
source: mode === 'asap' ? 'asap' : sameMode && details?.source || 'schedule',
|
|
180
|
+
...(sameMode && booking ? {
|
|
181
|
+
date: booking.start_date,
|
|
182
|
+
time: booking.start_time,
|
|
183
|
+
instant: details?.instant
|
|
184
|
+
} : {})
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
async validateSnapshot(selection) {
|
|
188
|
+
const snapshot = await this.snapshot(selection.serviceType === 'pick_up' && selection.mode === 'scheduled' && selection.source !== 'pos_manual');
|
|
189
|
+
const now = this.now();
|
|
190
|
+
const result = (0, _FulfillmentTiming.validatePickupTimingSelection)(selection, {
|
|
191
|
+
...snapshot,
|
|
192
|
+
now,
|
|
193
|
+
allowManualOverride: this.host.isPos()
|
|
194
|
+
});
|
|
195
|
+
return {
|
|
196
|
+
snapshot,
|
|
197
|
+
now,
|
|
198
|
+
result
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
async validate(selection) {
|
|
202
|
+
return (await this.validateSnapshot(selection)).result;
|
|
203
|
+
}
|
|
204
|
+
async setSelection(selection, options = {}) {
|
|
205
|
+
const order = this.host.getOrder();
|
|
206
|
+
const tempOrder = order.ensureTempOrder();
|
|
207
|
+
const sequence = ++this.writeSequence;
|
|
208
|
+
const {
|
|
209
|
+
snapshot,
|
|
210
|
+
now,
|
|
211
|
+
result
|
|
212
|
+
} = await this.validateSnapshot(selection);
|
|
213
|
+
if (sequence !== this.writeSequence || order.getTempOrder() !== tempOrder || snapshot.scope !== this.host.getScope()) {
|
|
214
|
+
throw new Error('The order changed. Please choose the pickup time again.');
|
|
215
|
+
}
|
|
216
|
+
if (!result.valid) throw new Error(result.message || 'Please choose a valid pickup time.');
|
|
217
|
+
if (!snapshot.config.handoverModes.length) {
|
|
218
|
+
order.clearPickupTimingBooking();
|
|
219
|
+
return this.getSelection();
|
|
220
|
+
}
|
|
221
|
+
if (selection.serviceType !== 'pick_up') {
|
|
222
|
+
if (this.host.setServiceType) {
|
|
223
|
+
await this.host.setServiceType(selection.serviceType);
|
|
224
|
+
} else {
|
|
225
|
+
order.updateTempOrderServiceType(selection.serviceType);
|
|
226
|
+
}
|
|
227
|
+
return this.getSelection();
|
|
228
|
+
}
|
|
229
|
+
const slot = selection.mode === 'asap' ? (0, _FulfillmentTiming.getAsapPickupTiming)({
|
|
230
|
+
...snapshot,
|
|
231
|
+
now
|
|
232
|
+
}) : result.slot;
|
|
233
|
+
if (!slot) throw new Error('Please choose a pickup time.');
|
|
234
|
+
// Validate everything before either field is changed; notify once after the combined update.
|
|
235
|
+
tempOrder.metadata = {
|
|
236
|
+
...(tempOrder.metadata || {}),
|
|
237
|
+
shop_service_data: {
|
|
238
|
+
...(tempOrder.metadata?.shop_service_data || {}),
|
|
239
|
+
service_type: 'pick_up'
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
order.setPickupTimingBooking({
|
|
243
|
+
mode: selection.mode,
|
|
244
|
+
source: selection.mode === 'asap' ? 'asap' : selection.source === 'pos_manual' ? 'pos_manual' : 'schedule',
|
|
245
|
+
date: slot.date,
|
|
246
|
+
time: slot.time,
|
|
247
|
+
instant: slot.instant,
|
|
248
|
+
timezone: snapshot.timezone,
|
|
249
|
+
frozen: options.frozen ?? false
|
|
250
|
+
});
|
|
251
|
+
return this.getSelection();
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/** Called before a new checkout/payment; payment callbacks keep their already prepared appointment. */
|
|
255
|
+
async prepare(options = {}) {
|
|
256
|
+
const order = this.host.getOrder();
|
|
257
|
+
const tempOrder = order.getTempOrder();
|
|
258
|
+
const sequence = this.writeSequence;
|
|
259
|
+
if (order.getOrderIdentity()?.isSubmitted) return this.getSelection();
|
|
260
|
+
const booking = order.getPickupTimingBooking();
|
|
261
|
+
if (booking?.metadata.fulfillment_timing?.frozen) return this.getSelection();
|
|
262
|
+
// An actual payment callback must never revalidate or move the time after funds have been taken.
|
|
263
|
+
const paymentStatus = order.getTempOrder()?.payment_status;
|
|
264
|
+
if (paymentStatus === 'paid' || paymentStatus === 'partially_paid') {
|
|
265
|
+
if (booking?.metadata.fulfillment_timing) {
|
|
266
|
+
const detail = booking.metadata.fulfillment_timing;
|
|
267
|
+
order.setPickupTimingBooking({
|
|
268
|
+
...detail,
|
|
269
|
+
date: booking.start_date,
|
|
270
|
+
time: booking.start_time,
|
|
271
|
+
frozen: true
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
return this.getSelection();
|
|
275
|
+
}
|
|
276
|
+
const snapshot = await this.snapshot(false);
|
|
277
|
+
if (order !== this.host.getOrder() || order.getTempOrder() !== tempOrder || sequence !== this.writeSequence) {
|
|
278
|
+
throw new Error('The order changed. Please choose the pickup time again.');
|
|
279
|
+
}
|
|
280
|
+
const selection = this.getSelection();
|
|
281
|
+
if (!snapshot.config.handoverModes.length) {
|
|
282
|
+
order.clearPickupTimingBooking();
|
|
283
|
+
return selection;
|
|
284
|
+
}
|
|
285
|
+
return this.setSelection(selection, {
|
|
286
|
+
frozen: options.freeze ?? false
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
exports.PickupTimingController = PickupTimingController;
|
|
@@ -4,6 +4,8 @@ import type { ScanOrderLogInput as BaseSalesLogInput, ScanOrderLoggerProviderCon
|
|
|
4
4
|
import type { QuantityCheckResult, QuantityLimitResult } from '../../model/strategy/adapter/itemRule';
|
|
5
5
|
import type { QuotationCustomerScopeInfo } from '../../modules/Quotation/types';
|
|
6
6
|
import type { PaymentMethod } from '../../modules/Payment/types';
|
|
7
|
+
import type { OrderPaymentSource } from '../../modules/Order/types';
|
|
8
|
+
import type { SubmitPayloadEnhancer } from '../../modules/Order/utils';
|
|
7
9
|
/**
|
|
8
10
|
* BaseSales 流程 hook 后缀。
|
|
9
11
|
* 完整事件名应由当前模块名动态拼接,避免多个实例共享固定事件 key。
|
|
@@ -27,6 +29,15 @@ export interface BaseSalesCashPaymentOptions {
|
|
|
27
29
|
/** 指定现金支付方式;省略时使用默认 CASHMANUAL。 */
|
|
28
30
|
paymentMethodId?: number | string;
|
|
29
31
|
}
|
|
32
|
+
export interface BaseSalesSubmitSalesOrderParams {
|
|
33
|
+
payments?: OrderPaymentSource[];
|
|
34
|
+
paymentStatus?: BaseSalesPaymentStatus;
|
|
35
|
+
smallTicketDataFlag?: number;
|
|
36
|
+
confirmPendingVoucherPayments?: boolean;
|
|
37
|
+
enhancePayload?: SubmitPayloadEnhancer;
|
|
38
|
+
/** Create the order without executing payment; payment status comes from the server. */
|
|
39
|
+
paymentExecution?: 'deferred';
|
|
40
|
+
}
|
|
30
41
|
export interface BaseSalesCashPaymentConfig {
|
|
31
42
|
available: boolean;
|
|
32
43
|
paymentMethod?: PaymentMethod;
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.parseSalesResponse = parseSalesResponse;
|
|
7
7
|
var _orderCollectionIdentity = require("../../../modules/Order/utils/orderCollectionIdentity");
|
|
8
|
+
var _pickupTiming = require("../../../modules/Order/pickupTiming");
|
|
8
9
|
/**
|
|
9
10
|
* 把 `/order/sales/{id}` 响应(OrderData)解析为 ISalesDetail。
|
|
10
11
|
*
|
|
@@ -64,6 +65,7 @@ function pickCustomer(raw) {
|
|
|
64
65
|
*/
|
|
65
66
|
function isRootBooking(booking) {
|
|
66
67
|
if (!booking || typeof booking !== 'object') return false;
|
|
68
|
+
if ((0, _pickupTiming.isFulfillmentTimingBooking)(booking)) return false;
|
|
67
69
|
const parentId = booking.parent_id;
|
|
68
70
|
if (parentId === 0 || parentId === null || parentId === undefined) return true;
|
|
69
71
|
return false;
|
|
@@ -71,6 +73,7 @@ function isRootBooking(booking) {
|
|
|
71
73
|
function indexBookingsByProductUid(bookings) {
|
|
72
74
|
const result = {};
|
|
73
75
|
for (const b of bookings) {
|
|
76
|
+
if ((0, _pickupTiming.isFulfillmentTimingBooking)(b)) continue;
|
|
74
77
|
const uid = b && (b.product_uid || b.metadata?.product_uid) || '';
|
|
75
78
|
if (!uid) continue;
|
|
76
79
|
const key = String(uid);
|
|
@@ -210,6 +210,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
|
|
|
210
210
|
* product: ProductData;
|
|
211
211
|
* date?: { startTime: string; endTime: string } | null;
|
|
212
212
|
* account?: Account | null;
|
|
213
|
+
* isLegacyOrder?: boolean;
|
|
213
214
|
* })} {
|
|
214
215
|
* product,
|
|
215
216
|
* date,
|
|
@@ -218,13 +219,14 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
|
|
|
218
219
|
* @return {*}
|
|
219
220
|
* @memberof BookingByStepImpl
|
|
220
221
|
*/
|
|
221
|
-
addProductToCart({ product, date, account, }: {
|
|
222
|
+
addProductToCart({ product, date, account, isLegacyOrder, }: {
|
|
222
223
|
product: ProductData;
|
|
223
224
|
date?: {
|
|
224
225
|
startTime: string;
|
|
225
226
|
endTime: string;
|
|
226
227
|
} | null;
|
|
227
228
|
account?: Account | null;
|
|
229
|
+
isLegacyOrder?: boolean;
|
|
228
230
|
}): {
|
|
229
231
|
success: boolean;
|
|
230
232
|
errorCode?: string;
|
|
@@ -636,7 +636,8 @@ class BookingByStepImpl extends _BaseModule.BaseModule {
|
|
|
636
636
|
// 直接调用 addProductToCart,不传递 date 参数以避免日期检查逻辑
|
|
637
637
|
return this.addProductToCart({
|
|
638
638
|
product: productData,
|
|
639
|
-
account: activeAccount
|
|
639
|
+
account: activeAccount,
|
|
640
|
+
isLegacyOrder: true
|
|
640
641
|
});
|
|
641
642
|
}
|
|
642
643
|
|
|
@@ -647,6 +648,7 @@ class BookingByStepImpl extends _BaseModule.BaseModule {
|
|
|
647
648
|
* product: ProductData;
|
|
648
649
|
* date?: { startTime: string; endTime: string } | null;
|
|
649
650
|
* account?: Account | null;
|
|
651
|
+
* isLegacyOrder?: boolean;
|
|
650
652
|
* })} {
|
|
651
653
|
* product,
|
|
652
654
|
* date,
|
|
@@ -658,7 +660,8 @@ class BookingByStepImpl extends _BaseModule.BaseModule {
|
|
|
658
660
|
addProductToCart({
|
|
659
661
|
product,
|
|
660
662
|
date,
|
|
661
|
-
account
|
|
663
|
+
account,
|
|
664
|
+
isLegacyOrder = false
|
|
662
665
|
}) {
|
|
663
666
|
const {
|
|
664
667
|
bundle,
|
|
@@ -725,7 +728,8 @@ class BookingByStepImpl extends _BaseModule.BaseModule {
|
|
|
725
728
|
product: productData,
|
|
726
729
|
bundle,
|
|
727
730
|
options,
|
|
728
|
-
quantity
|
|
731
|
+
quantity,
|
|
732
|
+
isLegacyOrder
|
|
729
733
|
};
|
|
730
734
|
if (date) {
|
|
731
735
|
addItemParams.date = date;
|
|
@@ -42,6 +42,10 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
|
|
|
42
42
|
*/
|
|
43
43
|
protected getRegisteredModuleNames(): readonly string[];
|
|
44
44
|
protected getSubmitOrderSalesChannel(): string;
|
|
45
|
+
/** 供销售展示层按 booking.resources[].form_id 读取当前多语言表单标题。 */
|
|
46
|
+
getFormTitleMap(): Record<string, Record<string, string> | string>;
|
|
47
|
+
/** 表单定义由 Ably 更新后通知展示层刷新,不改动订单里的历史 metadata。 */
|
|
48
|
+
onFormTitlesChanged(callback: (titles: Record<string, Record<string, string> | string>) => void): () => void;
|
|
45
49
|
/**
|
|
46
50
|
* 业务侧子模块工厂:BookingTicket 自带的 createBookingTicketModule 优先匹配;
|
|
47
51
|
* 未识别的模块名(如 BookingByStep 公共类型)回退到父类工厂。
|
|
@@ -53,11 +57,12 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
|
|
|
53
57
|
* 在解决方案对外 ready 前准备 Invoice Document;失败只降级模板,不阻断销售。
|
|
54
58
|
* 已由页面取得的 OpenData 直接交给模块接管,没有注入数据时再走 target-scoped 加载。
|
|
55
59
|
*/
|
|
56
|
-
|
|
60
|
+
protected prepareInvoiceTemplateAtSolutionReady(injectedOpenData?: OpenDataConfig): Promise<void>;
|
|
57
61
|
protected getBookingTicketBusinessCode(): string | null;
|
|
58
62
|
private getIdGeneratorPlugin;
|
|
59
|
-
|
|
63
|
+
protected loadOpenDataConfig(): Promise<OpenDataConfig | null>;
|
|
60
64
|
getOpenData(): Promise<OpenDataConfig | null>;
|
|
65
|
+
protected loadFulfillmentItemRuleOpenData(): Promise<OpenDataConfig | null>;
|
|
61
66
|
getInvoiceLayoutConfig(): Promise<InvoiceLayoutConfig>;
|
|
62
67
|
getInvoiceTemplateSettings(): Promise<InvoiceTemplateSettings>;
|
|
63
68
|
protected isInvoiceOpenDataCacheCurrent(): boolean;
|
|
@@ -66,6 +71,7 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
|
|
|
66
71
|
private getShortNumberOrDeviceId;
|
|
67
72
|
private configureIdGeneratorFromOpenData;
|
|
68
73
|
private normalizePositiveInteger;
|
|
74
|
+
private normalizeShortNumberMaximum;
|
|
69
75
|
private normalizeIdPrefix;
|
|
70
76
|
/**
|
|
71
77
|
* 加载销售详情,并在父类基础上把 customer 信息装配到 CustomerModule。
|
|
@@ -39,6 +39,7 @@ var _orderLineDisplay = require("../../modules/BookingContext/utils/orderLineDis
|
|
|
39
39
|
var _bookingStatus = require("./utils/bookingStatus");
|
|
40
40
|
var _resolveBestAddTimePlan = require("./utils/resolveBestAddTimePlan");
|
|
41
41
|
var _utils = require("../../modules/Order/utils");
|
|
42
|
+
var _types2 = require("../../server/modules/form/types");
|
|
42
43
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
43
44
|
const OPEN_DATA_SECTION_CODES = ['sale', 'reservation', 'fulfillment', 'menu', 'workflow', 'documents'];
|
|
44
45
|
const OPEN_DATA_CACHE_TTL = 5 * 60 * 1000;
|
|
@@ -179,6 +180,16 @@ class BookingTicketImpl extends _BaseSales.BaseSalesImpl {
|
|
|
179
180
|
return !channel || channel === 'system' ? 'pos' : channel;
|
|
180
181
|
}
|
|
181
182
|
|
|
183
|
+
/** 供销售展示层按 booking.resources[].form_id 读取当前多语言表单标题。 */
|
|
184
|
+
getFormTitleMap() {
|
|
185
|
+
return this.core?.server?.form?.getTitleMap?.() || {};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/** 表单定义由 Ably 更新后通知展示层刷新,不改动订单里的历史 metadata。 */
|
|
189
|
+
onFormTitlesChanged(callback) {
|
|
190
|
+
return this.core.effects.on(_types2.FormHooks.onChanged, callback);
|
|
191
|
+
}
|
|
192
|
+
|
|
182
193
|
/**
|
|
183
194
|
* 业务侧子模块工厂:BookingTicket 自带的 createBookingTicketModule 优先匹配;
|
|
184
195
|
* 未识别的模块名(如 BookingByStep 公共类型)回退到父类工厂。
|
|
@@ -289,6 +300,9 @@ class BookingTicketImpl extends _BaseSales.BaseSalesImpl {
|
|
|
289
300
|
async getOpenData() {
|
|
290
301
|
return this.loadOpenDataConfig();
|
|
291
302
|
}
|
|
303
|
+
async loadFulfillmentItemRuleOpenData() {
|
|
304
|
+
return this.store.openData ? this.getOpenData() : super.loadFulfillmentItemRuleOpenData();
|
|
305
|
+
}
|
|
292
306
|
async getInvoiceLayoutConfig() {
|
|
293
307
|
const openData = await this.loadOpenDataConfig();
|
|
294
308
|
if (!openData) return (0, _OpenData.getDefaultInvoiceLayoutConfig)();
|
|
@@ -364,9 +378,10 @@ class BookingTicketImpl extends _BaseSales.BaseSalesImpl {
|
|
|
364
378
|
config: {
|
|
365
379
|
prefix,
|
|
366
380
|
deviceCode: deviceId,
|
|
367
|
-
|
|
368
|
-
padReceiptSequence: false,
|
|
381
|
+
padReceiptSequence: openDataConfig?.['sale.pad_with_leading_zeros'] === true,
|
|
369
382
|
receiptSequenceLength,
|
|
383
|
+
receiptSequenceMax: this.normalizeShortNumberMaximum(openDataConfig?.['sale.maximum_number']),
|
|
384
|
+
randomReceiptSequence: openDataConfig?.['sale.short_number_random'] === true,
|
|
370
385
|
resetReceiptSequenceDaily,
|
|
371
386
|
receiptSequenceResetTime: operatingDayBoundary?.time,
|
|
372
387
|
receiptSequenceStart,
|
|
@@ -382,6 +397,17 @@ class BookingTicketImpl extends _BaseSales.BaseSalesImpl {
|
|
|
382
397
|
if (!Number.isInteger(numeric) || numeric <= 0) return fallback;
|
|
383
398
|
return numeric;
|
|
384
399
|
}
|
|
400
|
+
normalizeShortNumberMaximum(value) {
|
|
401
|
+
if (value === undefined || value === null || typeof value === 'string' && !value.trim()) return null;
|
|
402
|
+
if (typeof value !== 'number' && typeof value !== 'string') {
|
|
403
|
+
throw new Error('sale.maximum_number 必须是安全正整数或空值');
|
|
404
|
+
}
|
|
405
|
+
const numeric = Number(value);
|
|
406
|
+
if (!Number.isSafeInteger(numeric) || numeric <= 0) {
|
|
407
|
+
throw new Error('sale.maximum_number 必须是安全正整数或空值');
|
|
408
|
+
}
|
|
409
|
+
return numeric;
|
|
410
|
+
}
|
|
385
411
|
normalizeIdPrefix(value, fallback) {
|
|
386
412
|
if (value === undefined || value === null) return fallback;
|
|
387
413
|
const normalized = String(value).trim().toUpperCase();
|
|
@@ -1672,6 +1698,30 @@ class BookingTicketImpl extends _BaseSales.BaseSalesImpl {
|
|
|
1672
1698
|
};
|
|
1673
1699
|
}
|
|
1674
1700
|
try {
|
|
1701
|
+
// Capture before lookup/UI awaits, so a result cannot land in a new cart.
|
|
1702
|
+
// Unscoped POS Order modules return a no-op guard.
|
|
1703
|
+
const beforeScanCommit = this.store.order.createCartIntentCommitGuard('add_product');
|
|
1704
|
+
const beforeScanDialog = this.store.order.createCartIntentCommitGuard('add_product');
|
|
1705
|
+
const guardCallback = callback => callback ? (...args) => {
|
|
1706
|
+
beforeScanCommit();
|
|
1707
|
+
return callback(...args);
|
|
1708
|
+
} : undefined;
|
|
1709
|
+
const guardedBridge = bridge ? {
|
|
1710
|
+
...bridge,
|
|
1711
|
+
confirmDetail: guardCallback(bridge.confirmDetail),
|
|
1712
|
+
confirmBookingEdit: guardCallback(bridge.confirmBookingEdit),
|
|
1713
|
+
applyPromotionCode: guardCallback(bridge.applyPromotionCode),
|
|
1714
|
+
openOrder: guardCallback(bridge.openOrder),
|
|
1715
|
+
requestCustomerSwitch: guardCallback(bridge.requestCustomerSwitch),
|
|
1716
|
+
openProductDetail: bridge.openProductDetail ? payload => {
|
|
1717
|
+
beforeScanDialog();
|
|
1718
|
+
return bridge.openProductDetail(payload);
|
|
1719
|
+
} : undefined,
|
|
1720
|
+
openBookingEdit: bridge.openBookingEdit ? payload => {
|
|
1721
|
+
beforeScanDialog();
|
|
1722
|
+
return bridge.openBookingEdit(payload);
|
|
1723
|
+
} : undefined
|
|
1724
|
+
} : undefined;
|
|
1675
1725
|
const localSearch = v => this.store.products.findProductsByCodeOrBarcode(v);
|
|
1676
1726
|
const scanCallback = (0, _handleScan.handleGlobalScan)(this.request, localSearch, this.getSubmitOrderSalesChannel());
|
|
1677
1727
|
const raw = await scanCallback({
|
|
@@ -1687,7 +1737,10 @@ class BookingTicketImpl extends _BaseSales.BaseSalesImpl {
|
|
|
1687
1737
|
};
|
|
1688
1738
|
}
|
|
1689
1739
|
const result = await (0, _applyGlobalScan.applyGlobalScan)({
|
|
1690
|
-
setOrderCustomer: customer =>
|
|
1740
|
+
setOrderCustomer: customer => {
|
|
1741
|
+
beforeScanCommit();
|
|
1742
|
+
this.setOrderCustomer(customer);
|
|
1743
|
+
},
|
|
1691
1744
|
getOrderCustomerSnapshot: () => this.getOrderCustomerSnapshot(),
|
|
1692
1745
|
resolveCustomerById: customerId => this.resolveCustomerById(customerId),
|
|
1693
1746
|
getBusinessCode: () => this.otherParams?.businessCode,
|
|
@@ -1695,10 +1748,16 @@ class BookingTicketImpl extends _BaseSales.BaseSalesImpl {
|
|
|
1695
1748
|
decideAddProduct: (item, options) => this.decideAddProduct(item, options),
|
|
1696
1749
|
decideAfterDetail: (cacheItem, options) => this.decideAfterDetail(cacheItem, options),
|
|
1697
1750
|
transformDetailToProductAndBooking: input => this.transformDetailToProductAndBooking(input),
|
|
1698
|
-
addProductToOrder: (product, booking) =>
|
|
1751
|
+
addProductToOrder: (product, booking) => {
|
|
1752
|
+
beforeScanCommit();
|
|
1753
|
+
return this.addProductToOrder(product, booking);
|
|
1754
|
+
},
|
|
1699
1755
|
refreshWalletAssets: params => this.refreshWalletAssets(params),
|
|
1700
|
-
scanWalletAsset: scanCode =>
|
|
1701
|
-
|
|
1756
|
+
scanWalletAsset: scanCode => {
|
|
1757
|
+
beforeScanCommit();
|
|
1758
|
+
return this.scanWalletAsset(scanCode);
|
|
1759
|
+
}
|
|
1760
|
+
}, formatted, guardedBridge);
|
|
1702
1761
|
bridge?.refresh?.();
|
|
1703
1762
|
return result;
|
|
1704
1763
|
} catch (error) {
|
|
@@ -146,7 +146,7 @@ function isMultiDayLike(cacheItem) {
|
|
|
146
146
|
* `_extend.resource / capacity / startDate / endDate` 等后续 booking mapper 需要的字段。
|
|
147
147
|
*/
|
|
148
148
|
function prepareBookingCacheItem(cacheItem, ctx) {
|
|
149
|
-
if (isNormalBookingProduct(cacheItem) || hasPreparedBookingExtend(cacheItem)) {
|
|
149
|
+
if (ctx?.rememberedTime === undefined && (isNormalBookingProduct(cacheItem) || hasPreparedBookingExtend(cacheItem))) {
|
|
150
150
|
return cacheItem;
|
|
151
151
|
}
|
|
152
152
|
return (0, _BookingContext.getProductExtend)({
|
|
@@ -8,12 +8,14 @@ exports.buildCustomerView = buildCustomerView;
|
|
|
8
8
|
exports.indexBookingsByProductUid = indexBookingsByProductUid;
|
|
9
9
|
exports.isWalkInCustomer = isWalkInCustomer;
|
|
10
10
|
var _addTimeAvailability = require("./addTimeAvailability");
|
|
11
|
+
var _pickupTiming = require("../../../modules/Order/pickupTiming");
|
|
11
12
|
/**
|
|
12
13
|
* 仅按 booking.product_uid 建索引,避免发明 booking 与商品行之间的其它等价关系。
|
|
13
14
|
*/
|
|
14
15
|
function indexBookingsByProductUid(bookings) {
|
|
15
16
|
if (!Array.isArray(bookings) || bookings.length === 0) return {};
|
|
16
17
|
return bookings.reduce((acc, booking) => {
|
|
18
|
+
if ((0, _pickupTiming.isFulfillmentTimingBooking)(booking)) return acc;
|
|
17
19
|
const uid = booking?.product_uid;
|
|
18
20
|
if (uid === undefined || uid === null || uid === '') return acc;
|
|
19
21
|
const key = String(uid);
|
|
@@ -105,7 +107,7 @@ function isGiftProductLine(line) {
|
|
|
105
107
|
function buildCartView(lines, bookings, options = {}) {
|
|
106
108
|
const productLines = Array.isArray(lines) ? lines : [];
|
|
107
109
|
const bookingList = Array.isArray(bookings) ? bookings : [];
|
|
108
|
-
const childBookings = bookingList.filter(booking => booking.parent_id !== 0);
|
|
110
|
+
const childBookings = bookingList.filter(booking => booking.parent_id !== 0 && !(0, _pickupTiming.isFulfillmentTimingBooking)(booking));
|
|
109
111
|
const bookingsByProductUid = indexBookingsByProductUid(childBookings);
|
|
110
112
|
const linesByUid = indexProductsByUid(productLines);
|
|
111
113
|
const addTimeLinesByBookingUid = indexAddTimeProductsByBookingUid(productLines);
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { Module, ModuleOptions, PisellCore } from '../../types';
|
|
2
|
+
import { BaseModule } from '../../modules/BaseModule';
|
|
3
|
+
import { type CustomerInvoiceLanguageCode, type CustomerInvoiceLanguageOption } from '../../shared/receipt/customerInvoiceLanguages';
|
|
4
|
+
export type { CustomerInvoiceLanguageCode, CustomerInvoiceLanguageOption, } from '../../shared/receipt/customerInvoiceLanguages';
|
|
5
|
+
import type { InvoiceLayoutConfig } from '../../modules/OpenData';
|
|
6
|
+
import { type SmallTicketData } from '../../shared/receipt/small-ticket';
|
|
7
|
+
export interface OrderInvoicePreviewInput {
|
|
8
|
+
orderId: string | number;
|
|
9
|
+
tenantId: string | number;
|
|
10
|
+
shopId: string | number;
|
|
11
|
+
/** Changes on login/logout, without exposing credentials in state or cache keys. */
|
|
12
|
+
identity: string;
|
|
13
|
+
businessCode: string;
|
|
14
|
+
channel: string;
|
|
15
|
+
locale: string;
|
|
16
|
+
sourceRevision: string;
|
|
17
|
+
shop?: Record<string, any>;
|
|
18
|
+
}
|
|
19
|
+
export interface OrderInvoicePreviewResult {
|
|
20
|
+
identity: string;
|
|
21
|
+
sourceRevision: string;
|
|
22
|
+
generatedAt: string;
|
|
23
|
+
locale: string;
|
|
24
|
+
secondaryLocale?: string;
|
|
25
|
+
languageOptions: CustomerInvoiceLanguageOption[];
|
|
26
|
+
selectedLanguage: CustomerInvoiceLanguageCode;
|
|
27
|
+
orderId: string | number;
|
|
28
|
+
source: Record<string, any>;
|
|
29
|
+
shop: Record<string, any>;
|
|
30
|
+
layout: InvoiceLayoutConfig;
|
|
31
|
+
smallTicketData: SmallTicketData;
|
|
32
|
+
}
|
|
33
|
+
export interface OrderInvoicePreviewState {
|
|
34
|
+
status: 'idle' | 'loading' | 'ready' | 'error';
|
|
35
|
+
result: OrderInvoicePreviewResult | null;
|
|
36
|
+
error: string | null;
|
|
37
|
+
}
|
|
38
|
+
/** Read-only, page-owned solution. No Order, Schedule, quotation or payment modules. */
|
|
39
|
+
export declare class OrderInvoicePreviewImpl extends BaseModule implements Module {
|
|
40
|
+
isSolution: boolean;
|
|
41
|
+
private request;
|
|
42
|
+
private state;
|
|
43
|
+
private listeners;
|
|
44
|
+
private generation;
|
|
45
|
+
private disposed;
|
|
46
|
+
private input?;
|
|
47
|
+
private activeKey;
|
|
48
|
+
private languageSelection?;
|
|
49
|
+
private pending?;
|
|
50
|
+
private snapshotCache;
|
|
51
|
+
constructor(name?: string);
|
|
52
|
+
initialize(core: PisellCore, _options: ModuleOptions): void;
|
|
53
|
+
getState: () => OrderInvoicePreviewState;
|
|
54
|
+
subscribe: (listener: () => void) => (() => void);
|
|
55
|
+
private publish;
|
|
56
|
+
private getScope;
|
|
57
|
+
private loadContext;
|
|
58
|
+
private loadSource;
|
|
59
|
+
prepare(input: OrderInvoicePreviewInput): Promise<OrderInvoicePreviewResult>;
|
|
60
|
+
private getSelectionScope;
|
|
61
|
+
private documentIdentity;
|
|
62
|
+
/** Switch only the ready receipt projection; no fetching or rebuilding data. */
|
|
63
|
+
selectLanguage(code: string): OrderInvoicePreviewResult;
|
|
64
|
+
retry(): Promise<OrderInvoicePreviewResult>;
|
|
65
|
+
destroy(): void;
|
|
66
|
+
}
|