@pisell/pisellos 2.2.188 → 2.2.189

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.
Files changed (34) hide show
  1. package/dist/model/strategy/adapter/promotion/index.js +9 -0
  2. package/dist/modules/Order/index.d.ts +1 -0
  3. package/dist/modules/Order/index.js +32 -24
  4. package/dist/modules/Order/types.d.ts +1 -0
  5. package/dist/modules/Order/utils.js +3 -1
  6. package/dist/solution/BaseSales/index.js +20 -21
  7. package/dist/solution/BookingByStep/index.d.ts +1 -1
  8. package/dist/solution/BookingTicket/index.d.ts +15 -0
  9. package/dist/solution/BookingTicket/index.js +117 -6
  10. package/dist/solution/BookingTicket/types.d.ts +48 -0
  11. package/dist/solution/BookingTicket/types.js +5 -1
  12. package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.d.ts +36 -0
  13. package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.js +394 -0
  14. package/dist/solution/BookingTicket/utils/scan/formatGlobalScan.d.ts +32 -0
  15. package/dist/solution/BookingTicket/utils/scan/formatGlobalScan.js +56 -0
  16. package/dist/solution/BookingTicket/utils/scan/scanProductValues.d.ts +21 -0
  17. package/dist/solution/BookingTicket/utils/scan/scanProductValues.js +150 -0
  18. package/lib/model/strategy/adapter/promotion/index.js +49 -0
  19. package/lib/modules/Order/index.d.ts +1 -0
  20. package/lib/modules/Order/index.js +10 -5
  21. package/lib/modules/Order/types.d.ts +1 -0
  22. package/lib/modules/Order/utils.js +1 -0
  23. package/lib/solution/BaseSales/index.js +0 -1
  24. package/lib/solution/BookingByStep/index.d.ts +1 -1
  25. package/lib/solution/BookingTicket/index.d.ts +15 -0
  26. package/lib/solution/BookingTicket/index.js +56 -0
  27. package/lib/solution/BookingTicket/types.d.ts +48 -0
  28. package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.d.ts +36 -0
  29. package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.js +166 -0
  30. package/lib/solution/BookingTicket/utils/scan/formatGlobalScan.d.ts +32 -0
  31. package/lib/solution/BookingTicket/utils/scan/formatGlobalScan.js +51 -0
  32. package/lib/solution/BookingTicket/utils/scan/scanProductValues.d.ts +21 -0
  33. package/lib/solution/BookingTicket/utils/scan/scanProductValues.js +127 -0
  34. package/package.json +1 -1
