@pisell/pisellos 2.1.129 → 2.1.130
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/Order/index.d.ts +4 -0
- package/dist/modules/Order/index.js +18 -1
- package/dist/modules/Order/types.d.ts +9 -1
- package/dist/modules/Order/utils.d.ts +7 -0
- package/dist/modules/Order/utils.js +27 -11
- package/dist/solution/ScanOrder/index.d.ts +27 -3
- package/dist/solution/ScanOrder/index.js +865 -481
- package/dist/solution/ScanOrder/types.d.ts +34 -24
- package/dist/solution/ScanOrder/types.js +5 -1
- package/dist/solution/ScanOrder/utils.d.ts +13 -1
- package/dist/solution/ScanOrder/utils.js +45 -6
- package/dist/solution/VenueBooking/index.d.ts +28 -5
- package/dist/solution/VenueBooking/index.js +428 -193
- package/dist/solution/VenueBooking/types.d.ts +23 -0
- package/dist/solution/VenueBooking/utils/dateSummary.d.ts +1 -1
- package/dist/solution/VenueBooking/utils/dateSummary.js +1 -1
- package/dist/solution/VenueBooking/utils/resource.d.ts +11 -1
- package/dist/solution/VenueBooking/utils/resource.js +57 -21
- package/dist/solution/VenueBooking/utils/slotMerge.d.ts +5 -0
- package/dist/solution/VenueBooking/utils/slotMerge.js +33 -12
- package/dist/solution/VenueBooking/utils/timeSlot.d.ts +1 -1
- package/dist/solution/VenueBooking/utils/timeSlot.js +259 -62
- package/lib/modules/Order/index.d.ts +4 -0
- package/lib/modules/Order/index.js +14 -1
- package/lib/modules/Order/types.d.ts +9 -1
- package/lib/modules/Order/utils.d.ts +7 -0
- package/lib/modules/Order/utils.js +22 -12
- package/lib/solution/ScanOrder/index.d.ts +27 -3
- package/lib/solution/ScanOrder/index.js +409 -114
- package/lib/solution/ScanOrder/types.d.ts +34 -24
- package/lib/solution/ScanOrder/utils.d.ts +13 -1
- package/lib/solution/ScanOrder/utils.js +37 -0
- package/lib/solution/VenueBooking/index.d.ts +28 -5
- package/lib/solution/VenueBooking/index.js +193 -45
- package/lib/solution/VenueBooking/types.d.ts +23 -0
- package/lib/solution/VenueBooking/utils/dateSummary.d.ts +1 -1
- package/lib/solution/VenueBooking/utils/dateSummary.js +1 -1
- package/lib/solution/VenueBooking/utils/resource.d.ts +11 -1
- package/lib/solution/VenueBooking/utils/resource.js +15 -4
- package/lib/solution/VenueBooking/utils/slotMerge.d.ts +5 -0
- package/lib/solution/VenueBooking/utils/slotMerge.js +29 -12
- package/lib/solution/VenueBooking/utils/timeSlot.d.ts +1 -1
- package/lib/solution/VenueBooking/utils/timeSlot.js +182 -43
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { OrderModule, ProductList, SalesSummaryModule, ScanOrderLogInput, ScanOrderLoggerModule, ScanOrderLoggerProviderConfig, ScanOrderLoggerProviderType } from '../../modules';
|
|
1
|
+
import { OrderModule, ProductList, SalesSummaryModule, ScanOrderLogInput, ScanOrderLoggerModule, ScanOrderLoggerProviderConfig, ScanOrderLoggerProviderType, ScheduleModule } from '../../modules';
|
|
2
2
|
import type { QuantityCheckResult, QuantityLimitResult } from '../../model/strategy/adapter/itemRule';
|
|
3
3
|
/**
|
|
4
4
|
* 扫码下单流程 hook
|
|
@@ -114,6 +114,9 @@ export interface ScanOrderTempOrder {
|
|
|
114
114
|
shop_discount: string;
|
|
115
115
|
surcharge_fee: string;
|
|
116
116
|
note: string;
|
|
117
|
+
buzzer?: string;
|
|
118
|
+
delivery_type?: string;
|
|
119
|
+
table_number?: Record<string, any>;
|
|
117
120
|
schedule_date: string;
|
|
118
121
|
created_at: string;
|
|
119
122
|
products: ScanOrderOrderProduct[];
|
|
@@ -134,14 +137,15 @@ export interface ScanOrderSubmitPayload extends Omit<ScanOrderTempOrder, 'platfo
|
|
|
134
137
|
request_unique_idempotency_token?: string;
|
|
135
138
|
form_record_ids?: Array<{
|
|
136
139
|
form_id: number | string;
|
|
137
|
-
|
|
140
|
+
form_record_id: number | string;
|
|
138
141
|
}>;
|
|
139
142
|
products: ScanOrderSubmitProduct[];
|
|
140
143
|
}
|
|
141
|
-
export type ScanOrderAvailabilityMode = 'idle' | 'shop_closed' | '
|
|
144
|
+
export type ScanOrderAvailabilityMode = 'idle' | 'shop_closed' | 'submit_disabled' | 'resource_busy' | 'additional_order_with_code' | 'additional_order';
|
|
142
145
|
export interface ScanOrderTableFormRecord {
|
|
143
146
|
policy?: string | null;
|
|
144
147
|
partyroom_booking?: string | null;
|
|
148
|
+
capacity?: number | string | null;
|
|
145
149
|
[key: string]: any;
|
|
146
150
|
}
|
|
147
151
|
export interface ScanOrderAvailabilityInfo {
|
|
@@ -151,7 +155,9 @@ export interface ScanOrderAvailabilityInfo {
|
|
|
151
155
|
table_form_id?: string;
|
|
152
156
|
deskmate_valid?: boolean;
|
|
153
157
|
errorTips?: string;
|
|
154
|
-
/**
|
|
158
|
+
/** 透传 `availability.closed_behavior`,便于 UI 识别拦截类型(如 show_menu_disabled) */
|
|
159
|
+
closed_behavior?: string;
|
|
160
|
+
/** `/order/resource/occupy-detail` 返回的 `form_record` 原样透出 */
|
|
155
161
|
table_form_record?: ScanOrderTableFormRecord | null;
|
|
156
162
|
policy?: string | null;
|
|
157
163
|
partyroom_booking?: string | null;
|
|
@@ -162,34 +168,36 @@ export interface ScanOrderAvailabilityInfo {
|
|
|
162
168
|
/** 首个 `capacity.type === 'custom'` 商品里 `custom[0]` 的 max(人数上限) */
|
|
163
169
|
requestPaxMax?: number;
|
|
164
170
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
171
|
+
/** `resource_capacity[i].capacity_list[j]` */
|
|
172
|
+
export interface ScanOrderResourceCapacitySlot {
|
|
173
|
+
start_at?: string;
|
|
174
|
+
end_at?: string;
|
|
175
|
+
pax?: number | string;
|
|
168
176
|
}
|
|
169
|
-
export interface
|
|
170
|
-
|
|
171
|
-
|
|
177
|
+
export interface ScanOrderResourceCapacity {
|
|
178
|
+
capacity?: number | string;
|
|
179
|
+
capacity_list?: ScanOrderResourceCapacitySlot[];
|
|
172
180
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
181
|
+
/** `/order/resource/occupy-detail` 单条 `occupy_details[i]` */
|
|
182
|
+
export interface ScanOrderResourceOccupyDetail {
|
|
183
|
+
form_record_id?: number | string | null;
|
|
184
|
+
form_id?: number | string | null;
|
|
176
185
|
order_id?: number | string | null;
|
|
177
186
|
last_order_id?: number | string | null;
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
table_snack?: ScanOrderTableSnackConfig[] | null;
|
|
181
|
-
order_number_prefix?: ScanOrderOrderNumberPrefixConfig[] | null;
|
|
187
|
+
resource_capacity?: ScanOrderResourceCapacity[] | null;
|
|
188
|
+
form_record?: ScanOrderTableFormRecord | null;
|
|
182
189
|
[key: string]: any;
|
|
183
190
|
}
|
|
184
|
-
export interface
|
|
191
|
+
export interface ScanOrderResourceOccupyDetailApiResponse {
|
|
185
192
|
status?: boolean;
|
|
186
193
|
code?: number;
|
|
187
194
|
message?: string;
|
|
188
|
-
data?:
|
|
195
|
+
data?: {
|
|
196
|
+
occupy_details?: ScanOrderResourceOccupyDetail[] | null;
|
|
197
|
+
} | null;
|
|
189
198
|
}
|
|
199
|
+
export type ScanOrderResourceSelectType = 'single' | 'multiple' | 'capacity';
|
|
190
200
|
export interface ScanOrderResourceState extends ScanOrderAvailabilityInfo {
|
|
191
|
-
tableMaxNumber: number;
|
|
192
|
-
orderCount: number;
|
|
193
201
|
relationId?: string;
|
|
194
202
|
tableFormId?: string;
|
|
195
203
|
currentOrderId?: string;
|
|
@@ -198,13 +206,14 @@ export interface ScanOrderResourceState extends ScanOrderAvailabilityInfo {
|
|
|
198
206
|
deskmateValid: boolean;
|
|
199
207
|
isExclusive: boolean;
|
|
200
208
|
isFull: boolean;
|
|
201
|
-
|
|
202
|
-
|
|
209
|
+
/** 来自首个预约规则商品 product_resource.resources 中与 form_id 匹配的 resource type */
|
|
210
|
+
resourceSelectType?: ScanOrderResourceSelectType;
|
|
211
|
+
raw: ScanOrderResourceOccupyDetail | null;
|
|
203
212
|
}
|
|
204
213
|
export interface ScanOrderState {
|
|
205
214
|
entryContext: ScanOrderEntryContext | null;
|
|
206
215
|
status: ScanOrderStatus;
|
|
207
|
-
config:
|
|
216
|
+
config: Record<string, any> | null;
|
|
208
217
|
resource: ScanOrderResourceState | null;
|
|
209
218
|
flow: Record<string, any>;
|
|
210
219
|
error: string | null;
|
|
@@ -212,6 +221,7 @@ export interface ScanOrderState {
|
|
|
212
221
|
order?: OrderModule;
|
|
213
222
|
salesSummary?: SalesSummaryModule;
|
|
214
223
|
scanOrderLogger?: ScanOrderLoggerModule;
|
|
224
|
+
schedule?: ScheduleModule;
|
|
215
225
|
itemRuleQuantityLimits: QuantityLimitResult[];
|
|
216
226
|
cartValidation: {
|
|
217
227
|
passed: boolean | null;
|
|
@@ -13,4 +13,8 @@ export var ScanOrderHooks = /*#__PURE__*/function (ScanOrderHooks) {
|
|
|
13
13
|
/**
|
|
14
14
|
* ScanOrder 临时订单(runtime-clean 版本)
|
|
15
15
|
* 只保留运行时字段,不包含任何 __comment 字段
|
|
16
|
-
*/
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/** `resource_capacity[i].capacity_list[j]` */
|
|
19
|
+
|
|
20
|
+
/** `/order/resource/occupy-detail` 单条 `occupy_details[i]` */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ScanOrderOrderProduct, ScanOrderOrderProductIdentity, ScanOrderSummary, ScanOrderTempOrder } from './types';
|
|
1
|
+
import { ScanOrderOrderProduct, ScanOrderOrderProductIdentity, ScanOrderResourceCapacitySlot, ScanOrderResourceSelectType, ScanOrderSummary, ScanOrderTempOrder } from './types';
|
|
2
2
|
import type { CartItemSummary, ItemRuleBusinessData, PaxInfo, QuantityLimitResult } from '../../model/strategy/adapter/itemRule';
|
|
3
3
|
import type { StrategyConfig } from '../../model/strategy/type';
|
|
4
4
|
import type { ProductData } from '../../modules/Product/types';
|
|
@@ -109,6 +109,18 @@ export declare function collectLinkProductIdsFromReservationRules(rules: unknown
|
|
|
109
109
|
export declare function pickFirstDurationMinutesFromProducts(products: ProductData[]): number | undefined;
|
|
110
110
|
/** 是否存在 capacity.type === 'custom' 的商品 */
|
|
111
111
|
export declare function hasCustomCapacityProduct(products: ProductData[]): boolean;
|
|
112
|
+
/**
|
|
113
|
+
* 根据预约规则商品的 resource.type 计算桌台是否已被"占满"。
|
|
114
|
+
* - single:只要有 `lastOrderId` 即视为占用
|
|
115
|
+
* - multiple:当前时间落在 `capacity_list[i]` 的 `[start_at, end_at]`(inclusive)内的 pax 之和 > 总容量
|
|
116
|
+
* - 其他('capacity' / undefined):返回 false,不施加限制
|
|
117
|
+
*/
|
|
118
|
+
export declare function computeResourceIsFull(params: {
|
|
119
|
+
resourceSelectType?: ScanOrderResourceSelectType;
|
|
120
|
+
lastOrderId?: string;
|
|
121
|
+
capacityList?: ScanOrderResourceCapacitySlot[];
|
|
122
|
+
capacity?: number | string | null;
|
|
123
|
+
}): boolean;
|
|
112
124
|
/**
|
|
113
125
|
* 在商品列表中找到第一个 `capacity.type === 'custom'` 的商品,取其 `custom` 数组第一项的 min/max。
|
|
114
126
|
* 仅返回有限数字字段;若均无法解析则返回 `undefined`。
|
|
@@ -11,6 +11,7 @@ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" ==
|
|
|
11
11
|
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
12
12
|
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
13
13
|
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
14
|
+
import dayjs from 'dayjs';
|
|
14
15
|
/**
|
|
15
16
|
* 构建金额全为 0 的空 summary。
|
|
16
17
|
* 作为尚未计算金额时的兜底默认值,避免下游因 undefined 报错。
|
|
@@ -508,16 +509,54 @@ export function hasCustomCapacityProduct(products) {
|
|
|
508
509
|
});
|
|
509
510
|
}
|
|
510
511
|
|
|
512
|
+
/**
|
|
513
|
+
* 根据预约规则商品的 resource.type 计算桌台是否已被"占满"。
|
|
514
|
+
* - single:只要有 `lastOrderId` 即视为占用
|
|
515
|
+
* - multiple:当前时间落在 `capacity_list[i]` 的 `[start_at, end_at]`(inclusive)内的 pax 之和 > 总容量
|
|
516
|
+
* - 其他('capacity' / undefined):返回 false,不施加限制
|
|
517
|
+
*/
|
|
518
|
+
export function computeResourceIsFull(params) {
|
|
519
|
+
var resourceSelectType = params.resourceSelectType,
|
|
520
|
+
lastOrderId = params.lastOrderId,
|
|
521
|
+
capacityList = params.capacityList,
|
|
522
|
+
capacity = params.capacity;
|
|
523
|
+
if (resourceSelectType === 'single') return Boolean(lastOrderId);
|
|
524
|
+
if (resourceSelectType !== 'multiple') return false;
|
|
525
|
+
var totalCapacity = Number(capacity);
|
|
526
|
+
if (!Number.isFinite(totalCapacity) || totalCapacity <= 0) return false;
|
|
527
|
+
var now = dayjs();
|
|
528
|
+
var occupied = 0;
|
|
529
|
+
var _iterator8 = _createForOfIteratorHelper(capacityList || []),
|
|
530
|
+
_step8;
|
|
531
|
+
try {
|
|
532
|
+
for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
|
|
533
|
+
var slot = _step8.value;
|
|
534
|
+
var start = dayjs(slot === null || slot === void 0 ? void 0 : slot.start_at);
|
|
535
|
+
var end = dayjs(slot === null || slot === void 0 ? void 0 : slot.end_at);
|
|
536
|
+
if (!start.isValid() || !end.isValid()) continue;
|
|
537
|
+
if ((now.isAfter(start) || now.isSame(start)) && (now.isBefore(end) || now.isSame(end))) {
|
|
538
|
+
var pax = Number(slot === null || slot === void 0 ? void 0 : slot.pax);
|
|
539
|
+
if (Number.isFinite(pax) && pax > 0) occupied += pax;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
} catch (err) {
|
|
543
|
+
_iterator8.e(err);
|
|
544
|
+
} finally {
|
|
545
|
+
_iterator8.f();
|
|
546
|
+
}
|
|
547
|
+
return occupied > totalCapacity;
|
|
548
|
+
}
|
|
549
|
+
|
|
511
550
|
/**
|
|
512
551
|
* 在商品列表中找到第一个 `capacity.type === 'custom'` 的商品,取其 `custom` 数组第一项的 min/max。
|
|
513
552
|
* 仅返回有限数字字段;若均无法解析则返回 `undefined`。
|
|
514
553
|
*/
|
|
515
554
|
export function pickFirstCustomCapacityPaxBounds(products) {
|
|
516
|
-
var
|
|
517
|
-
|
|
555
|
+
var _iterator9 = _createForOfIteratorHelper(products),
|
|
556
|
+
_step9;
|
|
518
557
|
try {
|
|
519
|
-
for (
|
|
520
|
-
var p =
|
|
558
|
+
for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
|
|
559
|
+
var p = _step9.value;
|
|
521
560
|
var cap = p === null || p === void 0 ? void 0 : p.capacity;
|
|
522
561
|
if (!cap || cap.type !== 'custom') continue;
|
|
523
562
|
if (!Array.isArray(cap.custom) || cap.custom.length === 0) continue;
|
|
@@ -536,9 +575,9 @@ export function pickFirstCustomCapacityPaxBounds(products) {
|
|
|
536
575
|
if (out.min !== undefined || out.max !== undefined) return out;
|
|
537
576
|
}
|
|
538
577
|
} catch (err) {
|
|
539
|
-
|
|
578
|
+
_iterator9.e(err);
|
|
540
579
|
} finally {
|
|
541
|
-
|
|
580
|
+
_iterator9.f();
|
|
542
581
|
}
|
|
543
582
|
return undefined;
|
|
544
583
|
}
|
|
@@ -92,25 +92,48 @@ export declare class VenueBookingImpl extends BaseModule implements Module {
|
|
|
92
92
|
/**
|
|
93
93
|
* 切换单个时段的选中状态(选中/取消)。
|
|
94
94
|
* 内部自动处理连续时段的合并与拆分,订单是唯一真相源。
|
|
95
|
+
*
|
|
96
|
+
* slot.productId 指定当前操作针对的是该 resourceId 下的哪一个商品。
|
|
97
|
+
* 同一资源下不同 productId 之间互相隔离,不会相互合并。
|
|
95
98
|
*/
|
|
96
99
|
toggleSlot(slot: VenueSlotSelection): Promise<ScanOrderOrderProduct[]>;
|
|
97
100
|
/**
|
|
98
101
|
* 获取某资源当前选中的所有独立时段(从订单中解析)。
|
|
102
|
+
* 不传 productId 时返回该资源下所有商品的选中时段;传了则精确匹配。
|
|
99
103
|
*/
|
|
100
|
-
getSelectedSlotsForResource(resourceId: number | string): VenueSlotSelection[];
|
|
104
|
+
getSelectedSlotsForResource(resourceId: number | string, productId?: number): VenueSlotSelection[];
|
|
105
|
+
/** getSelectedSlotsForResource 的 (resourceId, productId) 精确版,内部使用。 */
|
|
106
|
+
private getSelectedSlotsForResourceProduct;
|
|
101
107
|
/**
|
|
102
108
|
* 判断某个时段是否已选中。
|
|
109
|
+
* 不传 productId 时:只要该资源下任一商品在 startTime 被选中即返回 true;传了则精确匹配。
|
|
103
110
|
*/
|
|
104
|
-
isSlotSelected(resourceId: number | string, startTime: string): boolean;
|
|
111
|
+
isSlotSelected(resourceId: number | string, startTime: string, productId?: number): boolean;
|
|
105
112
|
/**
|
|
106
|
-
*
|
|
113
|
+
* 判断指定 (resourceId, productId, startTime) 格子是否应因其它已选项而被禁用。
|
|
114
|
+
* 规则:
|
|
115
|
+
* 1) 同一 resourceId 下若已选了另一个 productId 的同 startTime → 禁用
|
|
116
|
+
* 2) 当前 resource 是组合资源:若其任一 child resource 在 startTime 被选中 → 禁用
|
|
117
|
+
* 3) 当前 resource 是某些组合资源的 child:若该组合资源在 startTime 被选中 → 禁用
|
|
118
|
+
* 4) 两个组合资源的 child 集合有交集,且对方在该 startTime 被选中 → 禁用
|
|
119
|
+
*/
|
|
120
|
+
isSlotDisabledBySelection(params: {
|
|
121
|
+
resourceId: number | string;
|
|
122
|
+
productId: number;
|
|
123
|
+
startTime: string;
|
|
124
|
+
}): boolean;
|
|
125
|
+
/**
|
|
126
|
+
* 获取所有已选时段(按资源分组)。每个 slot 上带 productId,便于 UI 做 per-product 判定。
|
|
107
127
|
*/
|
|
108
128
|
getAllSelectedSlots(): Map<number | string, VenueSlotSelection[]>;
|
|
109
129
|
/**
|
|
110
|
-
*
|
|
130
|
+
* 对指定 (resourceId, productId) 的订单商品进行 reconcile:
|
|
111
131
|
* 清除旧商品 → 合并连续时段 → 重新写入。
|
|
132
|
+
* 同一场地下不同商品互不干扰,各自单独 reconcile。
|
|
112
133
|
*/
|
|
113
|
-
private
|
|
134
|
+
private reconcileOrderForResourceProduct;
|
|
135
|
+
/** 给定一个父 rawResource,返回其 combined_resource.resource_ids 对应的子 rawResource 列表。 */
|
|
136
|
+
private getCombinedChildRawResources;
|
|
114
137
|
setSlotConfig(config: Partial<VenueBookingSlotConfig>): void;
|
|
115
138
|
getSlotConfig(): VenueBookingSlotConfig;
|
|
116
139
|
loadSchedules(): Promise<void>;
|