@pisell/pisellos 0.10.49 → 0.10.51
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/modules/Discount/types.d.ts +2 -0
- 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 +6 -0
- package/dist/modules/Order/index.d.ts +19 -1
- package/dist/modules/Order/index.js +362 -217
- package/dist/modules/Order/pickupTiming.d.ts +46 -0
- package/dist/modules/Order/pickupTiming.js +53 -0
- package/dist/modules/Order/types.d.ts +11 -1
- package/dist/modules/Order/utils.d.ts +10 -0
- package/dist/modules/Order/utils.js +145 -85
- package/dist/modules/Rules/index.js +45 -26
- package/dist/modules/Rules/types.d.ts +4 -0
- package/dist/modules/index.d.ts +1 -0
- package/dist/modules/index.js +1 -0
- package/dist/server/modules/order/index.d.ts +8 -0
- package/dist/server/modules/order/index.js +506 -453
- package/dist/server/modules/order/types.d.ts +1 -0
- package/dist/server/utils/small-ticket.js +173 -95
- package/dist/solution/BaseSales/index.d.ts +23 -0
- package/dist/solution/BaseSales/index.js +1216 -1031
- package/dist/solution/BaseSales/pickupTiming.d.ts +37 -0
- package/dist/solution/BaseSales/pickupTiming.js +482 -0
- package/dist/solution/BaseSales/utils/parseSalesResponse.js +3 -0
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/BookingTicket/utils/cartView.js +3 -1
- package/dist/solution/UnifiedBookingSales/index.d.ts +2 -0
- package/dist/solution/UnifiedBookingSales/index.js +583 -531
- package/lib/model/strategy/adapter/promotion/index.js +46 -1
- package/lib/modules/Discount/types.d.ts +2 -0
- 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 +6 -0
- package/lib/modules/Order/index.d.ts +19 -1
- package/lib/modules/Order/index.js +120 -7
- package/lib/modules/Order/pickupTiming.d.ts +46 -0
- package/lib/modules/Order/pickupTiming.js +61 -0
- package/lib/modules/Order/types.d.ts +11 -1
- package/lib/modules/Order/utils.d.ts +10 -0
- package/lib/modules/Order/utils.js +58 -4
- package/lib/modules/Rules/index.js +24 -13
- package/lib/modules/Rules/types.d.ts +4 -0
- package/lib/modules/index.d.ts +1 -0
- package/lib/modules/index.js +11 -0
- package/lib/server/modules/order/index.d.ts +8 -0
- package/lib/server/modules/order/index.js +19 -0
- package/lib/server/modules/order/types.d.ts +1 -0
- package/lib/server/utils/small-ticket.js +93 -22
- package/lib/solution/BaseSales/index.d.ts +23 -0
- package/lib/solution/BaseSales/index.js +104 -1
- package/lib/solution/BaseSales/pickupTiming.d.ts +37 -0
- package/lib/solution/BaseSales/pickupTiming.js +222 -0
- package/lib/solution/BaseSales/utils/parseSalesResponse.js +3 -0
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/BookingTicket/utils/cartView.js +3 -1
- package/lib/solution/UnifiedBookingSales/index.d.ts +2 -0
- package/lib/solution/UnifiedBookingSales/index.js +20 -0
- package/package.json +1 -1
|
@@ -29,6 +29,10 @@ export interface RulesCalcDiscountOptions {
|
|
|
29
29
|
discountId?: number;
|
|
30
30
|
selectedList?: SetDiscountSelectedParams[];
|
|
31
31
|
scan?: boolean;
|
|
32
|
+
/** 本次扫码优先使用的次卡实例;普通重算不传,继续保留商品行当前选择。 */
|
|
33
|
+
preferredEntitlementPassIds?: number[];
|
|
34
|
+
/** 普通重算保留商品行已应用的次卡;最优选择传 false 恢复自动排序。 */
|
|
35
|
+
preserveEntitlementSelection?: boolean;
|
|
32
36
|
/** Change time 重报价目标行:允许已选编辑态折扣卡重新应用到这些 booking 商品。 */
|
|
33
37
|
reapplyBookingDiscountProductUids?: string[];
|
|
34
38
|
}
|
package/lib/modules/index.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export * from './Schedule';
|
|
|
17
17
|
export * from './Quotation';
|
|
18
18
|
export * from './ScanOrderLogger';
|
|
19
19
|
export * from './OpenData';
|
|
20
|
+
export * from './FulfillmentTiming';
|
|
20
21
|
export * from './BookingContext';
|
|
21
22
|
export * from './Holder';
|
|
22
23
|
export * from './ResourcePlanner';
|
package/lib/modules/index.js
CHANGED
|
@@ -212,6 +212,17 @@ Object.keys(_OpenData).forEach(function (key) {
|
|
|
212
212
|
}
|
|
213
213
|
});
|
|
214
214
|
});
|
|
215
|
+
var _FulfillmentTiming = require("./FulfillmentTiming");
|
|
216
|
+
Object.keys(_FulfillmentTiming).forEach(function (key) {
|
|
217
|
+
if (key === "default" || key === "__esModule") return;
|
|
218
|
+
if (key in exports && exports[key] === _FulfillmentTiming[key]) return;
|
|
219
|
+
Object.defineProperty(exports, key, {
|
|
220
|
+
enumerable: true,
|
|
221
|
+
get: function () {
|
|
222
|
+
return _FulfillmentTiming[key];
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
});
|
|
215
226
|
var _BookingContext = require("./BookingContext");
|
|
216
227
|
Object.keys(_BookingContext).forEach(function (key) {
|
|
217
228
|
if (key === "default" || key === "__esModule") return;
|
|
@@ -24,6 +24,7 @@ export declare class OrderModule extends BaseModule implements Module {
|
|
|
24
24
|
private lastRecentSqliteWriteCleanupAtMs;
|
|
25
25
|
/** 最近一次 SSE 全量拉取完成时间 */
|
|
26
26
|
private lastServerFullFetchAtMs;
|
|
27
|
+
private businessDayRefreshPromise;
|
|
27
28
|
constructor(name?: string, version?: string);
|
|
28
29
|
/**
|
|
29
30
|
* 广播订单变更事件,兼容全量列表订阅并额外携带本次变更订单。
|
|
@@ -130,6 +131,13 @@ export declare class OrderModule extends BaseModule implements Module {
|
|
|
130
131
|
loadOrdersByServer(options?: {
|
|
131
132
|
trigger?: string;
|
|
132
133
|
}): Promise<OrderData[]>;
|
|
134
|
+
/**
|
|
135
|
+
* 供展示屏按需补齐当前营业日的订单快照;成功标记复用全量拉取落库逻辑。
|
|
136
|
+
* 拉取或落库失败时不记录已刷新,下一次调用仍可重试。
|
|
137
|
+
*/
|
|
138
|
+
refreshOrdersForCurrentBusinessDay(options?: {
|
|
139
|
+
trigger?: string;
|
|
140
|
+
}): Promise<void>;
|
|
133
141
|
/**
|
|
134
142
|
* 静默全量刷新:后台重新拉取全量 SSE 订单数据并更新本地
|
|
135
143
|
* 拿到完整数据后一次性替换 store,触发订单变更与同步完成事件
|
|
@@ -61,6 +61,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
61
61
|
lastRecentSqliteWriteCleanupAtMs = 0;
|
|
62
62
|
/** 最近一次 SSE 全量拉取完成时间 */
|
|
63
63
|
lastServerFullFetchAtMs = 0;
|
|
64
|
+
businessDayRefreshPromise = null;
|
|
64
65
|
constructor(name, version) {
|
|
65
66
|
super(name, version);
|
|
66
67
|
}
|
|
@@ -864,6 +865,24 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
864
865
|
return memoryOrders;
|
|
865
866
|
}
|
|
866
867
|
|
|
868
|
+
/**
|
|
869
|
+
* 供展示屏按需补齐当前营业日的订单快照;成功标记复用全量拉取落库逻辑。
|
|
870
|
+
* 拉取或落库失败时不记录已刷新,下一次调用仍可重试。
|
|
871
|
+
*/
|
|
872
|
+
async refreshOrdersForCurrentBusinessDay(options = {}) {
|
|
873
|
+
if (this.businessDayRefreshPromise) return this.businessDayRefreshPromise;
|
|
874
|
+
if (!this.orderDataSource || !this.getCurrentShopId() || this.hasPulledOrdersToday()) return;
|
|
875
|
+
const refreshPromise = this.silentRefresh({
|
|
876
|
+
trigger: options.trigger || 'business_day_rollover'
|
|
877
|
+
}).then(() => undefined);
|
|
878
|
+
this.businessDayRefreshPromise = refreshPromise;
|
|
879
|
+
try {
|
|
880
|
+
await refreshPromise;
|
|
881
|
+
} finally {
|
|
882
|
+
this.businessDayRefreshPromise = null;
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
|
|
867
886
|
/**
|
|
868
887
|
* 静默全量刷新:后台重新拉取全量 SSE 订单数据并更新本地
|
|
869
888
|
* 拿到完整数据后一次性替换 store,触发订单变更与同步完成事件
|
|
@@ -7,6 +7,7 @@ exports.buildSmallTicketData = buildSmallTicketData;
|
|
|
7
7
|
exports.hasSmallTicketData = hasSmallTicketData;
|
|
8
8
|
var _dayjs = _interopRequireDefault(require("dayjs"));
|
|
9
9
|
var _decimal = _interopRequireDefault(require("decimal.js"));
|
|
10
|
+
var _pickupTiming = require("../../modules/Order/pickupTiming");
|
|
10
11
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
12
|
const DEFAULT_LOCALES = ['en', 'zh_CN'];
|
|
12
13
|
const SERVICE_TYPE_LABEL_KEYS = {
|
|
@@ -511,7 +512,16 @@ function resolveProductBasePrice(product) {
|
|
|
511
512
|
const variantId = product.product_variant_id ?? product.variant_id;
|
|
512
513
|
const variant = Array.isArray(origin.variant) && isPresentId(variantId) ? origin.variant.find(item => isSameId(item?.id, variantId)) : undefined;
|
|
513
514
|
const isV2 = metadata.price_schema_version === 2 || metadata.price_schema_version === '2';
|
|
514
|
-
|
|
515
|
+
const quantity = toNumber(product.product_quantity ?? product.quantity ?? product.num ?? 1, 1);
|
|
516
|
+
const hasEntitlementPass = normalizeArray(product.discount_list).some(discount => getProductWalletDiscountType(discount) === 'entitlement_pass');
|
|
517
|
+
const hasOptions = normalizeArray(product.options).length > 0 || normalizeArray(product.product_sku?.option).length > 0;
|
|
518
|
+
const hasCombinations = normalizeArray(product.combinations).length > 0 || normalizeArray(product.product_bundle).length > 0 || normalizeArray(product.bundle).length > 0;
|
|
519
|
+
const aggregateSourcePrice = firstPresentValue(metadata.source_product_price, product.price);
|
|
520
|
+
const originalPrice = product.original_price;
|
|
521
|
+
// 部分旧 entitlement 商品把 source/price 持久化成了整行总价,但
|
|
522
|
+
// original_price 仍是单件价。仅在等式能明确证明该口径时做窄幅回退。
|
|
523
|
+
const useOriginalPriceAsLegacyUnitPrice = hasEntitlementPass && quantity > 1 && !hasOptions && !hasCombinations && isNumericAmount(aggregateSourcePrice) && isNumericAmount(originalPrice) && new _decimal.default(aggregateSourcePrice).eq(new _decimal.default(originalPrice).mul(quantity));
|
|
524
|
+
return firstPresentValue(useOriginalPriceAsLegacyUnitPrice ? originalPrice : undefined, metadata.source_product_price, variant?.price, product._origin?.price, product._origin?.base_price, !isV2 ? metadata.main_product_original_price : undefined, product.base_price, product.price);
|
|
515
525
|
}
|
|
516
526
|
function normalizeProductDiscounts(params) {
|
|
517
527
|
const {
|
|
@@ -527,7 +537,9 @@ function normalizeProductDiscounts(params) {
|
|
|
527
537
|
const title = resolveDiscountTitleWithPercent(discount, locale);
|
|
528
538
|
const amount = discount.amount ?? discount.value ?? discount.discount_amount;
|
|
529
539
|
const isMarkup = isManualMarkup(discount);
|
|
530
|
-
const
|
|
540
|
+
const isAggregatedBundleDiscount = Boolean(getReceiptDiscountBundleMapId(discount));
|
|
541
|
+
const isEntitlementPass = getProductWalletDiscountType(discount) === 'entitlement_pass';
|
|
542
|
+
const totalAmount = new _decimal.default(toMoneyNumber(amount)).mul(isAggregatedBundleDiscount || isEntitlementPass ? 1 : quantity);
|
|
531
543
|
const formattedAmount = isMarkup ? formatMoney(totalAmount.abs(), currencySymbol) : formatNegativeMoney(totalAmount, currencySymbol);
|
|
532
544
|
return {
|
|
533
545
|
item: title,
|
|
@@ -620,6 +632,9 @@ function buildProductQuantityPriceText(params) {
|
|
|
620
632
|
}
|
|
621
633
|
function resolveDiscountTitleWithPercent(discount, locale) {
|
|
622
634
|
const title = resolveDiscountTitle(discount, locale);
|
|
635
|
+
if (getProductWalletDiscountType(discount) === 'entitlement_pass') {
|
|
636
|
+
return title;
|
|
637
|
+
}
|
|
623
638
|
const percentRaw = discount.discount?.percent;
|
|
624
639
|
const cardType = discount.discount?.discount_card_type ?? 'percent';
|
|
625
640
|
const percent = percentRaw !== undefined && percentRaw !== null ? Math.trunc(Number(percentRaw)) : NaN;
|
|
@@ -760,9 +775,11 @@ function normalizeExistingCombinations(combinations, locale, currencySymbol) {
|
|
|
760
775
|
options: rawOptions
|
|
761
776
|
});
|
|
762
777
|
const nestedCombinations = Array.isArray(combination.combinations) ? normalizeExistingCombinations(combination.combinations, locale, currencySymbol) : [];
|
|
778
|
+
const productTitle = getBundleProductTitleSource(combination, locale);
|
|
763
779
|
const snapshot = {
|
|
764
780
|
...combination
|
|
765
781
|
};
|
|
782
|
+
delete snapshot.product_title;
|
|
766
783
|
delete snapshot.product_note;
|
|
767
784
|
delete snapshot.note;
|
|
768
785
|
delete snapshot.combinations;
|
|
@@ -782,6 +799,9 @@ function normalizeExistingCombinations(combinations, locale, currencySymbol) {
|
|
|
782
799
|
const shouldIncludeBasePrice = normalizedOptions.length > 0 || nestedCombinations.length > 0 || hasProductDiscount(combination, extensionList);
|
|
783
800
|
return {
|
|
784
801
|
...snapshot,
|
|
802
|
+
...(productTitle ? {
|
|
803
|
+
product_title: productTitle
|
|
804
|
+
} : {}),
|
|
785
805
|
product_quantity: quantity,
|
|
786
806
|
total_selling_price: formatCalculatedMoney(new _decimal.default(toMoneyNumber(unitPrice)).mul(quantity), currencySymbol),
|
|
787
807
|
...(shouldIncludeBasePrice ? {
|
|
@@ -850,18 +870,18 @@ function resolveBundleProductTitle(params) {
|
|
|
850
870
|
locale,
|
|
851
871
|
parentProduct
|
|
852
872
|
} = params;
|
|
853
|
-
const ownTitle =
|
|
873
|
+
const ownTitle = getBundleProductTitleSource(bundle, locale);
|
|
854
874
|
if (ownTitle) return ownTitle;
|
|
855
875
|
const parentBundleItem = resolveBundleItemFromParentProduct({
|
|
856
876
|
bundle,
|
|
857
877
|
parentProduct
|
|
858
878
|
});
|
|
859
|
-
const parentBundleTitle = parentBundleItem ?
|
|
879
|
+
const parentBundleTitle = parentBundleItem ? getBundleProductTitleSource(parentBundleItem, locale) : '';
|
|
860
880
|
if (parentBundleTitle) return parentBundleTitle;
|
|
861
881
|
const productId = bundle.bundle_product_id ?? bundle._bundle_product_id ?? bundle.product_id ?? bundle.id;
|
|
862
882
|
const fallbackProduct = resolveProductFromMap(productId, productMap);
|
|
863
883
|
if (!fallbackProduct) return '';
|
|
864
|
-
return
|
|
884
|
+
return getBundleProductTitleSource(fallbackProduct, locale);
|
|
865
885
|
}
|
|
866
886
|
function resolveProductFromMap(productId, productMap) {
|
|
867
887
|
if (productId === undefined || productId === null || productId === '') return null;
|
|
@@ -933,7 +953,11 @@ function resolveVariantItem(group, itemPositionId) {
|
|
|
933
953
|
}
|
|
934
954
|
function getProductTitleSource(source, locale) {
|
|
935
955
|
if (!source || typeof source !== 'object') return '';
|
|
936
|
-
return resolveTitleValue(source.product_title, locale) || resolveTitleValue(source.title, locale) || resolveTitleValue(source.name, locale);
|
|
956
|
+
return resolveTitleValue(source.product_title, locale) || resolveTitleValue(source.title_i18n, locale) || resolveTitleValue(source.title, locale) || resolveTitleValue(source.name, locale);
|
|
957
|
+
}
|
|
958
|
+
function getBundleProductTitleSource(source, locale) {
|
|
959
|
+
if (!source || typeof source !== 'object') return '';
|
|
960
|
+
return resolveTitleValue(source.bundle_title, locale) || resolveTitleValue(source.trans_title, locale) || resolveTitleValue(source.title_i18n, locale) || resolveTitleValue(source.product_title, locale) || resolveTitleValue(source.title, locale) || resolveTitleValue(source.name, locale);
|
|
937
961
|
}
|
|
938
962
|
function resolveTitleValue(value, locale) {
|
|
939
963
|
if (value === undefined || value === null) return '';
|
|
@@ -1173,11 +1197,21 @@ function buildDelivery(order, locale) {
|
|
|
1173
1197
|
const serviceTypeLabelKey = resolveServiceTypeLabelKey(serviceType);
|
|
1174
1198
|
if (!serviceTypeLabelKey) return [];
|
|
1175
1199
|
const items = [{
|
|
1176
|
-
item:
|
|
1177
|
-
value:
|
|
1178
|
-
size: 2
|
|
1179
|
-
align: 'left'
|
|
1200
|
+
item: label(locale, serviceTypeLabelKey),
|
|
1201
|
+
value: '',
|
|
1202
|
+
size: 2
|
|
1180
1203
|
}];
|
|
1204
|
+
if (serviceType === 'pick_up') {
|
|
1205
|
+
const pickupTime = formatPickupBookingStart(order.bookings, locale);
|
|
1206
|
+
if (pickupTime) {
|
|
1207
|
+
items.push({
|
|
1208
|
+
item: pickupTime,
|
|
1209
|
+
value: '',
|
|
1210
|
+
size: 2
|
|
1211
|
+
});
|
|
1212
|
+
return items;
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1181
1215
|
const handoverTime = firstPresentValue(order.handover_time, order.handover_at, order.pickup_time, order.pickup_at, order.scheduled_pickup_time, order.delivery_time, order.delivery_at, order.scheduled_delivery_time, order.fulfillment_time, order.fulfillment_at, order.metadata?.handover_time, order.metadata?.handover_at, order.metadata?.pickup_time, order.metadata?.pickup_at, order.metadata?.scheduled_pickup_time, order.metadata?.delivery_time, order.metadata?.delivery_at, order.metadata?.scheduled_delivery_time, order.metadata?.fulfillment_time, order.metadata?.fulfillment_at);
|
|
1182
1216
|
if (isPresentId(handoverTime)) {
|
|
1183
1217
|
items.push({
|
|
@@ -1187,8 +1221,27 @@ function buildDelivery(order, locale) {
|
|
|
1187
1221
|
}
|
|
1188
1222
|
return items;
|
|
1189
1223
|
}
|
|
1224
|
+
function formatPickupBookingStart(bookings, locale) {
|
|
1225
|
+
const booking = normalizeArray(bookings).find(_pickupTiming.isFulfillmentTimingBooking);
|
|
1226
|
+
const date = stringify(booking?.start_date).trim();
|
|
1227
|
+
const time = stringify(booking?.start_time).trim();
|
|
1228
|
+
if (!/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/.test(date) || !/^([01]\d|2[0-3]):[0-5]\d(?::[0-5]\d)?$/.test(time)) {
|
|
1229
|
+
return '';
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
// Validate only the calendar date in UTC; display the stored shop-local
|
|
1233
|
+
// fields verbatim so the printing device's timezone cannot shift pickup.
|
|
1234
|
+
const calendarDate = new Date(`${date}T00:00:00.000Z`);
|
|
1235
|
+
if (!Number.isFinite(calendarDate.getTime()) || calendarDate.toISOString().slice(0, 10) !== date) {
|
|
1236
|
+
return '';
|
|
1237
|
+
}
|
|
1238
|
+
const [year, month, day] = date.split('-');
|
|
1239
|
+
const dateText = locale === 'en' ? `${day}/${month}/${year}` : `${year}/${month}/${day}`;
|
|
1240
|
+
return `${time.slice(0, 5)} ${dateText}`;
|
|
1241
|
+
}
|
|
1190
1242
|
function buildAppointment(order, locale) {
|
|
1191
|
-
const
|
|
1243
|
+
const parentScheduleId = order.metadata?.appointment_booking_parent_schedule_id;
|
|
1244
|
+
const bookings = sortBookings(normalizeArray(order.bookings).filter(booking => !(0, _pickupTiming.isFulfillmentTimingBooking)(booking) && isReceiptAppointmentBooking(booking, parentScheduleId)));
|
|
1192
1245
|
if (bookings.length) {
|
|
1193
1246
|
const allResources = normalizeArray(order.resources || order.resource_list);
|
|
1194
1247
|
return bookings.flatMap(booking => buildAppointmentRows({
|
|
@@ -1205,6 +1258,19 @@ function buildAppointment(order, locale) {
|
|
|
1205
1258
|
value: getLocalizedValue(tableName, locale)
|
|
1206
1259
|
}];
|
|
1207
1260
|
}
|
|
1261
|
+
function isReceiptAppointmentBooking(booking, parentScheduleId) {
|
|
1262
|
+
if (!booking || typeof booking !== 'object' || Array.isArray(booking)) {
|
|
1263
|
+
return false;
|
|
1264
|
+
}
|
|
1265
|
+
if (isPresentId(parentScheduleId) && isSameId(booking.schedule_event_id, parentScheduleId)) {
|
|
1266
|
+
return false;
|
|
1267
|
+
}
|
|
1268
|
+
const parentId = booking.parent_id;
|
|
1269
|
+
if (parentId === undefined || parentId === null || parentId === '') {
|
|
1270
|
+
return true;
|
|
1271
|
+
}
|
|
1272
|
+
return Number(parentId) !== 0;
|
|
1273
|
+
}
|
|
1208
1274
|
function buildAppointmentRows(params) {
|
|
1209
1275
|
const {
|
|
1210
1276
|
booking,
|
|
@@ -1591,11 +1657,14 @@ function getProductWalletDiscountTime(asset) {
|
|
|
1591
1657
|
}
|
|
1592
1658
|
function getProductEntitlementBalance(asset) {
|
|
1593
1659
|
for (const record of asset.records) {
|
|
1594
|
-
const balance =
|
|
1660
|
+
const balance = getProductDiscountEntitlementBalance(record);
|
|
1595
1661
|
if (balance) return balance;
|
|
1596
1662
|
}
|
|
1597
1663
|
return null;
|
|
1598
1664
|
}
|
|
1665
|
+
function getProductDiscountEntitlementBalance(record) {
|
|
1666
|
+
return getEntitlementBalance(record.metadata?.balance, record.balance, record.discount?.metadata?.balance, record.discount?.balance);
|
|
1667
|
+
}
|
|
1599
1668
|
function getEntitlementBalance(...values) {
|
|
1600
1669
|
for (const value of values) {
|
|
1601
1670
|
if (!isNumericAmount(value)) continue;
|
|
@@ -1668,7 +1737,7 @@ function buildPointCardSnapshotAssets(params) {
|
|
|
1668
1737
|
codes: []
|
|
1669
1738
|
})) return [];
|
|
1670
1739
|
const rows = [{
|
|
1671
|
-
item: stringify(pointCard.product_name).trim() || label(params.locale, 'pointCard'),
|
|
1740
|
+
item: appendMaskedCardCode(stringify(pointCard.product_name).trim() || label(params.locale, 'pointCard'), pointCard.code),
|
|
1672
1741
|
value: ''
|
|
1673
1742
|
}];
|
|
1674
1743
|
const remainingPoints = getPointCardSnapshotRemainingPoints(pointCard);
|
|
@@ -2140,9 +2209,14 @@ function isPointCardPayment(payment) {
|
|
|
2140
2209
|
return code === 'POINTCARD' || type === 'point_card';
|
|
2141
2210
|
}
|
|
2142
2211
|
function maskMachineCode(code) {
|
|
2143
|
-
const text = stringify(code);
|
|
2144
|
-
if (text
|
|
2145
|
-
|
|
2212
|
+
const text = stringify(code).trim();
|
|
2213
|
+
if (!text) return '';
|
|
2214
|
+
if (text.length <= 6) return '*'.repeat(text.length);
|
|
2215
|
+
return `${text.slice(0, 2)}****${text.slice(-4)}`;
|
|
2216
|
+
}
|
|
2217
|
+
function appendMaskedCardCode(name, code) {
|
|
2218
|
+
const maskedCode = maskMachineCode(code);
|
|
2219
|
+
return maskedCode ? `${name}(${maskedCode})` : name;
|
|
2146
2220
|
}
|
|
2147
2221
|
function trimDecimal(value) {
|
|
2148
2222
|
return value.toDecimalPlaces(2).toFixed(2).replace(/\.?0+$/, '');
|
|
@@ -2151,16 +2225,13 @@ function getFundRecordPaymentName(payment, locale) {
|
|
|
2151
2225
|
const fundRecord = getFundRecord(payment);
|
|
2152
2226
|
if (!fundRecord) return '';
|
|
2153
2227
|
const name = getLocalizedValue(fundRecord.wallet_pass_name, locale);
|
|
2154
|
-
|
|
2155
|
-
if (!name && !code) return '';
|
|
2156
|
-
if (!code) return name;
|
|
2228
|
+
if (!name && !maskMachineCode(fundRecord.code)) return '';
|
|
2157
2229
|
const fallbackName = getLocalizedValue(payment.name || payment.title || payment.payment_method_name || payment.method_name || payment.code, locale);
|
|
2158
|
-
return
|
|
2230
|
+
return appendMaskedCardCode(name || fallbackName, fundRecord.code);
|
|
2159
2231
|
}
|
|
2160
2232
|
function appendMachineCodeToName(name, payment) {
|
|
2161
2233
|
const fundRecord = getFundRecord(payment);
|
|
2162
|
-
|
|
2163
|
-
return `${name}(${maskMachineCode(fundRecord.code)})`;
|
|
2234
|
+
return appendMaskedCardCode(name, fundRecord?.code);
|
|
2164
2235
|
}
|
|
2165
2236
|
function paymentMethodName(payment, locale) {
|
|
2166
2237
|
const fundRecordName = getFundRecordPaymentName(payment, locale);
|
|
@@ -2,6 +2,8 @@ import { Module, ModuleOptions, PisellCore } from '../../types';
|
|
|
2
2
|
import { BaseModule } from '../../modules/BaseModule';
|
|
3
3
|
import { BaseSalesOrderProduct, BaseSalesOrderProductIdentity, BaseSalesPaymentStatus, BaseSalesUpdateOrderProductQuantityParams, BaseSalesCalculateProductBookingPriceParams, BaseSalesPriceRecalculationContextChange, BaseSalesProductBookingPriceResult, BaseSalesQuotationCustomerScopeInfo, BaseSalesScanCodeResult, BaseSalesCashPaymentConfig, BaseSalesPayCashParams, BaseSalesPayCashResult, BaseSalesCommitPaymentMethodParams, BaseSalesCommitPaymentMethodResult, BaseSalesConfirmWalletPaymentResult } from './types';
|
|
4
4
|
import { OrderModule } from '../../modules/Order';
|
|
5
|
+
import { type PickupTimingBookingInput } from '../../modules/Order/pickupTiming';
|
|
6
|
+
import type { PickupTimingAvailability, PickupTimingSelection, PickupTimingValidationResult } from '../../modules/FulfillmentTiming';
|
|
5
7
|
import type { AddProductBookingInput, AddProductToOrderOptions, LoadSalesDetailParams, OrderPaymentData, OrderPaymentUpdateOptions, OrderPaymentUpdateResult, OrderPaymentSource, SendCustomerPayLinkParams, SyncPaymentsToOrderParams, SyncPaymentsToOrderResult, UpdateTempOrderCustomerInput, UpdateOrderBookingParams, UpdateOrderProductParams, OrderTempOrder, OrderSummary, OrderPromotionEvaluator, OrderGiftSelectResolver, OrderUnfulfilledPromotion, OrderLastGiftActions, RemoveProductsFromOrderOptions, ReplaceTempOrderOptions, SalesNote, SalesNotesMutationSnapshot, SetSalesNoteInput, PickupReferenceMode, ShopServiceData, ShopServiceType } from '../../modules/Order/types';
|
|
6
8
|
import type { SubmitPayloadEnhancer } from '../../modules/Order/utils';
|
|
7
9
|
import type { Discount, VirtualCurrencyAsset } from '../../modules/Discount/types';
|
|
@@ -75,6 +77,8 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
|
|
|
75
77
|
private serverOrderChangeHydrateInFlight;
|
|
76
78
|
private queuedServerOrderChanges;
|
|
77
79
|
private serverOrderChangeSyncEnabled;
|
|
80
|
+
protected pickupTimingEnabled: boolean;
|
|
81
|
+
private pickupTimingController?;
|
|
78
82
|
constructor(name?: string, version?: string);
|
|
79
83
|
/**
|
|
80
84
|
* 子类可覆盖此方法以追加/收敛要注册的子模块。
|
|
@@ -151,6 +155,22 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
|
|
|
151
155
|
private getAuthoritativeBundleUnitPrice;
|
|
152
156
|
private mergeProductForPriceQuery;
|
|
153
157
|
protected getSubmitOrderSalesChannel(): string | undefined;
|
|
158
|
+
/** Only solutions opting into Pickup Timing supply effective OpenData. */
|
|
159
|
+
protected loadPickupTimingOpenData(_force: boolean): Promise<Record<string, unknown>>;
|
|
160
|
+
protected isPickupTimingEnabled(): boolean;
|
|
161
|
+
protected getPickupTimingContextData(key: string): unknown;
|
|
162
|
+
protected getPickupTimingScope(): string;
|
|
163
|
+
private getPickupTimingController;
|
|
164
|
+
getPickupTimingAvailability(params?: {
|
|
165
|
+
date?: string;
|
|
166
|
+
force?: boolean;
|
|
167
|
+
}): Promise<PickupTimingAvailability>;
|
|
168
|
+
getPickupTimingSelection(): PickupTimingSelection;
|
|
169
|
+
setPickupTimingSelection(selection: PickupTimingSelection): Promise<PickupTimingSelection>;
|
|
170
|
+
validatePickupTimingSelection(selection: PickupTimingSelection): Promise<PickupTimingValidationResult>;
|
|
171
|
+
preparePickupTimingForCheckout(options?: {
|
|
172
|
+
freeze?: boolean;
|
|
173
|
+
}): Promise<PickupTimingSelection>;
|
|
154
174
|
/** Subclasses with target-scoped OpenData override this guard before reusing the cache. */
|
|
155
175
|
protected isInvoiceOpenDataCacheCurrent(): boolean;
|
|
156
176
|
private getFulfillmentRefModeConfigs;
|
|
@@ -248,6 +268,9 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
|
|
|
248
268
|
updateTempOrderDepositAmount(amount: string | number): OrderSummary;
|
|
249
269
|
setPickupReferenceMode(mode: PickupReferenceMode): ShopServiceData;
|
|
250
270
|
setServiceType(serviceType: ShopServiceType): ShopServiceData;
|
|
271
|
+
getPickupTimingBooking(): import("../../modules/Order").PickupTimingBooking | null;
|
|
272
|
+
setPickupTimingBooking(input: PickupTimingBookingInput): import("../../modules/Order").PickupTimingBooking;
|
|
273
|
+
clearPickupTimingBooking(): void;
|
|
251
274
|
updateTempOrderContactsInfo(contactsInfo: Record<string, any> | null): Record<string, any> | null;
|
|
252
275
|
/** @deprecated OrderModule 不再负责 tempOrder localStorage 持久化。 */
|
|
253
276
|
setEnableTempOrderPersist(enabled: boolean): void;
|
|
@@ -21,6 +21,8 @@ Object.keys(_types).forEach(function (key) {
|
|
|
21
21
|
});
|
|
22
22
|
});
|
|
23
23
|
var _Order = require("../../modules/Order");
|
|
24
|
+
var _pickupTiming = require("../../modules/Order/pickupTiming");
|
|
25
|
+
var _pickupTiming2 = require("./pickupTiming");
|
|
24
26
|
var _decimal = _interopRequireDefault(require("decimal.js"));
|
|
25
27
|
var _lodashEs = require("lodash-es");
|
|
26
28
|
var _types2 = require("../BookingByStep/types");
|
|
@@ -497,6 +499,8 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
497
499
|
serverOrderChangeHydrateInFlight = null;
|
|
498
500
|
queuedServerOrderChanges = [];
|
|
499
501
|
serverOrderChangeSyncEnabled = false;
|
|
502
|
+
pickupTimingEnabled = false;
|
|
503
|
+
pickupTimingController;
|
|
500
504
|
constructor(name, version) {
|
|
501
505
|
super(name, version);
|
|
502
506
|
}
|
|
@@ -1146,6 +1150,66 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1146
1150
|
return this.otherParams?.channel;
|
|
1147
1151
|
}
|
|
1148
1152
|
|
|
1153
|
+
/** Only solutions opting into Pickup Timing supply effective OpenData. */
|
|
1154
|
+
async loadPickupTimingOpenData(_force) {
|
|
1155
|
+
return {};
|
|
1156
|
+
}
|
|
1157
|
+
isPickupTimingEnabled() {
|
|
1158
|
+
return this.pickupTimingEnabled && this.otherParams?.enablePickupTiming !== false;
|
|
1159
|
+
}
|
|
1160
|
+
getPickupTimingContextData(key) {
|
|
1161
|
+
const context = this.core?.context;
|
|
1162
|
+
const getData = context?.getData;
|
|
1163
|
+
return typeof getData === 'function' ? getData.call(context, key) : undefined;
|
|
1164
|
+
}
|
|
1165
|
+
getPickupTimingScope() {
|
|
1166
|
+
return JSON.stringify({
|
|
1167
|
+
shop: this.getPickupTimingContextData('shop_id'),
|
|
1168
|
+
businessCode: this.otherParams?.businessCode ?? this.otherParams?.business_code,
|
|
1169
|
+
channel: this.getSubmitOrderSalesChannel(),
|
|
1170
|
+
timezone: this.getPickupTimingContextData('timezone'),
|
|
1171
|
+
platform: (0, _platform.normalizeRuntimePlatform)(this.otherParams?.platform),
|
|
1172
|
+
cacheId: this.cacheId
|
|
1173
|
+
});
|
|
1174
|
+
}
|
|
1175
|
+
getPickupTimingController() {
|
|
1176
|
+
if (!this.pickupTimingController) {
|
|
1177
|
+
this.pickupTimingController = new _pickupTiming2.PickupTimingController({
|
|
1178
|
+
getOrder: () => {
|
|
1179
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1180
|
+
return this.store.order;
|
|
1181
|
+
},
|
|
1182
|
+
getSchedule: () => this.store.schedule,
|
|
1183
|
+
loadOpenData: force => this.loadPickupTimingOpenData(force),
|
|
1184
|
+
getTimezone: () => String(this.getPickupTimingContextData('timezone') ?? ''),
|
|
1185
|
+
getScope: () => this.getPickupTimingScope(),
|
|
1186
|
+
isPos: () => (0, _platform.normalizeRuntimePlatform)(this.otherParams?.platform) === 'pos'
|
|
1187
|
+
});
|
|
1188
|
+
}
|
|
1189
|
+
return this.pickupTimingController;
|
|
1190
|
+
}
|
|
1191
|
+
getPickupTimingAvailability(params) {
|
|
1192
|
+
return this.getPickupTimingController().getAvailability(params);
|
|
1193
|
+
}
|
|
1194
|
+
getPickupTimingSelection() {
|
|
1195
|
+
return this.getPickupTimingController().getSelection();
|
|
1196
|
+
}
|
|
1197
|
+
setPickupTimingSelection(selection) {
|
|
1198
|
+
return this.getPickupTimingController().setSelection(selection);
|
|
1199
|
+
}
|
|
1200
|
+
validatePickupTimingSelection(selection) {
|
|
1201
|
+
return this.getPickupTimingController().validate(selection);
|
|
1202
|
+
}
|
|
1203
|
+
preparePickupTimingForCheckout(options) {
|
|
1204
|
+
if (!this.isPickupTimingEnabled()) {
|
|
1205
|
+
return Promise.resolve({
|
|
1206
|
+
serviceType: String(this.getTempOrder()?.metadata?.shop_service_data?.service_type || ''),
|
|
1207
|
+
mode: 'asap'
|
|
1208
|
+
});
|
|
1209
|
+
}
|
|
1210
|
+
return this.getPickupTimingController().prepare(options);
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1149
1213
|
/** Subclasses with target-scoped OpenData override this guard before reusing the cache. */
|
|
1150
1214
|
isInvoiceOpenDataCacheCurrent() {
|
|
1151
1215
|
return true;
|
|
@@ -1537,9 +1601,12 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1537
1601
|
/** 获取根 booking(is_next === 0 / is_root === 1),多个时取第一个。 */
|
|
1538
1602
|
getRootBooking() {
|
|
1539
1603
|
if (!this.currentSalesDetail) return null;
|
|
1540
|
-
if (this.currentSalesDetail.rootBooking
|
|
1604
|
+
if (this.currentSalesDetail.rootBooking && !(0, _pickupTiming.isFulfillmentTimingBooking)(this.currentSalesDetail.rootBooking)) {
|
|
1605
|
+
return this.currentSalesDetail.rootBooking;
|
|
1606
|
+
}
|
|
1541
1607
|
const bookings = this.currentSalesDetail.bookings || [];
|
|
1542
1608
|
return bookings.find(booking => {
|
|
1609
|
+
if ((0, _pickupTiming.isFulfillmentTimingBooking)(booking)) return false;
|
|
1543
1610
|
const parentId = booking?.parent_id;
|
|
1544
1611
|
return parentId === 0 || parentId === null || parentId === undefined;
|
|
1545
1612
|
}) || null;
|
|
@@ -1656,6 +1723,16 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1656
1723
|
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1657
1724
|
return this.store.order.updateTempOrderServiceType(serviceType);
|
|
1658
1725
|
}
|
|
1726
|
+
getPickupTimingBooking() {
|
|
1727
|
+
return this.store.order?.getPickupTimingBooking() || null;
|
|
1728
|
+
}
|
|
1729
|
+
setPickupTimingBooking(input) {
|
|
1730
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1731
|
+
return this.store.order.setPickupTimingBooking(input);
|
|
1732
|
+
}
|
|
1733
|
+
clearPickupTimingBooking() {
|
|
1734
|
+
this.store.order?.clearPickupTimingBooking();
|
|
1735
|
+
}
|
|
1659
1736
|
updateTempOrderContactsInfo(contactsInfo) {
|
|
1660
1737
|
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1661
1738
|
return this.store.order.updateTempOrderContactsInfo(contactsInfo);
|
|
@@ -2111,6 +2188,8 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2111
2188
|
holders: [],
|
|
2112
2189
|
isFormSubject: product => (0, _utils.resolveIsFormSubject)(tempOrder, product),
|
|
2113
2190
|
orderTotalAmount
|
|
2191
|
+
}, {
|
|
2192
|
+
preserveEntitlementSelection: false
|
|
2114
2193
|
}) || result;
|
|
2115
2194
|
if (result.productList) {
|
|
2116
2195
|
tempOrder.products = preserveManualProductDiscountProducts(tempOrder.products, result.productList);
|
|
@@ -2454,6 +2533,9 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2454
2533
|
if (!this.store.order) {
|
|
2455
2534
|
throw new Error('BaseSales 解决方案需要 order 模块支持');
|
|
2456
2535
|
}
|
|
2536
|
+
if (this.isPickupTimingEnabled()) await this.preparePickupTimingForCheckout({
|
|
2537
|
+
freeze: true
|
|
2538
|
+
});
|
|
2457
2539
|
const virtualSettlement = await this.buildVirtualSettlementSubmitData();
|
|
2458
2540
|
// this.store.order.persistTempOrder();
|
|
2459
2541
|
const inferredPaymentStatus = this.getSubmitPaymentStatus(params?.paymentStatus);
|
|
@@ -2511,6 +2593,9 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2511
2593
|
if (!this.store.order) {
|
|
2512
2594
|
throw new Error('BaseSales 解决方案需要 order 模块支持');
|
|
2513
2595
|
}
|
|
2596
|
+
if (this.isPickupTimingEnabled()) await this.preparePickupTimingForCheckout({
|
|
2597
|
+
freeze: false
|
|
2598
|
+
});
|
|
2514
2599
|
return this.store.order.saveTempOrderAsDraft({
|
|
2515
2600
|
cacheId: this.cacheId,
|
|
2516
2601
|
platform: params?.platform ?? this.otherParams?.platform,
|
|
@@ -2526,6 +2611,11 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2526
2611
|
if (!this.store.order) {
|
|
2527
2612
|
throw new Error('BaseSales 解决方案需要 order 模块支持');
|
|
2528
2613
|
}
|
|
2614
|
+
if (this.isPickupTimingEnabled()) {
|
|
2615
|
+
await this.preparePickupTimingForCheckout({
|
|
2616
|
+
freeze: true
|
|
2617
|
+
});
|
|
2618
|
+
}
|
|
2529
2619
|
const inferredPaymentStatus = this.getSubmitPaymentStatus(params?.paymentStatus);
|
|
2530
2620
|
const smallTicketDataFlag = params?.smallTicketDataFlag ?? this.getDefaultCheckoutSmallTicketDataFlag();
|
|
2531
2621
|
const enhancePayload = this.buildSubmitPayloadEnhancerWithOpenDataConfig(params?.enhancePayload);
|
|
@@ -3025,6 +3115,10 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
3025
3115
|
};
|
|
3026
3116
|
}
|
|
3027
3117
|
const result = await this.store.payment.wallet.initializeWalletDataFromBusinessAsync(walletBusinessData);
|
|
3118
|
+
this.store.order.mergePointCardSnapshotCodes?.(result.userIdentificationCodes, {
|
|
3119
|
+
customerId: walletBusinessData.customer_id,
|
|
3120
|
+
orderIdentity: snapshot?.identity
|
|
3121
|
+
});
|
|
3028
3122
|
await this.core.effects.emit(`${this.name}:onWalletDataInitialized`, {
|
|
3029
3123
|
orderId: snapshot?.identity?.orderId,
|
|
3030
3124
|
customerId: walletBusinessData.customer_id,
|
|
@@ -3151,6 +3245,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
3151
3245
|
async importWalletAssetsSnapshot(snapshot) {
|
|
3152
3246
|
if (!this.store.payment) throw new Error('payment 模块未初始化');
|
|
3153
3247
|
const state = this.store.payment.wallet.importWalletAssetsSnapshot(snapshot);
|
|
3248
|
+
this.store.order?.mergePointCardSnapshotCodes?.(state.items);
|
|
3154
3249
|
await this.syncSelectedWalletAssets(state);
|
|
3155
3250
|
return this.publishWalletAssetsState(state);
|
|
3156
3251
|
}
|
|
@@ -3172,6 +3267,10 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
3172
3267
|
});
|
|
3173
3268
|
return this.publishWalletAssetsState(emptyState);
|
|
3174
3269
|
}
|
|
3270
|
+
const pointCardSnapshotMergeContext = {
|
|
3271
|
+
customerId: businessData.customer_id,
|
|
3272
|
+
orderIdentity: this.store.order.getOrderSnapshot()?.identity
|
|
3273
|
+
};
|
|
3175
3274
|
const previousState = wallet.getWalletAssetsState();
|
|
3176
3275
|
const hasPreviousWalletContext = previousState.status !== 'idle' || previousState.items.length > 0 || previousState.selectedIds.length > 0 || previousState.customerId !== undefined;
|
|
3177
3276
|
const customerChanged = hasPreviousWalletContext && String(previousState.customerId ?? '') !== String(businessData.customer_id ?? '');
|
|
@@ -3194,6 +3293,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
3194
3293
|
if (state.status !== 'error') {
|
|
3195
3294
|
const committed = this.getCommittedWalletAssets();
|
|
3196
3295
|
state = wallet.setCommittedWalletAssets(committed.ids, committed.assets);
|
|
3296
|
+
this.store.order.mergePointCardSnapshotCodes?.(wallet.getUserIdentificationCodes?.() || [], pointCardSnapshotMergeContext);
|
|
3197
3297
|
}
|
|
3198
3298
|
await this.syncSelectedWalletAssets(state);
|
|
3199
3299
|
return this.publishWalletAssetsState(state);
|
|
@@ -3434,6 +3534,9 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
3434
3534
|
if (!Number.isFinite(actualPaidAmount) || actualPaidAmount + 0.01 < amount) {
|
|
3435
3535
|
throw new Error('顾客实收现金不能小于支付金额');
|
|
3436
3536
|
}
|
|
3537
|
+
if (this.isPickupTimingEnabled()) await this.preparePickupTimingForCheckout({
|
|
3538
|
+
freeze: true
|
|
3539
|
+
});
|
|
3437
3540
|
this.window?.interaction?.utils?.postMessageToApp?.({
|
|
3438
3541
|
module: 'till',
|
|
3439
3542
|
key: 'open_till',
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { OrderModule } from '../../modules/Order';
|
|
2
|
+
import type { ScheduleModule } from '../../modules/Schedule';
|
|
3
|
+
import { type PickupTimingAvailability, type PickupTimingSelection, type PickupTimingValidationResult } from '../../modules/FulfillmentTiming';
|
|
4
|
+
interface PickupTimingHost {
|
|
5
|
+
getOrder: () => OrderModule;
|
|
6
|
+
getSchedule: () => ScheduleModule | undefined;
|
|
7
|
+
loadOpenData: (force: boolean) => Promise<Record<string, unknown>>;
|
|
8
|
+
getTimezone: () => string;
|
|
9
|
+
getScope: () => string;
|
|
10
|
+
isPos: () => boolean;
|
|
11
|
+
now?: () => Date;
|
|
12
|
+
}
|
|
13
|
+
/** Coordinates fresh configuration with the independent appointment; UI keeps edit drafts. */
|
|
14
|
+
export declare class PickupTimingController {
|
|
15
|
+
private readonly host;
|
|
16
|
+
private latest?;
|
|
17
|
+
private readonly requests;
|
|
18
|
+
private writeSequence;
|
|
19
|
+
constructor(host: PickupTimingHost);
|
|
20
|
+
private now;
|
|
21
|
+
private snapshot;
|
|
22
|
+
getAvailability(params?: {
|
|
23
|
+
date?: string;
|
|
24
|
+
force?: boolean;
|
|
25
|
+
}): Promise<PickupTimingAvailability>;
|
|
26
|
+
getSelection(): PickupTimingSelection;
|
|
27
|
+
private validateSnapshot;
|
|
28
|
+
validate(selection: PickupTimingSelection): Promise<PickupTimingValidationResult>;
|
|
29
|
+
setSelection(selection: PickupTimingSelection, options?: {
|
|
30
|
+
frozen?: boolean;
|
|
31
|
+
}): Promise<PickupTimingSelection>;
|
|
32
|
+
/** Called before a new checkout/payment; payment callbacks keep their already prepared appointment. */
|
|
33
|
+
prepare(options?: {
|
|
34
|
+
freeze?: boolean;
|
|
35
|
+
}): Promise<PickupTimingSelection>;
|
|
36
|
+
}
|
|
37
|
+
export {};
|