@@ -0,0 +1,150 @@
1
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
+ 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; } } }; }
3
+ 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); }
4
+ 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; }
5
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
6
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
7
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
8
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
9
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
10
+ /**
11
+ * 扫码商品条码预选规格纯函数(对齐 ticketBooking addServiceVariant/utils)。
12
+ */
13
+
14
+ /** 套餐商品 */
15
+ export function isScanProductBundle(item) {
16
+ return ((item === null || item === void 0 ? void 0 : item.bundle_group_count) || 0) > 0;
17
+ }
18
+
19
+ /** 单规格 / 选项组商品 */
20
+ export function isScanProductOption(item) {
21
+ var _item$option_group;
22
+ return ((item === null || item === void 0 ? void 0 : item.option_group_count) || 0) > 0 || ((item === null || item === void 0 || (_item$option_group = item.option_group) === null || _item$option_group === void 0 ? void 0 : _item$option_group.length) || 0) > 0;
23
+ }
24
+ function formatVariantGroupTitle(title) {
25
+ var variantGroup = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
26
+ try {
27
+ return variantGroup.map(function (group) {
28
+ var value = title === null || title === void 0 ? void 0 : title[group === null || group === void 0 ? void 0 : group.position_id];
29
+ return value ? "".concat((group === null || group === void 0 ? void 0 : group.name) || '-', ": ").concat(value) : '';
30
+ }).filter(Boolean).join(', ');
31
+ } catch (_unused) {
32
+ return '';
33
+ }
34
+ }
35
+ function formatDataKey(data) {
36
+ var _next$option, _next$bundle;
37
+ var next = _objectSpread({}, data);
38
+ var key = "".concat(next.product_id);
39
+ var rowKey = key;
40
+ if (next.product_variant_id) {
41
+ var str = "_".concat(next.product_variant_id);
42
+ key += str;
43
+ rowKey += str;
44
+ }
45
+ if (next !== null && next !== void 0 && (_next$option = next.option) !== null && _next$option !== void 0 && _next$option.length) {
46
+ var _iterator = _createForOfIteratorHelper(next.option),
47
+ _step;
48
+ try {
49
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
50
+ var item = _step.value;
51
+ var _str = "_".concat(item.option_group_id, "_").concat(item.product_option_item_id);
52
+ key += _str;
53
+ rowKey += "".concat(_str, "_").concat(item.quantity || item.num);
54
+ }
55
+ } catch (err) {
56
+ _iterator.e(err);
57
+ } finally {
58
+ _iterator.f();
59
+ }
60
+ }
61
+ if (next !== null && next !== void 0 && (_next$bundle = next.bundle) !== null && _next$bundle !== void 0 && _next$bundle.length) {
62
+ var _iterator2 = _createForOfIteratorHelper(next.bundle),
63
+ _step2;
64
+ try {
65
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
66
+ var _item = _step2.value;
67
+ var _str2 = "_".concat(_item.group_id, "_").concat(_item.bundle_product_id);
68
+ key += _str2;
69
+ rowKey += "".concat(_str2, "_").concat(_item.quantity || _item.num);
70
+ if (_item !== null && _item !== void 0 && _item.option) {
71
+ var _iterator3 = _createForOfIteratorHelper(_item.option),
72
+ _step3;
73
+ try {
74
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
75
+ var opt = _step3.value;
76
+ var optStr = "_".concat(opt.option_group_id, "_").concat(opt.product_option_item_id);
77
+ key += optStr;
78
+ rowKey += "".concat(optStr, "_").concat(opt.quantity || opt.num);
79
+ }
80
+ } catch (err) {
81
+ _iterator3.e(err);
82
+ } finally {
83
+ _iterator3.f();
84
+ }
85
+ }
86
+ }
87
+ } catch (err) {
88
+ _iterator2.e(err);
89
+ } finally {
90
+ _iterator2.f();
91
+ }
92
+ }
93
+ if (next !== null && next !== void 0 && next.session) {
94
+ var _next$session;
95
+ var _str3 = "_".concat((_next$session = next.session) === null || _next$session === void 0 ? void 0 : _next$session.key);
96
+ key += _str3;
97
+ rowKey += _str3;
98
+ }
99
+ if (next !== null && next !== void 0 && next.schedule) {
100
+ var _next$schedule;
101
+ var _str4 = "_".concat((_next$schedule = next.schedule) === null || _next$schedule === void 0 ? void 0 : _next$schedule.key);
102
+ key += _str4;
103
+ rowKey += _str4;
104
+ }
105
+ next.key = key;
106
+ next.rowKey = rowKey;
107
+ return next;
108
+ }
109
+
110
+ /**
111
+ * 根据条码匹配 variant,生成 cartDetailValue(对齐 ticketBooking `genValues`)。
112
+ *
113
+ * @example
114
+ * ```ts
115
+ * const values = genScanProductValues(catalogItem, '6901234567890');
116
+ * const itemWithSelection = { ...catalogItem, cartDetailValue: values };
117
+ * ```
118
+ */
119
+ export function genScanProductValues(item, code) {
120
+ var _item$variant_group, _item$option_group2;
121
+ var params = {
122
+ bundle: [],
123
+ option: [],
124
+ product_id: item.id,
125
+ product_variant_id: 0,
126
+ quantity: 1,
127
+ rowKey: '',
128
+ session: null
129
+ };
130
+ if (item !== null && item !== void 0 && (_item$variant_group = item.variant_group) !== null && _item$variant_group !== void 0 && _item$variant_group.length || item !== null && item !== void 0 && (_item$option_group2 = item.option_group) !== null && _item$option_group2 !== void 0 && _item$option_group2.length) {
131
+ var variantItem = (item.variant || []).find(function (v) {
132
+ return (v === null || v === void 0 ? void 0 : v.code) === code || (v === null || v === void 0 ? void 0 : v.barcode) === code;
133
+ });
134
+ if (variantItem) {
135
+ params.price = Number((variantItem === null || variantItem === void 0 ? void 0 : variantItem.price) || 0);
136
+ params.product_variant_id = variantItem.id;
137
+ params.product_option_string = formatVariantGroupTitle(variantItem === null || variantItem === void 0 ? void 0 : variantItem.title, (item === null || item === void 0 ? void 0 : item.variant_group) || []);
138
+ }
139
+ }
140
+ return formatDataKey(params);
141
+ }
142
+
143
+ /**
144
+ * 统计条码命中的 variant 数量(多命中时需弹窗选择)。
145
+ */
146
+ export function countScanVariantMatches(item, code) {
147
+ return ((item === null || item === void 0 ? void 0 : item.variant) || []).filter(function (v) {
148
+ return (v === null || v === void 0 ? void 0 : v.code) === code || (v === null || v === void 0 ? void 0 : v.barcode) === code;
149
+ }).length;
150
+ }
@@ -0,0 +1,49 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+
29
+ // src/model/strategy/adapter/promotion/index.ts
30
+ var promotion_exports = {};
31
+ __export(promotion_exports, {
32
+ BUY_X_GET_Y_FREE_STRATEGY: () => import_examples.BUY_X_GET_Y_FREE_STRATEGY,
33
+ PromotionAdapter: () => import_adapter.PromotionAdapter,
34
+ PromotionEvaluator: () => import_evaluator.PromotionEvaluator,
35
+ X_ITEMS_FOR_Y_PRICE_STRATEGY: () => import_examples.X_ITEMS_FOR_Y_PRICE_STRATEGY,
36
+ default: () => import_adapter2.default
37
+ });
38
+ module.exports = __toCommonJS(promotion_exports);
39
+ var import_evaluator = require("./evaluator");
40
+ var import_adapter = require("./adapter");
41
+ var import_adapter2 = __toESM(require("./adapter"));
42
+ var import_examples = require("./examples");
43
+ // Annotate the CommonJS export names for ESM import in node:
44
+ 0 && (module.exports = {
45
+ BUY_X_GET_Y_FREE_STRATEGY,
46
+ PromotionAdapter,
47
+ PromotionEvaluator,
48
+ X_ITEMS_FOR_Y_PRICE_STRATEGY
49
+ });
@@ -143,6 +143,7 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
143
143
  private saveDraftInBackground;
