@pisell/pisellos 2.3.103 → 2.3.105
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/model/strategy/adapter/promotion/index.js +0 -9
- package/dist/modules/Order/index.js +3 -3
- package/dist/modules/Payment/walletpass.js +20 -21
- package/dist/modules/ResourcePlanner/planner.js +26 -3
- package/dist/modules/ResourcePlanner/types.d.ts +7 -0
- package/dist/modules/Rules/index.js +2 -1
- package/dist/server/utils/small-ticket.js +49 -1
- package/dist/solution/BookingByStep/index.d.ts +2 -2
- package/dist/solution/UnifiedBookingSales/index.d.ts +2 -2
- package/dist/solution/UnifiedBookingSales/index.js +33 -25
- package/lib/model/strategy/adapter/promotion/index.js +46 -1
- package/lib/modules/Order/index.js +2 -2
- package/lib/modules/Payment/walletpass.js +14 -11
- package/lib/modules/ResourcePlanner/planner.js +25 -4
- package/lib/modules/ResourcePlanner/types.d.ts +7 -0
- package/lib/modules/Rules/index.js +1 -0
- package/lib/server/utils/small-ticket.js +50 -1
- package/lib/solution/BookingByStep/index.d.ts +2 -2
- package/lib/solution/UnifiedBookingSales/index.d.ts +2 -2
- package/lib/solution/UnifiedBookingSales/index.js +15 -7
- package/package.json +1 -1
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
// 导出评估器
|
|
2
|
-
export { PromotionEvaluator } from "./evaluator";
|
|
3
|
-
|
|
4
|
-
// 导出适配器
|
|
5
|
-
export { PromotionAdapter } from "./adapter";
|
|
6
|
-
export { default } from "./adapter";
|
|
7
|
-
|
|
8
|
-
// 导出策略配置示例常量
|
|
9
|
-
export { X_ITEMS_FOR_Y_PRICE_STRATEGY, BUY_X_GET_Y_FREE_STRATEGY, ITEM_REWARD_STRATEGY } from "./examples";
|
|
@@ -297,14 +297,14 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
|
|
|
297
297
|
}
|
|
298
298
|
if (Array.isArray(product.product_bundle)) {
|
|
299
299
|
product.product_bundle = product.product_bundle.map(function (bundle) {
|
|
300
|
-
var _ref11, _bundle$
|
|
300
|
+
var _ref11, _bundle$price, _bundle$bundle_sellin;
|
|
301
301
|
var hasBundleDiscount = Array.isArray(bundle === null || bundle === void 0 ? void 0 : bundle.discount_list) && bundle.discount_list.length > 0;
|
|
302
302
|
if (hasBundleDiscount) return bundle;
|
|
303
|
-
var restoredPrice = (_ref11 = (_bundle$
|
|
303
|
+
var restoredPrice = (_ref11 = (_bundle$price = bundle === null || bundle === void 0 ? void 0 : bundle.price) !== null && _bundle$price !== void 0 ? _bundle$price : bundle === null || bundle === void 0 ? void 0 : bundle.original_price) !== null && _ref11 !== void 0 ? _ref11 : bundle === null || bundle === void 0 ? void 0 : bundle.product_price;
|
|
304
304
|
if (restoredPrice === undefined || restoredPrice === null || restoredPrice === '') return bundle;
|
|
305
305
|
return _objectSpread(_objectSpread({}, bundle), {}, {
|
|
306
306
|
price: restoredPrice,
|
|
307
|
-
bundle_selling_price: restoredPrice
|
|
307
|
+
bundle_selling_price: (_bundle$bundle_sellin = bundle === null || bundle === void 0 ? void 0 : bundle.bundle_selling_price) !== null && _bundle$bundle_sellin !== void 0 ? _bundle$bundle_sellin : restoredPrice
|
|
308
308
|
});
|
|
309
309
|
});
|
|
310
310
|
}
|
|
@@ -851,7 +851,7 @@ export var WalletPassPaymentImpl = /*#__PURE__*/function () {
|
|
|
851
851
|
key: "getUserIdentificationCodeListAsync",
|
|
852
852
|
value: function () {
|
|
853
853
|
var _getUserIdentificationCodeListAsync = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(params) {
|
|
854
|
-
var _newParams$products, _newParams$prepare_pa, _this$walletParams4, newParams,
|
|
854
|
+
var _newParams$products, _newParams$prepare_pa, _this$walletParams4, newParams, response, sortedData;
|
|
855
855
|
return _regeneratorRuntime().wrap(function _callee6$(_context6) {
|
|
856
856
|
while (1) switch (_context6.prev = _context6.next) {
|
|
857
857
|
case 0:
|
|
@@ -864,20 +864,19 @@ export var WalletPassPaymentImpl = /*#__PURE__*/function () {
|
|
|
864
864
|
this.paymentModule.logInfo('[WalletPass] 商品列表为空,跳过获取用户识别码列表');
|
|
865
865
|
return _context6.abrupt("return", []);
|
|
866
866
|
case 5:
|
|
867
|
-
platform = this.paymentModule.getPlatform();
|
|
868
|
-
if (
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
this.
|
|
874
|
-
|
|
875
|
-
}
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
case 11:
|
|
867
|
+
// const platform = this.paymentModule.getPlatform();
|
|
868
|
+
// if (platform === 'pc' || platform === 'h5') {
|
|
869
|
+
// this.userIdentificationCodes = [];
|
|
870
|
+
// this.emitEvent(WalletPassHooks.OnUserIdentificationCodesUpdated, {
|
|
871
|
+
// userIdentificationCodes: [],
|
|
872
|
+
// } as OnUserIdentificationCodesUpdatedEventData);
|
|
873
|
+
// this.paymentModule.logInfo(
|
|
874
|
+
// '[WalletPass] 用户端平台跳过获取用户识别码列表',
|
|
875
|
+
// { platform },
|
|
876
|
+
// );
|
|
877
|
+
// return [];
|
|
878
|
+
// }
|
|
879
|
+
|
|
881
880
|
if (typeof newParams.payment_order_id === 'string' && newParams.payment_order_id.startsWith('LOCAL_')) {
|
|
882
881
|
newParams.payment_order_id = undefined;
|
|
883
882
|
}
|
|
@@ -888,9 +887,9 @@ export var WalletPassPaymentImpl = /*#__PURE__*/function () {
|
|
|
888
887
|
filter_prepare_wallet_pass: newParams.filter_prepare_wallet_pass,
|
|
889
888
|
payment_order_id: (_this$walletParams4 = this.walletParams) === null || _this$walletParams4 === void 0 ? void 0 : _this$walletParams4.payment_order_id
|
|
890
889
|
});
|
|
891
|
-
_context6.next =
|
|
890
|
+
_context6.next = 9;
|
|
892
891
|
return this.paymentModule.request.post('/machinecode/prepare/deduction', newParams);
|
|
893
|
-
case
|
|
892
|
+
case 9:
|
|
894
893
|
response = _context6.sent;
|
|
895
894
|
// 对获取到的数据进行排序,将错误码为 500100、500200、500300 的项目排到最后
|
|
896
895
|
sortedData = sortUserIdentificationCodeList((response === null || response === void 0 ? void 0 : response.data) || []);
|
|
@@ -911,19 +910,19 @@ export var WalletPassPaymentImpl = /*#__PURE__*/function () {
|
|
|
911
910
|
})
|
|
912
911
|
});
|
|
913
912
|
return _context6.abrupt("return", this.userIdentificationCodes);
|
|
914
|
-
case
|
|
915
|
-
_context6.prev =
|
|
913
|
+
case 17:
|
|
914
|
+
_context6.prev = 17;
|
|
916
915
|
_context6.t0 = _context6["catch"](0);
|
|
917
916
|
this.paymentModule.logError('[WalletPass] 获取用户识别码列表失败', _context6.t0, {
|
|
918
917
|
customer_id: params.customer_id,
|
|
919
918
|
available: params.available
|
|
920
919
|
});
|
|
921
920
|
return _context6.abrupt("return", []);
|
|
922
|
-
case
|
|
921
|
+
case 21:
|
|
923
922
|
case "end":
|
|
924
923
|
return _context6.stop();
|
|
925
924
|
}
|
|
926
|
-
}, _callee6, this, [[0,
|
|
925
|
+
}, _callee6, this, [[0, 17]]);
|
|
927
926
|
}));
|
|
928
927
|
function getUserIdentificationCodeListAsync(_x7) {
|
|
929
928
|
return _getUserIdentificationCodeListAsync.apply(this, arguments);
|
|
@@ -62,13 +62,21 @@ function resolveRequestedDurationMinutes(product, request) {
|
|
|
62
62
|
}
|
|
63
63
|
function resolveRequestedDurationStartTimes(product, request) {
|
|
64
64
|
var _request$durationStar;
|
|
65
|
-
|
|
65
|
+
var allowSessionCustomRanges = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
66
|
+
if (product.kind !== 'duration' && !(product.kind === 'session' && allowSessionCustomRanges)) return [];
|
|
66
67
|
var values = (_request$durationStar = request.durationStartTimesByProductId) === null || _request$durationStar === void 0 ? void 0 : _request$durationStar[String(product.id)];
|
|
67
68
|
if (!Array.isArray(values)) return [];
|
|
68
69
|
return Array.from(new Set(values.filter(function (value) {
|
|
69
70
|
return typeof value === 'string' && /^([01]\d|2[0-3]):[0-5]\d$/.test(value);
|
|
70
71
|
})));
|
|
71
72
|
}
|
|
73
|
+
function resolveRequestedSessionDurationMinutes(product, request, allowSessionCustomRanges) {
|
|
74
|
+
var _request$durationMinu2;
|
|
75
|
+
if (product.kind !== 'session' || !allowSessionCustomRanges) return undefined;
|
|
76
|
+
var override = (_request$durationMinu2 = request.durationMinutesByProductId) === null || _request$durationMinu2 === void 0 ? void 0 : _request$durationMinu2[String(product.id)];
|
|
77
|
+
var normalized = Number(override);
|
|
78
|
+
return Number.isInteger(normalized) && normalized > 0 ? normalized : undefined;
|
|
79
|
+
}
|
|
72
80
|
function toDateTime(value, _timezoneName) {
|
|
73
81
|
try {
|
|
74
82
|
return localDateTimeToScalar(parseLocalDateTime(value));
|
|
@@ -212,7 +220,11 @@ function evaluateCandidateTimeGate(params) {
|
|
|
212
220
|
};
|
|
213
221
|
}
|
|
214
222
|
if (policy.type === 'before_start') {
|
|
215
|
-
|
|
223
|
+
// Flexible-duration candidates start at minute precision. Keep the current
|
|
224
|
+
// minute selectable instead of treating the freshly generated candidate as
|
|
225
|
+
// already started because the query clock still contains seconds.
|
|
226
|
+
var hasNotReachedStart = product.isFlexibleDuration ? floorToMinute(now) <= candidateRange.start : now < candidateRange.start;
|
|
227
|
+
if (hasNotReachedStart) return null;
|
|
216
228
|
return {
|
|
217
229
|
status: 'unavailable',
|
|
218
230
|
reasonCodes: ['booking_cutoff_before_start'],
|
|
@@ -1025,12 +1037,23 @@ export function getProductTimeRanges(projection) {
|
|
|
1025
1037
|
};
|
|
1026
1038
|
}
|
|
1027
1039
|
if (product.kind === 'session' || product.kind === 'venue_slot') {
|
|
1040
|
+
var fixedRanges = getSessionRangesForProduct(projection, product, dateRange);
|
|
1041
|
+
var customRanges = [];
|
|
1042
|
+
var customDurationMinutes = resolveRequestedSessionDurationMinutes(product, request, runtimeOptions.allowSessionCustomRanges === true);
|
|
1043
|
+
var _requestedStartTimes = resolveRequestedDurationStartTimes(product, request, runtimeOptions.allowSessionCustomRanges === true);
|
|
1044
|
+
if (product.kind === 'session' && customDurationMinutes && dateRange.startDate === dateRange.endDate) {
|
|
1045
|
+
_requestedStartTimes.forEach(function (startTime) {
|
|
1046
|
+
var start = toDateTimeInDate(dateRange.startDate, startTime, projection.meta.timezone);
|
|
1047
|
+
if (!Number.isFinite(start)) return;
|
|
1048
|
+
customRanges.push(createDurationTimeRange(product, start, customDurationMinutes, projection, fixedOffsetMinutes));
|
|
1049
|
+
});
|
|
1050
|
+
}
|
|
1028
1051
|
return {
|
|
1029
1052
|
productId: product.id,
|
|
1030
1053
|
title: product.title,
|
|
1031
1054
|
kind: product.kind,
|
|
1032
1055
|
slotStepMinutes: slotStepMinutes,
|
|
1033
|
-
ranges:
|
|
1056
|
+
ranges: dedupeProductRanges([].concat(_toConsumableArray(fixedRanges), customRanges))
|
|
1034
1057
|
};
|
|
1035
1058
|
}
|
|
1036
1059
|
var requiredGroups = (product.requirementGroups || []).filter(function (group) {
|
|
@@ -243,6 +243,13 @@ export interface GetProductTimeRangesRequest {
|
|
|
243
243
|
}
|
|
244
244
|
export interface GetProductTimeRangesRuntimeOptions {
|
|
245
245
|
evaluatedAt?: string;
|
|
246
|
+
/**
|
|
247
|
+
* Internal POS capability: allow explicit duration/start overrides to append
|
|
248
|
+
* a custom duration candidate for Session products. Fixed Session ranges are
|
|
249
|
+
* still returned unchanged. Callers outside the POS facade must leave this
|
|
250
|
+
* disabled.
|
|
251
|
+
*/
|
|
252
|
+
allowSessionCustomRanges?: boolean;
|
|
246
253
|
}
|
|
247
254
|
export interface QueryAvailabilityBaseRequest {
|
|
248
255
|
productIds?: AvailabilityId[];
|
|
@@ -1384,11 +1384,12 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
|
|
|
1384
1384
|
}))]);
|
|
1385
1385
|
}
|
|
1386
1386
|
} else {
|
|
1387
|
-
var _flatItem$bundleItem8, _flatItem$bundleItem9
|
|
1387
|
+
var _flatItem$bundleItem8, _flatItem$bundleItem9, _flatItem$bundleItem$;
|
|
1388
1388
|
// bundle子商品:保存到扁平化Map
|
|
1389
1389
|
processedFlatItemsMap.set(flatItem._id, [_objectSpread(_objectSpread({}, flatItem), {}, {
|
|
1390
1390
|
discount_list: isManualDiscount ? _this4.resolveDiscountListForManualOverride(((_flatItem$bundleItem8 = flatItem.bundleItem) === null || _flatItem$bundleItem8 === void 0 ? void 0 : _flatItem$bundleItem8.discount_list) || []) : _this4.filterDiscountListByType(((_flatItem$bundleItem9 = flatItem.bundleItem) === null || _flatItem$bundleItem9 === void 0 ? void 0 : _flatItem$bundleItem9.discount_list) || [], 'promotion'),
|
|
1391
1391
|
price: isManualDiscount ? flatItem.bundleItem.price : flatItem.bundleItem.original_price,
|
|
1392
|
+
bundle_selling_price: (_flatItem$bundleItem$ = flatItem.bundleItem.bundle_selling_price) !== null && _flatItem$bundleItem$ !== void 0 ? _flatItem$bundleItem$ : isManualDiscount ? flatItem.bundleItem.price : flatItem.bundleItem.original_price,
|
|
1392
1393
|
processed: true
|
|
1393
1394
|
})]);
|
|
1394
1395
|
}
|
|
@@ -30,6 +30,8 @@ var LABELS = {
|
|
|
30
30
|
pickUpTime: 'Pick-up time',
|
|
31
31
|
asap: 'ASAP',
|
|
32
32
|
cash: 'Cash',
|
|
33
|
+
cashReceived: 'Cash received',
|
|
34
|
+
changeDue: 'Change due',
|
|
33
35
|
eftpos: 'Eftpos',
|
|
34
36
|
wallet: 'Wallet',
|
|
35
37
|
giftCard: 'Gift card',
|
|
@@ -57,6 +59,8 @@ var LABELS = {
|
|
|
57
59
|
pickUpTime: '取餐时间',
|
|
58
60
|
asap: '尽快',
|
|
59
61
|
cash: '现金支付',
|
|
62
|
+
cashReceived: '收取现金',
|
|
63
|
+
changeDue: '找零',
|
|
60
64
|
eftpos: '刷卡支付',
|
|
61
65
|
wallet: '钱包支付',
|
|
62
66
|
giftCard: '礼品卡',
|
|
@@ -84,6 +88,8 @@ var LABELS = {
|
|
|
84
88
|
pickUpTime: '取餐時間',
|
|
85
89
|
asap: '盡快',
|
|
86
90
|
cash: '現金支付',
|
|
91
|
+
cashReceived: '收取現金',
|
|
92
|
+
changeDue: '找零',
|
|
87
93
|
eftpos: '刷卡支付',
|
|
88
94
|
wallet: '錢包支付',
|
|
89
95
|
giftCard: '禮品卡',
|
|
@@ -98,6 +104,14 @@ var LABELS = {
|
|
|
98
104
|
rounding: '抹零',
|
|
99
105
|
gross: '重量',
|
|
100
106
|
tare: '去皮'
|
|
107
|
+
},
|
|
108
|
+
ja: {
|
|
109
|
+
cashReceived: 'お預かり',
|
|
110
|
+
changeDue: 'お釣り'
|
|
111
|
+
},
|
|
112
|
+
pt: {
|
|
113
|
+
cashReceived: 'Dinheiro recebido',
|
|
114
|
+
changeDue: 'Troco'
|
|
101
115
|
}
|
|
102
116
|
};
|
|
103
117
|
export function buildSmallTicketData(params) {
|
|
@@ -174,7 +188,7 @@ function buildBaseData(params) {
|
|
|
174
188
|
order_number: orderNumber,
|
|
175
189
|
shop_tax_number: stringify(shopInfo.tax_number || order.shop_tax_number),
|
|
176
190
|
shop_phone: stringify(shopInfo.phone || order.shop_phone),
|
|
177
|
-
shop_address: stringify(shopInfo.address || buildShopAddress(shopInfo) || order.shop_address),
|
|
191
|
+
shop_address: stringify(shopInfo.receipt_address || shopInfo.address || buildShopAddress(shopInfo) || order.shop_address),
|
|
178
192
|
original_payment_status: stringify(order.payment_status),
|
|
179
193
|
is_repeat: 0,
|
|
180
194
|
buzzer: stringify(order.buzzer || order.pickup_number || ((_order$metadata = order.metadata) === null || _order$metadata === void 0 ? void 0 : _order$metadata.buzzer)),
|
|
@@ -839,6 +853,11 @@ function buildPaymentItems(params) {
|
|
|
839
853
|
item: paymentMethodName(payment, locale),
|
|
840
854
|
value: formatMoney(resolveReceiptPaymentAmount(payment, serviceFee), currencySymbol)
|
|
841
855
|
}];
|
|
856
|
+
items.push.apply(items, _toConsumableArray(buildCashChangePaymentItems({
|
|
857
|
+
payment: payment,
|
|
858
|
+
locale: locale,
|
|
859
|
+
currencySymbol: currencySymbol
|
|
860
|
+
})));
|
|
842
861
|
if (serviceFee.gt(0)) {
|
|
843
862
|
items.push({
|
|
844
863
|
item: label(locale, 'surchargeIncluded'),
|
|
@@ -882,6 +901,35 @@ function resolveReceiptPaymentAmount(payment, serviceFee) {
|
|
|
882
901
|
var originAmount = new Decimal(toMoneyNumber(payment.origin_amount));
|
|
883
902
|
return amount.eq(originAmount) ? amount.plus(serviceFee) : amount;
|
|
884
903
|
}
|
|
904
|
+
function buildCashChangePaymentItems(params) {
|
|
905
|
+
var payment = params.payment,
|
|
906
|
+
locale = params.locale,
|
|
907
|
+
currencySymbol = params.currencySymbol;
|
|
908
|
+
if (!shouldDisplayCashChange(payment)) return [];
|
|
909
|
+
return [{
|
|
910
|
+
item: label(locale, 'cashReceived'),
|
|
911
|
+
value: formatMoney(payment.metadata.actual_paid_amount, currencySymbol)
|
|
912
|
+
}, {
|
|
913
|
+
item: label(locale, 'changeDue'),
|
|
914
|
+
value: formatMoney(payment.metadata.change_given_amount, currencySymbol)
|
|
915
|
+
}];
|
|
916
|
+
}
|
|
917
|
+
function shouldDisplayCashChange(payment) {
|
|
918
|
+
var _payment$code, _payment$metadata2, _payment$metadata3;
|
|
919
|
+
if (stringify(payment.status).toLowerCase() !== 'paid') return false;
|
|
920
|
+
var paymentMethod = stringify((_payment$code = payment.code) !== null && _payment$code !== void 0 ? _payment$code : payment.payment_method).toUpperCase();
|
|
921
|
+
if (paymentMethod !== 'CASHMANUAL') return false;
|
|
922
|
+
var actualPaidAmount = (_payment$metadata2 = payment.metadata) === null || _payment$metadata2 === void 0 ? void 0 : _payment$metadata2.actual_paid_amount;
|
|
923
|
+
var changeGivenAmount = (_payment$metadata3 = payment.metadata) === null || _payment$metadata3 === void 0 ? void 0 : _payment$metadata3.change_given_amount;
|
|
924
|
+
if (!isNumericAmount(actualPaidAmount) || !isNumericAmount(changeGivenAmount)) return false;
|
|
925
|
+
return new Decimal(changeGivenAmount).toDecimalPlaces(2).gt(0);
|
|
926
|
+
}
|
|
927
|
+
function isNumericAmount(value) {
|
|
928
|
+
if (typeof value === 'number') return Number.isFinite(value);
|
|
929
|
+
if (typeof value !== 'string') return false;
|
|
930
|
+
var normalized = value.trim();
|
|
931
|
+
return normalized !== '' && /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i.test(normalized);
|
|
932
|
+
}
|
|
885
933
|
function buildFundRecordPaymentItems(params) {
|
|
886
934
|
var payment = params.payment,
|
|
887
935
|
fundRecord = params.fundRecord,
|
|
@@ -326,7 +326,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
|
|
|
326
326
|
date: string;
|
|
327
327
|
status: string;
|
|
328
328
|
week: string;
|
|
329
|
-
weekNum: 0 |
|
|
329
|
+
weekNum: 0 | 2 | 3 | 1 | 5 | 6 | 4;
|
|
330
330
|
}[]>;
|
|
331
331
|
submitTimeSlot(timeSlots: TimeSliceItem): void;
|
|
332
332
|
private getScheduleDataByIds;
|
|
@@ -345,7 +345,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
|
|
|
345
345
|
count: number;
|
|
346
346
|
left: number;
|
|
347
347
|
summaryCount: number;
|
|
348
|
-
status: "
|
|
348
|
+
status: "lots_of_space" | "filling_up_fast" | "sold_out";
|
|
349
349
|
}[];
|
|
350
350
|
/**
|
|
351
351
|
* 找到多个资源的公共可用时间段
|
|
@@ -130,8 +130,8 @@ export declare class UnifiedBookingSalesImpl extends BookingTicket {
|
|
|
130
130
|
*/
|
|
131
131
|
clearSessionStorageOrderSnapshot(): void;
|
|
132
132
|
/**
|
|
133
|
-
* Kiosk
|
|
134
|
-
*
|
|
133
|
+
* H5/Kiosk 不能把已收款订单留在本地等待重试,必须直接等待云端 checkout。
|
|
134
|
+
* 其它平台保持 WebPOS/POS 的本地待同步任务;显式 true 仍可强制使用本地任务。
|
|
135
135
|
*/
|
|
136
136
|
protected shouldUseCheckoutSyncTask(): boolean;
|
|
137
137
|
/** UnifiedBookingSales 的真实结账默认请求收据数据,供云端确认后再本地打印。 */
|
|
@@ -43,7 +43,7 @@ import { UnifiedBookingSalesHooks } from "./types";
|
|
|
43
43
|
import { AvailabilityRemoteOccupancyCache } from "./remoteOccupancyCache";
|
|
44
44
|
import { BookingTicket } from "../BookingTicket";
|
|
45
45
|
import { addLocalCalendarDays, captureRuntimeOffsetMinutes, formatLocalDate, formatLocalDateTime, formatLocalTime, localDateTimeToScalar, localDateToScalar, localDateToScalarStart, parseLocalDate, parseLocalDateTime } from "../../modules/ResourcePlanner/localClock";
|
|
46
|
-
import { isCustomerUserPlatform } from "../../utils/platform";
|
|
46
|
+
import { isCustomerUserPlatform, normalizeRuntimePlatform } from "../../utils/platform";
|
|
47
47
|
import { ItemRuleEvaluator } from "../../model/strategy/adapter/itemRule";
|
|
48
48
|
export * from "./types";
|
|
49
49
|
export { AvailabilityError } from "../../modules/ResourcePlanner";
|
|
@@ -1053,7 +1053,7 @@ function buildBookingFromAvailabilitySelection(params) {
|
|
|
1053
1053
|
var timeSlotId = (_candidate$primarySch3 = (_candidate$primarySch4 = candidate.primaryScheduleRef) === null || _candidate$primarySch4 === void 0 ? void 0 : _candidate$primarySch4.timeSlotId) !== null && _candidate$primarySch3 !== void 0 ? _candidate$primarySch3 : (_assignments$find2 = assignments.find(function (assignment) {
|
|
1054
1054
|
return assignment.timeSlotId != null;
|
|
1055
1055
|
})) === null || _assignments$find2 === void 0 ? void 0 : _assignments$find2.timeSlotId;
|
|
1056
|
-
if (product.kind === 'session' && scheduleId == null) {
|
|
1056
|
+
if (product.kind === 'session' && candidate.source === 'session_schedule' && scheduleId == null) {
|
|
1057
1057
|
throw new AvailabilityError('REVALIDATION_FAILED', 'session 候选缺少真实 schedule identity', {
|
|
1058
1058
|
productId: product.id,
|
|
1059
1059
|
candidateKey: candidate.key,
|
|
@@ -1062,15 +1062,16 @@ function buildBookingFromAvailabilitySelection(params) {
|
|
|
1062
1062
|
}
|
|
1063
1063
|
var normalizedHolder = holder && _typeof(holder) === 'object' ? cloneDeep(holder) : undefined;
|
|
1064
1064
|
var normalizedHolderIds = Array.isArray(holderIds) ? cloneDeep(holderIds) : holderIds;
|
|
1065
|
-
return _objectSpread(_objectSpread({
|
|
1065
|
+
return _objectSpread(_objectSpread(_objectSpread({
|
|
1066
1066
|
start_date: bookingStartAt.slice(0, 10),
|
|
1067
1067
|
start_time: bookingStartAt.slice(11, 16),
|
|
1068
1068
|
end_date: bookingEndAt.slice(0, 10),
|
|
1069
1069
|
end_time: bookingEndAt.slice(11, 16),
|
|
1070
1070
|
duration: Math.max(1, Math.trunc((endScalar - startScalar) / (60 * 1000))),
|
|
1071
|
-
like_status: 'common'
|
|
1071
|
+
like_status: 'common'
|
|
1072
|
+
}, product.kind === 'session' && candidate.source === 'duration_window' ? {} : {
|
|
1072
1073
|
schedule_id: scheduleId !== null && scheduleId !== void 0 ? scheduleId : 0
|
|
1073
|
-
}, normalizedHolder ? {
|
|
1074
|
+
}), normalizedHolder ? {
|
|
1074
1075
|
holder: normalizedHolder
|
|
1075
1076
|
} : {}), {}, {
|
|
1076
1077
|
resources: assignments.map(function (assignment) {
|
|
@@ -1867,15 +1868,17 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
|
|
|
1867
1868
|
}
|
|
1868
1869
|
|
|
1869
1870
|
/**
|
|
1870
|
-
* Kiosk
|
|
1871
|
-
*
|
|
1871
|
+
* H5/Kiosk 不能把已收款订单留在本地等待重试,必须直接等待云端 checkout。
|
|
1872
|
+
* 其它平台保持 WebPOS/POS 的本地待同步任务;显式 true 仍可强制使用本地任务。
|
|
1872
1873
|
*/
|
|
1873
1874
|
}, {
|
|
1874
1875
|
key: "shouldUseCheckoutSyncTask",
|
|
1875
1876
|
value: function shouldUseCheckoutSyncTask() {
|
|
1876
|
-
var _this$otherParams15;
|
|
1877
|
+
var _this$otherParams15, _this$otherParams16;
|
|
1877
1878
|
var configured = (_this$otherParams15 = this.otherParams) === null || _this$otherParams15 === void 0 ? void 0 : _this$otherParams15.checkoutSyncTaskEnabled;
|
|
1878
|
-
|
|
1879
|
+
if (configured === true) return true;
|
|
1880
|
+
var platform = normalizeRuntimePlatform((_this$otherParams16 = this.otherParams) === null || _this$otherParams16 === void 0 ? void 0 : _this$otherParams16.platform);
|
|
1881
|
+
return platform !== 'h5' && platform !== 'kiosk';
|
|
1879
1882
|
}
|
|
1880
1883
|
|
|
1881
1884
|
/** UnifiedBookingSales 的真实结账默认请求收据数据,供云端确认后再本地打印。 */
|
|
@@ -2029,8 +2032,8 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
|
|
|
2029
2032
|
}, {
|
|
2030
2033
|
key: "isAuthenticatedCustomerUserPlatform",
|
|
2031
2034
|
value: function isAuthenticatedCustomerUserPlatform() {
|
|
2032
|
-
var _this$
|
|
2033
|
-
return isCustomerUserPlatform((_this$
|
|
2035
|
+
var _this$otherParams17;
|
|
2036
|
+
return isCustomerUserPlatform((_this$otherParams17 = this.otherParams) === null || _this$otherParams17 === void 0 ? void 0 : _this$otherParams17.platform);
|
|
2034
2037
|
}
|
|
2035
2038
|
}, {
|
|
2036
2039
|
key: "resolveDiscountOrderIdentity",
|
|
@@ -2208,13 +2211,13 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
|
|
|
2208
2211
|
key: "getOpenData",
|
|
2209
2212
|
value: function () {
|
|
2210
2213
|
var _getOpenData = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee12() {
|
|
2211
|
-
var _this$
|
|
2214
|
+
var _this$otherParams18, _this$otherParams19, _this$store$openData;
|
|
2212
2215
|
var businessCode, channel, target, cachedData;
|
|
2213
2216
|
return _regeneratorRuntime().wrap(function _callee12$(_context12) {
|
|
2214
2217
|
while (1) switch (_context12.prev = _context12.next) {
|
|
2215
2218
|
case 0:
|
|
2216
|
-
businessCode = String(((_this$
|
|
2217
|
-
channel = String(((_this$
|
|
2219
|
+
businessCode = String(((_this$otherParams18 = this.otherParams) === null || _this$otherParams18 === void 0 ? void 0 : _this$otherParams18.businessCode) || '').trim();
|
|
2220
|
+
channel = String(((_this$otherParams19 = this.otherParams) === null || _this$otherParams19 === void 0 ? void 0 : _this$otherParams19.channel) || '').trim();
|
|
2218
2221
|
if (!(!businessCode || !channel)) {
|
|
2219
2222
|
_context12.next = 4;
|
|
2220
2223
|
break;
|
|
@@ -2381,7 +2384,7 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
|
|
|
2381
2384
|
key: "resolveProductAllergyRequirement",
|
|
2382
2385
|
value: (function () {
|
|
2383
2386
|
var _resolveProductAllergyRequirement = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee16(params) {
|
|
2384
|
-
var _this$
|
|
2387
|
+
var _this$otherParams20, _this$getOrderProduct, _runtimePax$total, _runtimePax$adult, _runtimePax$child, _ref35, _runtimeConfig$servic, _this$otherParams21, _ref36, _ref37, _params$channel, _this$otherParams22, _this$otherParams23, _runtimeConfig$submis;
|
|
2385
2388
|
var productId, strategyConfigs, productVariantId, runtimeConfig, runtimePax, cartItems;
|
|
2386
2389
|
return _regeneratorRuntime().wrap(function _callee16$(_context16) {
|
|
2387
2390
|
while (1) switch (_context16.prev = _context16.next) {
|
|
@@ -2404,7 +2407,7 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
|
|
|
2404
2407
|
return _context16.abrupt("return", null);
|
|
2405
2408
|
case 8:
|
|
2406
2409
|
productVariantId = normalizePositiveInteger(params.productVariantId);
|
|
2407
|
-
runtimeConfig = ((_this$
|
|
2410
|
+
runtimeConfig = ((_this$otherParams20 = this.otherParams) === null || _this$otherParams20 === void 0 ? void 0 : _this$otherParams20.itemRule) || {};
|
|
2408
2411
|
runtimePax = runtimeConfig.pax || {};
|
|
2409
2412
|
cartItems = (((_this$getOrderProduct = this.getOrderProducts) === null || _this$getOrderProduct === void 0 ? void 0 : _this$getOrderProduct.call(this)) || []).map(function (item) {
|
|
2410
2413
|
var _item$product_id, _item$product_variant, _ref34, _item$num;
|
|
@@ -2423,8 +2426,8 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
|
|
|
2423
2426
|
child: Number((_runtimePax$child = runtimePax.child) !== null && _runtimePax$child !== void 0 ? _runtimePax$child : 0) || 0
|
|
2424
2427
|
},
|
|
2425
2428
|
cartItems: cartItems,
|
|
2426
|
-
serviceType: String((_ref35 = (_runtimeConfig$servic = runtimeConfig.serviceType) !== null && _runtimeConfig$servic !== void 0 ? _runtimeConfig$servic : (_this$
|
|
2427
|
-
channel: String((_ref36 = (_ref37 = (_params$channel = params.channel) !== null && _params$channel !== void 0 ? _params$channel : (_this$
|
|
2429
|
+
serviceType: String((_ref35 = (_runtimeConfig$servic = runtimeConfig.serviceType) !== null && _runtimeConfig$servic !== void 0 ? _runtimeConfig$servic : (_this$otherParams21 = this.otherParams) === null || _this$otherParams21 === void 0 ? void 0 : _this$otherParams21.serviceType) !== null && _ref35 !== void 0 ? _ref35 : ''),
|
|
2430
|
+
channel: String((_ref36 = (_ref37 = (_params$channel = params.channel) !== null && _params$channel !== void 0 ? _params$channel : (_this$otherParams22 = this.otherParams) === null || _this$otherParams22 === void 0 ? void 0 : _this$otherParams22.channel) !== null && _ref37 !== void 0 ? _ref37 : (_this$otherParams23 = this.otherParams) === null || _this$otherParams23 === void 0 ? void 0 : _this$otherParams23.platform) !== null && _ref36 !== void 0 ? _ref36 : ''),
|
|
2428
2431
|
currentProduct: _objectSpread({
|
|
2429
2432
|
product_id: productId
|
|
2430
2433
|
}, productVariantId ? {
|
|
@@ -4466,13 +4469,14 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
|
|
|
4466
4469
|
value: (function () {
|
|
4467
4470
|
var _getProductTimeRanges = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee40(contextId) {
|
|
4468
4471
|
var _this$otherParams$pla,
|
|
4469
|
-
_this$
|
|
4472
|
+
_this$otherParams24,
|
|
4470
4473
|
_this10 = this;
|
|
4471
4474
|
var request,
|
|
4472
4475
|
_yield$this$ensureAva,
|
|
4473
4476
|
context,
|
|
4474
4477
|
projectionEntry,
|
|
4475
4478
|
contextVersion,
|
|
4479
|
+
isPosAvailabilityRequest,
|
|
4476
4480
|
allowOutsideOperatingHoursForRequestedStartTimes,
|
|
4477
4481
|
_args40 = arguments;
|
|
4478
4482
|
return _regeneratorRuntime().wrap(function _callee40$(_context40) {
|
|
@@ -4486,13 +4490,15 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
|
|
|
4486
4490
|
context = _yield$this$ensureAva.context;
|
|
4487
4491
|
projectionEntry = _yield$this$ensureAva.projectionEntry;
|
|
4488
4492
|
contextVersion = context.activeVersion;
|
|
4489
|
-
|
|
4493
|
+
isPosAvailabilityRequest = String((_this$otherParams$pla = (_this$otherParams24 = this.otherParams) === null || _this$otherParams24 === void 0 ? void 0 : _this$otherParams24.platform) !== null && _this$otherParams$pla !== void 0 ? _this$otherParams$pla : '').trim().toLowerCase() === 'pos';
|
|
4494
|
+
allowOutsideOperatingHoursForRequestedStartTimes = isPosAvailabilityRequest && Object.values(request.durationStartTimesByProductId || {}).some(function (startTimes) {
|
|
4490
4495
|
return Array.isArray(startTimes) && startTimes.length > 0;
|
|
4491
4496
|
});
|
|
4492
4497
|
return _context40.abrupt("return", getProjectionProductTimeRanges(projectionEntry.projection, _objectSpread(_objectSpread({}, request), allowOutsideOperatingHoursForRequestedStartTimes ? {
|
|
4493
4498
|
allowOutsideOperatingHoursForRequestedStartTimes: true
|
|
4494
4499
|
} : {}), {
|
|
4495
|
-
evaluatedAt: this.getAvailabilityRuntimeDateTime()
|
|
4500
|
+
evaluatedAt: this.getAvailabilityRuntimeDateTime(),
|
|
4501
|
+
allowSessionCustomRanges: isPosAvailabilityRequest
|
|
4496
4502
|
}).map(function (group) {
|
|
4497
4503
|
return _objectSpread(_objectSpread({}, group), {}, {
|
|
4498
4504
|
ranges: group.ranges.map(function (candidate) {
|
|
@@ -4500,7 +4506,7 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
|
|
|
4500
4506
|
})
|
|
4501
4507
|
});
|
|
4502
4508
|
}));
|
|
4503
|
-
case
|
|
4509
|
+
case 10:
|
|
4504
4510
|
case "end":
|
|
4505
4511
|
return _context40.stop();
|
|
4506
4512
|
}
|
|
@@ -4636,7 +4642,7 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
|
|
|
4636
4642
|
key: "commitAvailabilitySelection",
|
|
4637
4643
|
value: (function () {
|
|
4638
4644
|
var _commitAvailabilitySelection = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee42(contextId, params) {
|
|
4639
|
-
var normalizedContextId, _params$bookingCount, _ref51, _params$orderProduct$, _params$orderProduct, _params$orderProduct2, _params$orderProduct3, _params$orderProduct$2, _params$orderProduct4, _params$orderProduct5, _editingLine$product_, _baseProjection$meta$, _refreshedProjection$, _baseProjection$meta$2, _this$otherParams$pla2, _this$
|
|
4645
|
+
var normalizedContextId, _params$bookingCount, _ref51, _params$orderProduct$, _params$orderProduct, _params$orderProduct2, _params$orderProduct3, _params$orderProduct$2, _params$orderProduct4, _params$orderProduct5, _editingLine$product_, _baseProjection$meta$, _refreshedProjection$, _baseProjection$meta$2, _this$otherParams$pla2, _this$otherParams25, _ref52, _params$orderProduct$3, _params$orderProduct6, _existingBooking$meta, _ref53, _ref54, _params$orderProduct$4, _params$orderProduct7, _params$orderProduct8, _existingBooking$meta2, _existingBooking$hold, bookingCount, orderProductQuantity, partySize, _yield$this$ensureAva3, context, projectionEntry, refreshed, boundEditingUids, orderProductId, editingLine, _editingLine$product_2, baseProjection, commitWriteGuard, prepareParams, fallbackResources, commitSnapshot, refreshedProjection, _baseProjection$meta$3, latestContext, candidateDurationMinutes, candidateStartTime, allowPosAvailabilityOverride, refreshedRanges, refreshedCandidateBase, product, validation, forced, capacityConflict, revalidationEntry, revalidatedContext, refreshedCandidate, existingBooking, existingBookingUid, booking, transformed, productLineUid, bookingUid, productLineUids, bookingUids, _transformed$product_, _transformed$product_2, _transformed$product_3, _ref55, _transformed$product_4, _this$getTempOrder4, _this$getTempOrder5, _params$salesNotes, _this$getTempOrder6, beforeProductLineUids, beforeBookingUids, products, addedLines, addedBookings, nextContext, result;
|
|
4640
4646
|
return _regeneratorRuntime().wrap(function _callee42$(_context42) {
|
|
4641
4647
|
while (1) switch (_context42.prev = _context42.next) {
|
|
4642
4648
|
case 0:
|
|
@@ -4866,7 +4872,7 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
|
|
|
4866
4872
|
this.assertAvailabilityCommitWriteCAS(commitWriteGuard);
|
|
4867
4873
|
candidateDurationMinutes = getCandidateDurationMinutes(params.candidate);
|
|
4868
4874
|
candidateStartTime = getCandidateStartTime(params.candidate);
|
|
4869
|
-
allowPosAvailabilityOverride = String((_this$otherParams$pla2 = (_this$
|
|
4875
|
+
allowPosAvailabilityOverride = String((_this$otherParams$pla2 = (_this$otherParams25 = this.otherParams) === null || _this$otherParams25 === void 0 ? void 0 : _this$otherParams25.platform) !== null && _this$otherParams$pla2 !== void 0 ? _this$otherParams$pla2 : '').trim().toLowerCase() === 'pos';
|
|
4870
4876
|
refreshedRanges = getProjectionProductTimeRanges(refreshedProjection, _objectSpread({
|
|
4871
4877
|
productIds: [params.candidate.productId],
|
|
4872
4878
|
dateRange: {
|
|
@@ -4879,7 +4885,9 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
|
|
|
4879
4885
|
durationStartTimesByProductId: _defineProperty({}, String(params.candidate.productId), [candidateStartTime])
|
|
4880
4886
|
}, allowPosAvailabilityOverride ? {
|
|
4881
4887
|
allowOutsideOperatingHoursForRequestedStartTimes: true
|
|
4882
|
-
} : {}) : {}) : {})
|
|
4888
|
+
} : {}) : {}) : {}), {
|
|
4889
|
+
allowSessionCustomRanges: allowPosAvailabilityOverride
|
|
4890
|
+
}).flatMap(function (group) {
|
|
4883
4891
|
return group.ranges;
|
|
4884
4892
|
});
|
|
4885
4893
|
refreshedCandidateBase = refreshedRanges.find(function (candidate) {
|
|
@@ -1 +1,46 @@
|
|
|
1
|
-
"use strict";
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "BUY_X_GET_Y_FREE_STRATEGY", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _examples.BUY_X_GET_Y_FREE_STRATEGY;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(exports, "ITEM_REWARD_STRATEGY", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () {
|
|
15
|
+
return _examples.ITEM_REWARD_STRATEGY;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
Object.defineProperty(exports, "PromotionAdapter", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () {
|
|
21
|
+
return _adapter.PromotionAdapter;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(exports, "PromotionEvaluator", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () {
|
|
27
|
+
return _evaluator.PromotionEvaluator;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(exports, "X_ITEMS_FOR_Y_PRICE_STRATEGY", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
get: function () {
|
|
33
|
+
return _examples.X_ITEMS_FOR_Y_PRICE_STRATEGY;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(exports, "default", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
get: function () {
|
|
39
|
+
return _adapter.default;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
var _evaluator = require("./evaluator");
|
|
43
|
+
var _adapter = _interopRequireWildcard(require("./adapter"));
|
|
44
|
+
var _examples = require("./examples");
|
|
45
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
46
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
@@ -264,12 +264,12 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
264
264
|
product.product_bundle = product.product_bundle.map(bundle => {
|
|
265
265
|
const hasBundleDiscount = Array.isArray(bundle?.discount_list) && bundle.discount_list.length > 0;
|
|
266
266
|
if (hasBundleDiscount) return bundle;
|
|
267
|
-
const restoredPrice = bundle?.
|
|
267
|
+
const restoredPrice = bundle?.price ?? bundle?.original_price ?? bundle?.product_price;
|
|
268
268
|
if (restoredPrice === undefined || restoredPrice === null || restoredPrice === '') return bundle;
|
|
269
269
|
return {
|
|
270
270
|
...bundle,
|
|
271
271
|
price: restoredPrice,
|
|
272
|
-
bundle_selling_price: restoredPrice
|
|
272
|
+
bundle_selling_price: bundle?.bundle_selling_price ?? restoredPrice
|
|
273
273
|
};
|
|
274
274
|
});
|
|
275
275
|
}
|
|
@@ -650,17 +650,20 @@ class WalletPassPaymentImpl {
|
|
|
650
650
|
this.paymentModule.logInfo('[WalletPass] 商品列表为空,跳过获取用户识别码列表');
|
|
651
651
|
return [];
|
|
652
652
|
}
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
653
|
+
|
|
654
|
+
// const platform = this.paymentModule.getPlatform();
|
|
655
|
+
// if (platform === 'pc' || platform === 'h5') {
|
|
656
|
+
// this.userIdentificationCodes = [];
|
|
657
|
+
// this.emitEvent(WalletPassHooks.OnUserIdentificationCodesUpdated, {
|
|
658
|
+
// userIdentificationCodes: [],
|
|
659
|
+
// } as OnUserIdentificationCodesUpdatedEventData);
|
|
660
|
+
// this.paymentModule.logInfo(
|
|
661
|
+
// '[WalletPass] 用户端平台跳过获取用户识别码列表',
|
|
662
|
+
// { platform },
|
|
663
|
+
// );
|
|
664
|
+
// return [];
|
|
665
|
+
// }
|
|
666
|
+
|
|
664
667
|
if (typeof newParams.payment_order_id === 'string' && newParams.payment_order_id.startsWith('LOCAL_')) {
|
|
665
668
|
newParams.payment_order_id = undefined;
|
|
666
669
|
}
|
|
@@ -55,12 +55,18 @@ function resolveRequestedDurationMinutes(product, request) {
|
|
|
55
55
|
const normalized = Number(override);
|
|
56
56
|
return Number.isInteger(normalized) && normalized > 0 ? normalized : configured;
|
|
57
57
|
}
|
|
58
|
-
function resolveRequestedDurationStartTimes(product, request) {
|
|
59
|
-
if (product.kind !== 'duration') return [];
|
|
58
|
+
function resolveRequestedDurationStartTimes(product, request, allowSessionCustomRanges = false) {
|
|
59
|
+
if (product.kind !== 'duration' && !(product.kind === 'session' && allowSessionCustomRanges)) return [];
|
|
60
60
|
const values = request.durationStartTimesByProductId?.[String(product.id)];
|
|
61
61
|
if (!Array.isArray(values)) return [];
|
|
62
62
|
return Array.from(new Set(values.filter(value => typeof value === 'string' && /^([01]\d|2[0-3]):[0-5]\d$/.test(value))));
|
|
63
63
|
}
|
|
64
|
+
function resolveRequestedSessionDurationMinutes(product, request, allowSessionCustomRanges) {
|
|
65
|
+
if (product.kind !== 'session' || !allowSessionCustomRanges) return undefined;
|
|
66
|
+
const override = request.durationMinutesByProductId?.[String(product.id)];
|
|
67
|
+
const normalized = Number(override);
|
|
68
|
+
return Number.isInteger(normalized) && normalized > 0 ? normalized : undefined;
|
|
69
|
+
}
|
|
64
70
|
function toDateTime(value, _timezoneName) {
|
|
65
71
|
try {
|
|
66
72
|
return (0, _localClock.localDateTimeToScalar)((0, _localClock.parseLocalDateTime)(value));
|
|
@@ -207,7 +213,11 @@ function evaluateCandidateTimeGate(params) {
|
|
|
207
213
|
};
|
|
208
214
|
}
|
|
209
215
|
if (policy.type === 'before_start') {
|
|
210
|
-
|
|
216
|
+
// Flexible-duration candidates start at minute precision. Keep the current
|
|
217
|
+
// minute selectable instead of treating the freshly generated candidate as
|
|
218
|
+
// already started because the query clock still contains seconds.
|
|
219
|
+
const hasNotReachedStart = product.isFlexibleDuration ? floorToMinute(now) <= candidateRange.start : now < candidateRange.start;
|
|
220
|
+
if (hasNotReachedStart) return null;
|
|
211
221
|
return {
|
|
212
222
|
status: 'unavailable',
|
|
213
223
|
reasonCodes: ['booking_cutoff_before_start'],
|
|
@@ -919,12 +929,23 @@ function getProductTimeRanges(projection, request = {}, runtimeOptions = {}) {
|
|
|
919
929
|
};
|
|
920
930
|
}
|
|
921
931
|
if (product.kind === 'session' || product.kind === 'venue_slot') {
|
|
932
|
+
const fixedRanges = getSessionRangesForProduct(projection, product, dateRange);
|
|
933
|
+
const customRanges = [];
|
|
934
|
+
const customDurationMinutes = resolveRequestedSessionDurationMinutes(product, request, runtimeOptions.allowSessionCustomRanges === true);
|
|
935
|
+
const requestedStartTimes = resolveRequestedDurationStartTimes(product, request, runtimeOptions.allowSessionCustomRanges === true);
|
|
936
|
+
if (product.kind === 'session' && customDurationMinutes && dateRange.startDate === dateRange.endDate) {
|
|
937
|
+
requestedStartTimes.forEach(startTime => {
|
|
938
|
+
const start = toDateTimeInDate(dateRange.startDate, startTime, projection.meta.timezone);
|
|
939
|
+
if (!Number.isFinite(start)) return;
|
|
940
|
+
customRanges.push(createDurationTimeRange(product, start, customDurationMinutes, projection, fixedOffsetMinutes));
|
|
941
|
+
});
|
|
942
|
+
}
|
|
922
943
|
return {
|
|
923
944
|
productId: product.id,
|
|
924
945
|
title: product.title,
|
|
925
946
|
kind: product.kind,
|
|
926
947
|
slotStepMinutes,
|
|
927
|
-
ranges:
|
|
948
|
+
ranges: dedupeProductRanges([...fixedRanges, ...customRanges])
|
|
928
949
|
};
|
|
929
950
|
}
|
|
930
951
|
const requiredGroups = (product.requirementGroups || []).filter(group => group.required !== false);
|
|
@@ -243,6 +243,13 @@ export interface GetProductTimeRangesRequest {
|
|
|
243
243
|
}
|
|
244
244
|
export interface GetProductTimeRangesRuntimeOptions {
|
|
245
245
|
evaluatedAt?: string;
|
|
246
|
+
/**
|
|
247
|
+
* Internal POS capability: allow explicit duration/start overrides to append
|
|
248
|
+
* a custom duration candidate for Session products. Fixed Session ranges are
|
|
249
|
+
* still returned unchanged. Callers outside the POS facade must leave this
|
|
250
|
+
* disabled.
|
|
251
|
+
*/
|
|
252
|
+
allowSessionCustomRanges?: boolean;
|
|
246
253
|
}
|
|
247
254
|
export interface QueryAvailabilityBaseRequest {
|
|
248
255
|
productIds?: AvailabilityId[];
|
|
@@ -1129,6 +1129,7 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
1129
1129
|
...flatItem,
|
|
1130
1130
|
discount_list: isManualDiscount ? this.resolveDiscountListForManualOverride(flatItem.bundleItem?.discount_list || []) : this.filterDiscountListByType(flatItem.bundleItem?.discount_list || [], 'promotion'),
|
|
1131
1131
|
price: isManualDiscount ? flatItem.bundleItem.price : flatItem.bundleItem.original_price,
|
|
1132
|
+
bundle_selling_price: flatItem.bundleItem.bundle_selling_price ?? (isManualDiscount ? flatItem.bundleItem.price : flatItem.bundleItem.original_price),
|
|
1132
1133
|
processed: true
|
|
1133
1134
|
}]);
|
|
1134
1135
|
}
|
|
@@ -22,6 +22,8 @@ const LABELS = {
|
|
|
22
22
|
pickUpTime: 'Pick-up time',
|
|
23
23
|
asap: 'ASAP',
|
|
24
24
|
cash: 'Cash',
|
|
25
|
+
cashReceived: 'Cash received',
|
|
26
|
+
changeDue: 'Change due',
|
|
25
27
|
eftpos: 'Eftpos',
|
|
26
28
|
wallet: 'Wallet',
|
|
27
29
|
giftCard: 'Gift card',
|
|
@@ -49,6 +51,8 @@ const LABELS = {
|
|
|
49
51
|
pickUpTime: '取餐时间',
|
|
50
52
|
asap: '尽快',
|
|
51
53
|
cash: '现金支付',
|
|
54
|
+
cashReceived: '收取现金',
|
|
55
|
+
changeDue: '找零',
|
|
52
56
|
eftpos: '刷卡支付',
|
|
53
57
|
wallet: '钱包支付',
|
|
54
58
|
giftCard: '礼品卡',
|
|
@@ -76,6 +80,8 @@ const LABELS = {
|
|
|
76
80
|
pickUpTime: '取餐時間',
|
|
77
81
|
asap: '盡快',
|
|
78
82
|
cash: '現金支付',
|
|
83
|
+
cashReceived: '收取現金',
|
|
84
|
+
changeDue: '找零',
|
|
79
85
|
eftpos: '刷卡支付',
|
|
80
86
|
wallet: '錢包支付',
|
|
81
87
|
giftCard: '禮品卡',
|
|
@@ -90,6 +96,14 @@ const LABELS = {
|
|
|
90
96
|
rounding: '抹零',
|
|
91
97
|
gross: '重量',
|
|
92
98
|
tare: '去皮'
|
|
99
|
+
},
|
|
100
|
+
ja: {
|
|
101
|
+
cashReceived: 'お預かり',
|
|
102
|
+
changeDue: 'お釣り'
|
|
103
|
+
},
|
|
104
|
+
pt: {
|
|
105
|
+
cashReceived: 'Dinheiro recebido',
|
|
106
|
+
changeDue: 'Troco'
|
|
93
107
|
}
|
|
94
108
|
};
|
|
95
109
|
function buildSmallTicketData(params) {
|
|
@@ -169,7 +183,7 @@ function buildBaseData(params) {
|
|
|
169
183
|
order_number: orderNumber,
|
|
170
184
|
shop_tax_number: stringify(shopInfo.tax_number || order.shop_tax_number),
|
|
171
185
|
shop_phone: stringify(shopInfo.phone || order.shop_phone),
|
|
172
|
-
shop_address: stringify(shopInfo.address || buildShopAddress(shopInfo) || order.shop_address),
|
|
186
|
+
shop_address: stringify(shopInfo.receipt_address || shopInfo.address || buildShopAddress(shopInfo) || order.shop_address),
|
|
173
187
|
original_payment_status: stringify(order.payment_status),
|
|
174
188
|
is_repeat: 0,
|
|
175
189
|
buzzer: stringify(order.buzzer || order.pickup_number || order.metadata?.buzzer),
|
|
@@ -807,6 +821,11 @@ function buildPaymentItems(params) {
|
|
|
807
821
|
item: paymentMethodName(payment, locale),
|
|
808
822
|
value: formatMoney(resolveReceiptPaymentAmount(payment, serviceFee), currencySymbol)
|
|
809
823
|
}];
|
|
824
|
+
items.push(...buildCashChangePaymentItems({
|
|
825
|
+
payment,
|
|
826
|
+
locale,
|
|
827
|
+
currencySymbol
|
|
828
|
+
}));
|
|
810
829
|
if (serviceFee.gt(0)) {
|
|
811
830
|
items.push({
|
|
812
831
|
item: label(locale, 'surchargeIncluded'),
|
|
@@ -848,6 +867,36 @@ function resolveReceiptPaymentAmount(payment, serviceFee) {
|
|
|
848
867
|
const originAmount = new _decimal.default(toMoneyNumber(payment.origin_amount));
|
|
849
868
|
return amount.eq(originAmount) ? amount.plus(serviceFee) : amount;
|
|
850
869
|
}
|
|
870
|
+
function buildCashChangePaymentItems(params) {
|
|
871
|
+
const {
|
|
872
|
+
payment,
|
|
873
|
+
locale,
|
|
874
|
+
currencySymbol
|
|
875
|
+
} = params;
|
|
876
|
+
if (!shouldDisplayCashChange(payment)) return [];
|
|
877
|
+
return [{
|
|
878
|
+
item: label(locale, 'cashReceived'),
|
|
879
|
+
value: formatMoney(payment.metadata.actual_paid_amount, currencySymbol)
|
|
880
|
+
}, {
|
|
881
|
+
item: label(locale, 'changeDue'),
|
|
882
|
+
value: formatMoney(payment.metadata.change_given_amount, currencySymbol)
|
|
883
|
+
}];
|
|
884
|
+
}
|
|
885
|
+
function shouldDisplayCashChange(payment) {
|
|
886
|
+
if (stringify(payment.status).toLowerCase() !== 'paid') return false;
|
|
887
|
+
const paymentMethod = stringify(payment.code ?? payment.payment_method).toUpperCase();
|
|
888
|
+
if (paymentMethod !== 'CASHMANUAL') return false;
|
|
889
|
+
const actualPaidAmount = payment.metadata?.actual_paid_amount;
|
|
890
|
+
const changeGivenAmount = payment.metadata?.change_given_amount;
|
|
891
|
+
if (!isNumericAmount(actualPaidAmount) || !isNumericAmount(changeGivenAmount)) return false;
|
|
892
|
+
return new _decimal.default(changeGivenAmount).toDecimalPlaces(2).gt(0);
|
|
893
|
+
}
|
|
894
|
+
function isNumericAmount(value) {
|
|
895
|
+
if (typeof value === 'number') return Number.isFinite(value);
|
|
896
|
+
if (typeof value !== 'string') return false;
|
|
897
|
+
const normalized = value.trim();
|
|
898
|
+
return normalized !== '' && /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i.test(normalized);
|
|
899
|
+
}
|
|
851
900
|
function buildFundRecordPaymentItems(params) {
|
|
852
901
|
const {
|
|
853
902
|
payment,
|
|
@@ -326,7 +326,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
|
|
|
326
326
|
date: string;
|
|
327
327
|
status: string;
|
|
328
328
|
week: string;
|
|
329
|
-
weekNum: 0 |
|
|
329
|
+
weekNum: 0 | 2 | 3 | 1 | 5 | 6 | 4;
|
|
330
330
|
}[]>;
|
|
331
331
|
submitTimeSlot(timeSlots: TimeSliceItem): void;
|
|
332
332
|
private getScheduleDataByIds;
|
|
@@ -345,7 +345,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
|
|
|
345
345
|
count: number;
|
|
346
346
|
left: number;
|
|
347
347
|
summaryCount: number;
|
|
348
|
-
status: "
|
|
348
|
+
status: "lots_of_space" | "filling_up_fast" | "sold_out";
|
|
349
349
|
}[];
|
|
350
350
|
/**
|
|
351
351
|
* 找到多个资源的公共可用时间段
|
|
@@ -130,8 +130,8 @@ export declare class UnifiedBookingSalesImpl extends BookingTicket {
|
|
|
130
130
|
*/
|
|
131
131
|
clearSessionStorageOrderSnapshot(): void;
|
|
132
132
|
/**
|
|
133
|
-
* Kiosk
|
|
134
|
-
*
|
|
133
|
+
* H5/Kiosk 不能把已收款订单留在本地等待重试,必须直接等待云端 checkout。
|
|
134
|
+
* 其它平台保持 WebPOS/POS 的本地待同步任务;显式 true 仍可强制使用本地任务。
|
|
135
135
|
*/
|
|
136
136
|
protected shouldUseCheckoutSyncTask(): boolean;
|
|
137
137
|
/** UnifiedBookingSales 的真实结账默认请求收据数据,供云端确认后再本地打印。 */
|
|
@@ -962,7 +962,7 @@ function buildBookingFromAvailabilitySelection(params) {
|
|
|
962
962
|
const endScalar = (0, _localClock.localDateTimeToScalar)((0, _localClock.parseLocalDateTime)(bookingEndAt));
|
|
963
963
|
const scheduleId = candidate.primaryScheduleRef?.scheduleId ?? assignments.find(assignment => assignment.scheduleId != null)?.scheduleId;
|
|
964
964
|
const timeSlotId = candidate.primaryScheduleRef?.timeSlotId ?? assignments.find(assignment => assignment.timeSlotId != null)?.timeSlotId;
|
|
965
|
-
if (product.kind === 'session' && scheduleId == null) {
|
|
965
|
+
if (product.kind === 'session' && candidate.source === 'session_schedule' && scheduleId == null) {
|
|
966
966
|
throw new _ResourcePlanner.AvailabilityError('REVALIDATION_FAILED', 'session 候选缺少真实 schedule identity', {
|
|
967
967
|
productId: product.id,
|
|
968
968
|
candidateKey: candidate.key,
|
|
@@ -978,7 +978,9 @@ function buildBookingFromAvailabilitySelection(params) {
|
|
|
978
978
|
end_time: bookingEndAt.slice(11, 16),
|
|
979
979
|
duration: Math.max(1, Math.trunc((endScalar - startScalar) / (60 * 1000))),
|
|
980
980
|
like_status: 'common',
|
|
981
|
-
|
|
981
|
+
...(product.kind === 'session' && candidate.source === 'duration_window' ? {} : {
|
|
982
|
+
schedule_id: scheduleId ?? 0
|
|
983
|
+
}),
|
|
982
984
|
...(normalizedHolder ? {
|
|
983
985
|
holder: normalizedHolder
|
|
984
986
|
} : {}),
|
|
@@ -1548,12 +1550,14 @@ class UnifiedBookingSalesImpl extends _BookingTicket.BookingTicket {
|
|
|
1548
1550
|
}
|
|
1549
1551
|
|
|
1550
1552
|
/**
|
|
1551
|
-
* Kiosk
|
|
1552
|
-
*
|
|
1553
|
+
* H5/Kiosk 不能把已收款订单留在本地等待重试,必须直接等待云端 checkout。
|
|
1554
|
+
* 其它平台保持 WebPOS/POS 的本地待同步任务;显式 true 仍可强制使用本地任务。
|
|
1553
1555
|
*/
|
|
1554
1556
|
shouldUseCheckoutSyncTask() {
|
|
1555
1557
|
const configured = this.otherParams?.checkoutSyncTaskEnabled;
|
|
1556
|
-
|
|
1558
|
+
if (configured === true) return true;
|
|
1559
|
+
const platform = (0, _platform.normalizeRuntimePlatform)(this.otherParams?.platform);
|
|
1560
|
+
return platform !== 'h5' && platform !== 'kiosk';
|
|
1557
1561
|
}
|
|
1558
1562
|
|
|
1559
1563
|
/** UnifiedBookingSales 的真实结账默认请求收据数据,供云端确认后再本地打印。 */
|
|
@@ -2929,14 +2933,16 @@ class UnifiedBookingSalesImpl extends _BookingTicket.BookingTicket {
|
|
|
2929
2933
|
projectionEntry
|
|
2930
2934
|
} = await this.ensureAvailabilityContextProjection(contextId, 'get_product_time_ranges');
|
|
2931
2935
|
const contextVersion = context.activeVersion;
|
|
2932
|
-
const
|
|
2936
|
+
const isPosAvailabilityRequest = String(this.otherParams?.platform ?? '').trim().toLowerCase() === 'pos';
|
|
2937
|
+
const allowOutsideOperatingHoursForRequestedStartTimes = isPosAvailabilityRequest && Object.values(request.durationStartTimesByProductId || {}).some(startTimes => Array.isArray(startTimes) && startTimes.length > 0);
|
|
2933
2938
|
return (0, _ResourcePlanner.getProductTimeRanges)(projectionEntry.projection, {
|
|
2934
2939
|
...request,
|
|
2935
2940
|
...(allowOutsideOperatingHoursForRequestedStartTimes ? {
|
|
2936
2941
|
allowOutsideOperatingHoursForRequestedStartTimes: true
|
|
2937
2942
|
} : {})
|
|
2938
2943
|
}, {
|
|
2939
|
-
evaluatedAt: this.getAvailabilityRuntimeDateTime()
|
|
2944
|
+
evaluatedAt: this.getAvailabilityRuntimeDateTime(),
|
|
2945
|
+
allowSessionCustomRanges: isPosAvailabilityRequest
|
|
2940
2946
|
}).map(group => ({
|
|
2941
2947
|
...group,
|
|
2942
2948
|
ranges: group.ranges.map(candidate => this.decorateAvailabilityCandidate(context.contextId, contextVersion, candidate))
|
|
@@ -3207,6 +3213,8 @@ class UnifiedBookingSalesImpl extends _BookingTicket.BookingTicket {
|
|
|
3207
3213
|
} : {})
|
|
3208
3214
|
} : {})
|
|
3209
3215
|
} : {})
|
|
3216
|
+
}, {
|
|
3217
|
+
allowSessionCustomRanges: allowPosAvailabilityOverride
|
|
3210
3218
|
}).flatMap(group => group.ranges);
|
|
3211
3219
|
const refreshedCandidateBase = refreshedRanges.find(candidate => candidate.startAt === params.candidate.startAt && candidate.endAt === params.candidate.endAt && candidate.bookingStartAt === params.candidate.bookingStartAt && candidate.bookingEndAt === params.candidate.bookingEndAt);
|
|
3212
3220
|
if (!refreshedCandidateBase) {
|