144
144
  private hydrateTempOrderFromLocalRecord;
145
145
  private extractOrderIdFromSubmitResult;
146
+ private calculatePaymentEffectiveAmount;
146
147
  private calculatePaymentTotal;
147
148
  private normalizePaymentSource;
148
149
  private updateTempOrderPaymentStatus;
@@ -690,13 +690,16 @@ var OrderModule = class extends import_BaseModule.BaseModule {
690
690
  var _a, _b;
691
691
  return ((_a = result == null ? void 0 : result.data) == null ? void 0 : _a.order_id) ?? (result == null ? void 0 : result.order_id) ?? ((_b = result == null ? void 0 : result.data) == null ? void 0 : _b.id) ?? (result == null ? void 0 : result.id) ?? null;
692
692
  }
693
+ calculatePaymentEffectiveAmount(payment) {
694
+ const amount = new import_decimal.default(payment.amount || 0).minus(new import_decimal.default(payment.service_fee || 0));
695
+ const rounding = new import_decimal.default(payment.rounding_amount || 0);
696
+ return amount.minus(rounding);
697
+ }
693
698
  calculatePaymentTotal(payments) {
694
699
  return (0, import_utils.mapPaymentItemsToOrderPayments)(payments, {
695
700
  includeVoided: false
696
701
  }).reduce((sum, payment) => {
697
- const amount = new import_decimal.default(payment.amount || 0).minus(new import_decimal.default(payment.service_fee || 0));
698
- const rounding = new import_decimal.default(payment.rounding_amount || 0);
699
- return sum.plus(amount.minus(rounding));
702
+ return sum.plus(this.calculatePaymentEffectiveAmount(payment));
700
703
  }, new import_decimal.default(0));
701
704
  }
702
705
  normalizePaymentSource(payment, options) {
@@ -739,12 +742,14 @@ var OrderModule = class extends import_BaseModule.BaseModule {
739
742
  return {
740
743
  customerPaidAmount: summary.customerPaidAmount.plus(paymentRecord.amount || 0),
741
744
  orderPaidAmount: summary.orderPaidAmount.plus(paymentRecord.origin_amount || 0),
745
+ gapPaidAmount: summary.gapPaidAmount.plus(this.calculatePaymentEffectiveAmount(paymentRecord)),
742
746
  payServiceChargeAmount: summary.payServiceChargeAmount.plus(this.calculatePaymentServiceFee(paymentRecord))
743
747
  };
744
748
  },
745
749
  {
746
750
  customerPaidAmount: new import_decimal.default(0),
747
751
  orderPaidAmount: new import_decimal.default(0),
752
+ gapPaidAmount: new import_decimal.default(0),
748
753
  payServiceChargeAmount: new import_decimal.default(0)
749
754
  }
750
755
  );
@@ -1078,7 +1083,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1078
1083
  amount_gap: this.calculateSummaryAmountGap({
1079
1084
  tempOrder,
1080
1085
  summary: (0, import_utils.createEmptySummary)(),
1081
- orderPaidAmount: paidPaymentSummary.orderPaidAmount
1086
+ orderPaidAmount: paidPaymentSummary.gapPaidAmount
1082
1087
  }),
1083
1088
  pay_service_charge_amount: paidPaymentSummary.payServiceChargeAmount.toFixed(2)
1084
1089
  };
@@ -1100,7 +1105,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1100
1105
  amount_gap: this.calculateSummaryAmountGap({
1101
1106
  tempOrder,
1102
1107
  summary: salesSummaryResult,
1103
- orderPaidAmount: paidPaymentSummary.orderPaidAmount
1108
+ orderPaidAmount: paidPaymentSummary.gapPaidAmount
1104
1109
  }),
1105
1110
  pay_service_charge_amount: paidPaymentSummary.payServiceChargeAmount.toFixed(2)
1106
1111
  };
@@ -439,6 +439,7 @@ export interface OrderPaymentMetadata {
439
439
  [key: string]: any;
440
440
  }
441
441
  export interface OrderPaymentData {
442
+ order_payment_id?: number | string;
442
443
  amount: string;
443
444
  code: string;
444
445
  custom_payment_id: number;
@@ -753,6 +753,7 @@ function mapPaymentItemToOrderPayment(paymentItem) {
753
753
  }
754
754
  }
755
755
  return {
756
+ ...item.order_payment_id !== void 0 ? { order_payment_id: item.order_payment_id } : {},
756
757
  amount: String(item.amount ?? "0.00"),
757
758
  code: String(item.code || ""),
758
759
  custom_payment_id: Number(customPaymentId ?? 0),
@@ -432,7 +432,6 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
432
432
  const externalSaleNumber = params.externalSaleNumber || params.external_sale_number;
433
433
  if (!params.forceRemote) {
434
434
  const localRecord = params.orderId !== void 0 ? await this.store.order.getLocalOrderByOrderId(params.orderId) : externalSaleNumber ? await this.store.order.getLocalOrderByExternalSaleNumber(externalSaleNumber) : params.orderNumber ? await this.store.order.getLocalOrderByOrderNumber(params.orderNumber) : null;
435
- debugger;
436
435
  if (localRecord) {
437
436
  const sales2 = await this.store.order.hydrateTempOrderFromRecord(localRecord, { recalcOnHydrate: false });
438
437
  this.currentSalesDetail = sales2;
@@ -311,7 +311,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
311
311
  date: string;
312
312
  status: string;
313
313
  week: string;
314
- weekNum: 0 | 1 | 2 | 3 | 5 | 4 | 6;
314
+ weekNum: 0 | 1 | 2 | 6 | 3 | 5 | 4;
315
315
  }[]>;
316
316
  submitTimeSlot(timeSlots: TimeSliceItem): void;
317
317
  private getScheduleDataByIds;
@@ -7,6 +7,7 @@ import { BaseSalesImpl } from '../BaseSales';
7
7
  import type { BaseSalesScanCodeResult } from '../BaseSales/types';
8
8
  import type { ISalesDetail } from '../BaseSales/utils/parseSalesResponse';
9
9
  import type { LoadSalesDetailParams } from '../../modules/Order/types';
10
+ import type { GlobalScanHandleResult, GlobalScanHostBridge } from './types';
10
11
  import { AddProductDecideContext, AddProductRequiresDetailPayload } from './utils/addProductDecision';
11
12
  import { type BuildCacheItemFromOrderLineInput } from '../../modules/BookingContext/utils/buildCacheItemFromOrderLine';
12
13
  import { type BuildNormalProductCacheItemFromOrderLineInput } from '../../modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine';
@@ -441,6 +442,20 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
441
442
  buildNormalProductCacheItemFromOrderLine(input: BuildNormalProductCacheItemFromOrderLineInput): Record<string, any>;
442
443
  /** 文档别名:与 OrderModule.updateOrderProduct 一致。 */
443
444
  updateProductInOrder(params: UpdateOrderProductParams): Promise<OrderProduct[]>;
445
+ /**
446
+ * 全局扫码 pubsub 入口:解析码值 → 搜索 → 业务分发(客户 / 加车 / 开单)。
447
+ * UI 层在 pubsub 订阅回调里注入 `bridge`(uiHosts / action / cart.confirm*)。
448
+ *
449
+ * @example
450
+ * ```ts
451
+ * await bookingTicket.handleGlobalScanCode(payload.data, {
452
+ * openProductDetail: uiHosts.openProductDetail,
453
+ * confirmDetail: cart.confirmDetail,
454
+ * openOrder: ({ order_id }) => action({ type: 'pisell1.handleOpenCachedBigSale', data: { order_id } }),
455
+ * });
456
+ * ```
457
+ */
458
+ handleGlobalScanCode(code: string, bridge?: GlobalScanHostBridge): Promise<GlobalScanHandleResult>;
444
459
  /**
445
460
  * 销毁模块:先调用父类(销毁所有 store 内子模块 + emit destroy + super.destroy()),
446
461
  * 再清理 BookingTicket 自有资源(scan 监听 + scan 内存缓存)。
@@ -41,6 +41,8 @@ var import_scan = __toESM(require("./utils/scan"));
41
41
  var import_orderCustomer = require("./utils/orderCustomer");
42
42
  var import_handleScan = require("./utils/scan/handleScan");
43
43
  var import_scanCache = __toESM(require("./utils/scan/scanCache"));
44
+ var import_formatGlobalScan = require("./utils/scan/formatGlobalScan");
45
+ var import_applyGlobalScan = require("./utils/scan/applyGlobalScan");
44
46
  var import_cartView = require("./utils/cartView");
45
47
  var import_addProductDecision = require("./utils/addProductDecision");
46
48
  var import_buildCacheItemFromOrderLine = require("../../modules/BookingContext/utils/buildCacheItemFromOrderLine");
@@ -1017,6 +1019,60 @@ var BookingTicketImpl = class extends import_BaseSales.BaseSalesImpl {
1017
1019
  async updateProductInOrder(params) {
1018
1020
  return this.updateOrderProduct(params);
1019
1021
  }
1022
+ /**
1023
+ * 全局扫码 pubsub 入口:解析码值 → 搜索 → 业务分发(客户 / 加车 / 开单)。
1024
+ * UI 层在 pubsub 订阅回调里注入 `bridge`(uiHosts / action / cart.confirm*)。
1025
+ *
1026
+ * @example
1027
+ * ```ts
1028
+ * await bookingTicket.handleGlobalScanCode(payload.data, {
1029
+ * openProductDetail: uiHosts.openProductDetail,
1030
+ * confirmDetail: cart.confirmDetail,
1031
+ * openOrder: ({ order_id }) => action({ type: 'pisell1.handleOpenCachedBigSale', data: { order_id } }),
1032
+ * });
1033
+ * ```
1034
+ */
1035
+ async handleGlobalScanCode(code, bridge) {
1036
+ var _a, _b, _c, _d;
1037
+ const trimmed = typeof code === "string" ? code.trim() : "";
1038
+ if (!trimmed) {
1039
+ (_a = bridge == null ? void 0 : bridge.onNotify) == null ? void 0 : _a.call(bridge, "fail", "pisell2.text.scan-global-failed");
1040
+ return { status: "failed", reason: "empty_code" };
1041
+ }
1042
+ try {
1043
+ const localSearch = (v) => this.store.products.findProductsByCodeOrBarcode(v);
1044
+ const scanCallback = (0, import_handleScan.handleGlobalScan)(this.request, localSearch);
1045
+ const raw = await scanCallback({ type: "nativeScanner", value: trimmed });
1046
+ const formatted = (0, import_formatGlobalScan.formatGlobalScanResult)(raw, trimmed);
1047
+ if (!formatted) {
1048
+ (_b = bridge == null ? void 0 : bridge.onNotify) == null ? void 0 : _b.call(bridge, "fail", "pisell2.text.scan-global-failed");
1049
+ return { status: "failed", reason: "not_found" };
1050
+ }
1051
+ const result = await (0, import_applyGlobalScan.applyGlobalScan)(
1052
+ {
1053
+ setOrderCustomer: (customer) => this.setOrderCustomer(customer),
1054
+ getOrderCustomerSnapshot: () => this.getOrderCustomerSnapshot(),
1055
+ getBusinessCode: () => {
1056
+ var _a2;
1057
+ return (_a2 = this.otherParams) == null ? void 0 : _a2.businessCode;
1058
+ },
1059
+ buildAddProductCtx: (extra) => this.buildAddProductCtx(extra),
1060
+ decideAddProduct: (item, options) => this.decideAddProduct(item, options),
1061
+ decideAfterDetail: (cacheItem, options) => this.decideAfterDetail(cacheItem, options),
1062
+ transformDetailToProductAndBooking: (input) => this.transformDetailToProductAndBooking(input),
1063
+ addProductToOrder: (product, booking) => this.addProductToOrder(product, booking)
1064
+ },
1065
+ formatted,
1066
+ bridge
1067
+ );
1068
+ (_c = bridge == null ? void 0 : bridge.refresh) == null ? void 0 : _c.call(bridge);
1069
+ return result;
1070
+ } catch (error) {
1071
+ console.error("[BookingTicket] handleGlobalScanCode failed", error);
1072
+ (_d = bridge == null ? void 0 : bridge.onNotify) == null ? void 0 : _d.call(bridge, "fail", "pisell2.text.scan-global-failed");
1073
+ return { status: "failed", reason: "not_found" };
1074
+ }
1075
+ }
1020
1076
  /**
1021
1077
  * 销毁模块:先调用父类(销毁所有 store 内子模块 + emit destroy + super.destroy()),
1022
1078
  * 再清理 BookingTicket 自有资源(scan 监听 + scan 内存缓存)。
@@ -134,3 +134,51 @@ export interface BookingTicketCustomerView {
134
134
  export interface BookingTicketProductCatalogView {
135
135
  products: ProductData[];
136
136
  }
137
+ /** 扫码宿主桥接:SalesSdk 在 pubsub 订阅回调里注入,OS 需要 UI 时直接调用 */
138
+ export interface GlobalScanHostBridge {
139
+ openProductDetail?: (payload: Record<string, any>) => Promise<any | null>;
140
+ openBookingEdit?: (payload: Record<string, any>) => Promise<any | null>;
141
+ confirmDetail?: (input: {
142
+ item: any;
143
+ detailResult: {
144
+ e: any;
145
+ extension_type?: any;
146
+ detail?: any;
147
+ };
148
+ options?: Record<string, any>;
149
+ }) => Promise<any>;
150
+ confirmBookingEdit?: (input: {
151
+ cacheItem: any;
152
+ options?: Record<string, any>;
153
+ }) => Promise<any>;
154
+ openOrder?: (data: {
155
+ order_id: number;
156
+ business_code?: string;
157
+ }) => void;
158
+ /**
159
+ * walk-in 扫 walletPass:直接核销优惠码(对齐 SaleDetail Voucher.handleApplyCode / cart.scanCode)。
160
+ */
161
+ applyPromotionCode?: (code: string, customerId?: number) => Promise<{
162
+ isAvailable?: boolean;
163
+ type?: string;
164
+ unavailableReason?: string;
165
+ }>;
166
+ onNotify?: (type: 'success' | 'fail' | 'info', messageKey?: string) => void;
167
+ refresh?: () => void;
168
+ }
169
+ /** handleGlobalScanCode 结构化返回 */
170
+ export type GlobalScanHandleResult = {
171
+ status: 'success';
172
+ kind: 'customer' | 'products' | 'promotion';
173
+ meta?: {
174
+ count?: number;
175
+ };
176
+ } | {
177
+ status: 'pending';
178
+ kind: 'openOrder' | 'requiresDetail' | 'requiresBookingEdit';
179
+ } | {
180
+ status: 'cancelled';
181
+ } | {
182
+ status: 'failed';
183
+ reason: 'empty_code' | 'not_found' | 'invalid_data' | 'no_bridge';
184
+ };
@@ -0,0 +1,36 @@
1
+ import type { GlobalScanHandleResult, GlobalScanHostBridge, ICustomer } from '../../types';
2
+ import type { AddProductDecision } from '../addProductDecision';
3
+ import { GlobalScanFormattedResult } from './formatGlobalScan';
4
+ /** applyGlobalScan 所需的 BookingTicket 运行时能力 */
5
+ export interface GlobalScanApplyHost {
6
+ setOrderCustomer(customer: ICustomer | null): void;
7
+ getOrderCustomerSnapshot(): ICustomer | null;
8
+ getBusinessCode(): string | undefined;
9
+ buildAddProductCtx(extra?: Record<string, any>): Record<string, any>;
10
+ decideAddProduct(item: any, options?: Record<string, any>): AddProductDecision;
11
+ decideAfterDetail(cacheItem: any, options?: Record<string, any>): AddProductDecision;
12
+ transformDetailToProductAndBooking(input: {
13
+ item: any;
14
+ cacheItem?: any;
15
+ detailResult?: {
16
+ e: any;
17
+ extension_type?: any;
18
+ detail?: any;
19
+ };
20
+ options?: Record<string, any>;
21
+ }): {
22
+ product: any;
23
+ booking?: any;
24
+ cacheItem: any;
25
+ };
26
+ addProductToOrder(product: any, booking?: any): Promise<any>;
27
+ }
28
+ /**
29
+ * 应用全局扫码格式化结果:设客户 / 加车 / 开单 / 弹窗链。
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * const result = await applyGlobalScan(bookingTicket, formatted, bridge);
34
+ * ```
35
+ */
36
+ export declare function applyGlobalScan(host: GlobalScanApplyHost, formatted: GlobalScanFormattedResult, bridge?: GlobalScanHostBridge): Promise<GlobalScanHandleResult>;
@@ -0,0 +1,166 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // src/solution/BookingTicket/utils/scan/applyGlobalScan.ts
20
+ var applyGlobalScan_exports = {};
21
+ __export(applyGlobalScan_exports, {
22
+ applyGlobalScan: () => applyGlobalScan
23
+ });
24
+ module.exports = __toCommonJS(applyGlobalScan_exports);
25
+ var import_addProductDecision = require("../addProductDecision");
26
+ var import_cartView = require("../cartView");
27
+ var import_scanProductValues = require("./scanProductValues");
28
+ async function processScannedProductItem(host, item, code, bridge) {
29
+ const ctx = host.buildAddProductCtx();
30
+ if ((0, import_scanProductValues.isScanProductBundle)(item) || (0, import_scanProductValues.isScanProductOption)(item)) {
31
+ return runRequiresDetailFlow(host, item, ctx, bridge);
32
+ }
33
+ if ((0, import_scanProductValues.countScanVariantMatches)(item, code) >= 2) {
34
+ return runRequiresDetailFlow(host, item, ctx, bridge);
35
+ }
36
+ const values = (0, import_scanProductValues.genScanProductValues)(item, code);
37
+ const itemWithSelection = { ...item, cartDetailValue: values };
38
+ const decision = host.decideAddProduct(itemWithSelection, ctx);
39
+ return runAddProductDecision(host, item, decision, ctx, bridge);
40
+ }
41
+ async function runRequiresDetailFlow(host, item, ctx, bridge) {
42
+ if (!(bridge == null ? void 0 : bridge.openProductDetail)) {
43
+ return "pending";
44
+ }
45
+ const payload = (0, import_addProductDecision.buildRequiresDetailPayload)(item, ctx);
46
+ const detailResult = await bridge.openProductDetail(payload);
47
+ if (!detailResult) {
48
+ return "cancelled";
49
+ }
50
+ if (!bridge.confirmDetail) {
51
+ return "pending";
52
+ }
53
+ await bridge.confirmDetail({
54
+ item: payload.productData ?? payload.item ?? item,
55
+ detailResult
56
+ });
57
+ return "added";
58
+ }
59
+ async function runAddProductDecision(host, catalogItem, decision, ctx, bridge) {
60
+ if (decision.action === "add") {
61
+ const transformed = host.transformDetailToProductAndBooking({
62
+ item: catalogItem,
63
+ cacheItem: decision.cacheItem,
64
+ options: ctx
65
+ });
66
+ await host.addProductToOrder(transformed.product, transformed.booking);
67
+ return "added";
68
+ }
69
+ if (decision.action === "requiresDetail") {
70
+ return runRequiresDetailFlow(host, catalogItem, ctx, bridge);
71
+ }
72
+ if (decision.action === "requiresBookingEdit") {
73
+ if (!(bridge == null ? void 0 : bridge.openBookingEdit)) {
74
+ return "pending";
75
+ }
76
+ const edited = await bridge.openBookingEdit(decision.payload);
77
+ if (!edited) {
78
+ return "cancelled";
79
+ }
80
+ if (!bridge.confirmBookingEdit) {
81
+ return "pending";
82
+ }
83
+ await bridge.confirmBookingEdit({ cacheItem: edited });
84
+ return "added";
85
+ }
86
+ return "pending";
87
+ }
88
+ async function applyGlobalScan(host, formatted, bridge) {
89
+ var _a, _b, _c, _d, _e, _f, _g;
90
+ const { searchType, data, scanCode } = formatted;
91
+ debugger;
92
+ if (searchType === "wallet") {
93
+ if (!data) {
94
+ (_a = bridge == null ? void 0 : bridge.onNotify) == null ? void 0 : _a.call(bridge, "fail", "pisell2.text.scan-global-failed");
95
+ return { status: "failed", reason: "invalid_data" };
96
+ }
97
+ host.setOrderCustomer(data);
98
+ (_b = bridge == null ? void 0 : bridge.onNotify) == null ? void 0 : _b.call(bridge, "success", "pisell2.text.add-client-success");
99
+ return { status: "success", kind: "customer" };
100
+ }
101
+ if (searchType === "walletPass") {
102
+ if (!data) {
103
+ (_c = bridge == null ? void 0 : bridge.onNotify) == null ? void 0 : _c.call(bridge, "fail", "pisell2.text.scan-global-failed");
104
+ return { status: "failed", reason: "invalid_data" };
105
+ }
106
+ const snapshot = host.getOrderCustomerSnapshot();
107
+ if ((0, import_cartView.isWalkInCustomer)(snapshot)) {
108
+ if (!(bridge == null ? void 0 : bridge.applyPromotionCode)) {
109
+ return { status: "failed", reason: "no_bridge" };
110
+ }
111
+ const result = await bridge.applyPromotionCode(scanCode);
112
+ if (result == null ? void 0 : result.isAvailable) {
113
+ return { status: "success", kind: "promotion" };
114
+ }
115
+ return { status: "failed", reason: "invalid_data" };
116
+ }
117
+ host.setOrderCustomer(data);
118
+ (_d = bridge == null ? void 0 : bridge.onNotify) == null ? void 0 : _d.call(bridge, "success", "pisell2.text.add-client-success");
119
+ return { status: "success", kind: "customer" };
120
+ }
121
+ if (searchType === "product" || searchType === "local_product") {
122
+ const list = data == null ? void 0 : data.list;
123
+ if (!Array.isArray(list) || list.length === 0) {
124
+ (_e = bridge == null ? void 0 : bridge.onNotify) == null ? void 0 : _e.call(bridge, "fail", "pisell2.text.scan-global-failed");
125
+ return { status: "failed", reason: "invalid_data" };
126
+ }
127
+ let addedCount = 0;
128
+ for (const item of list) {
129
+ const outcome = await processScannedProductItem(host, item, scanCode, bridge);
130
+ if (outcome === "added") {
131
+ addedCount += 1;
132
+ }
133
+ if (outcome === "cancelled") {
134
+ return { status: "cancelled" };
135
+ }
136
+ if (outcome === "pending") {
137
+ return { status: "pending", kind: "requiresDetail" };
138
+ }
139
+ }
140
+ if (addedCount > 0) {
141
+ (_f = bridge == null ? void 0 : bridge.onNotify) == null ? void 0 : _f.call(bridge, "success");
142
+ return { status: "success", kind: "products", meta: { count: addedCount } };
143
+ }
144
+ return { status: "failed", reason: "no_bridge" };
145
+ }
146
+ if (searchType === "order") {
147
+ const orderId = (data == null ? void 0 : data.order_id) ?? (data == null ? void 0 : data.id);
148
+ if (!orderId) {
149
+ (_g = bridge == null ? void 0 : bridge.onNotify) == null ? void 0 : _g.call(bridge, "fail", "pisell2.text.scan-global-failed");
150
+ return { status: "failed", reason: "invalid_data" };
151
+ }
152
+ if (!(bridge == null ? void 0 : bridge.openOrder)) {
153
+ return { status: "pending", kind: "openOrder" };
154
+ }
155
+ bridge.openOrder({
156
+ order_id: Number(orderId),
157
+ business_code: host.getBusinessCode()
158
+ });
159
+ return { status: "pending", kind: "openOrder" };
160
+ }
161
+ return { status: "failed", reason: "invalid_data" };
162
+ }
163
+ // Annotate the CommonJS export names for ESM import in node:
164
+ 0 && (module.exports = {
165
+ applyGlobalScan
166
+ });