@pisell/pisellos 0.10.42 → 0.10.43

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.
@@ -1,9 +0,0 @@
1
- // 导出评估器
2
- export { PromotionEvaluator } from "./evaluator";
3
-
4
- // 导出适配器
5
- export { PromotionAdapter } from "./adapter";
6
- export { default } from "./adapter";
7
-
8
- // 导出策略配置示例常量
9
- export { X_ITEMS_FOR_Y_PRICE_STRATEGY, BUY_X_GET_Y_FREE_STRATEGY, ITEM_REWARD_STRATEGY } from "./examples";
@@ -540,7 +540,7 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
540
540
  generateIdempotencyToken(): string;
541
541
  syncPaymentsToOrder<T = any>(params: SyncPaymentsToOrderParams): Promise<SyncPaymentsToOrderResult<T>>;
542
542
  createOrder(params: CommitOrderParams['query']): {
543
- type: "virtual" | "appointment_booking";
543
+ type: "appointment_booking" | "virtual";
544
544
  platform: string;
545
545
  sales_channel: string;
546
546
  order_sales_channel: string;
@@ -1813,7 +1813,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1813
1813
 
1814
1814
  // 计算折扣后的价格(使用 getDiscountAmount,内部已处理 maxDeductionAmount)
1815
1815
  var discountedPrice = getDiscountAmount(_selectedDiscount2, product.origin_total, product.origin_total);
1816
- var bundleDiscountAmount = new Decimal(product.origin_total || 0).minus(discountedPrice).toNumber();
1816
+ var bundleDiscountAmountPerItem = new Decimal(product.origin_total || 0).minus(discountedPrice).toNumber();
1817
+ var bundleDiscountAmount = new Decimal(bundleDiscountAmountPerItem).mul(_appliedUseCount).toNumber();
1817
1818
  debugger;
1818
1819
  var _discountDetail = {
1819
1820
  amount: bundleDiscountAmount,
@@ -326,7 +326,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
326
326
  date: string;
327
327
  status: string;
328
328
  week: string;
329
- weekNum: 0 | 1 | 2 | 3 | 4 | 5 | 6;
329
+ weekNum: 0 | 2 | 1 | 3 | 4 | 5 | 6;
330
330
  }[]>;
331
331
  submitTimeSlot(timeSlots: TimeSliceItem): void;
332
332
  private getScheduleDataByIds;
@@ -230,12 +230,16 @@ export interface GlobalScanHostBridge {
230
230
  /**
231
231
  * walk-in 扫 walletPass:直接核销优惠码(对齐 SaleDetail Voucher.handleApplyCode / cart.scanCode)。
232
232
  */
233
- applyPromotionCode?: (code: string, customerId?: number) => Promise<{
233
+ applyPromotionCode?: (code: string, customerId?: number, options?: {
234
+ suppressFailureNotification?: boolean;
235
+ }) => Promise<{
234
236
  isAvailable?: boolean;
235
237
  isAccepted?: boolean;
236
238
  type?: string;
237
239
  unavailableReason?: string;
238
240
  }>;
241
+ /** 当前订单已有其他客户时,由宿主复用客户组件完成确认及切换。 */
242
+ requestCustomerSwitch?: (customer: ICustomer) => Promise<boolean | null>;
239
243
  onNotify?: (type: 'success' | 'fail' | 'info', messageKey?: string) => void;
240
244
  refresh?: () => void;
241
245
  }
@@ -206,35 +206,27 @@ export function applyGlobalScan(_x14, _x15, _x16) {
206
206
  }
207
207
  function _applyGlobalScan() {
208
208
  _applyGlobalScan = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(host, formatted, bridge) {
209
- var searchType, data, scanCode, formattedCustomerId, isCrossShopWallet, _getRealCustomerId, _bridge$onNotify4, currentCustomer, _customer, sourceCustomerId, _bridge$onNotify, _bridge$onNotify2, _customerId, _bridge$onNotify3, orderCustomer, _promotionResult$isAc, snapshot, currentCustomerIsWalkIn, activeCustomer, bindWalletPassCustomer, trySelectWalletAsset, walletSelection, promotionResult, list, _bridge$onNotify10, addedCount, _iterator, _step, _item, outcome, _bridge$onNotify11, _data$order_id, _data$business_code, orderId, _bridge$onNotify12;
209
+ var searchType, data, scanCode, formattedCustomerId, isCrossShopWallet, isWalletPassUnavailableAtStore, _getRealCustomerId, _bridge$onNotify5, currentCustomer, currentCustomerId, _customer, sourceCustomerId, _bridge$onNotify, _bridge$onNotify2, _customerId, _bridge$onNotify3, orderCustomer, switched, _bridge$onNotify4, _promotionResult$isAc, _bridge$onNotify6, snapshot, activeCustomer, bindWalletPassCustomer, trySelectWalletAsset, bindResult, walletSelection, promotionCustomerId, promotionResult, list, _bridge$onNotify12, addedCount, _iterator, _step, _item, outcome, _bridge$onNotify13, _data$order_id, _data$business_code, orderId, _bridge$onNotify14;
210
210
  return _regeneratorRuntime().wrap(function _callee6$(_context6) {
211
211
  while (1) switch (_context6.prev = _context6.next) {
212
212
  case 0:
213
- searchType = formatted.searchType, data = formatted.data, scanCode = formatted.scanCode, formattedCustomerId = formatted.customerId, isCrossShopWallet = formatted.isCrossShopWallet;
213
+ searchType = formatted.searchType, data = formatted.data, scanCode = formatted.scanCode, formattedCustomerId = formatted.customerId, isCrossShopWallet = formatted.isCrossShopWallet, isWalletPassUnavailableAtStore = formatted.isWalletPassUnavailableAtStore;
214
214
  if (!(searchType === 'wallet')) {
215
- _context6.next = 29;
215
+ _context6.next = 44;
216
216
  break;
217
217
  }
218
218
  currentCustomer = host.getOrderCustomerSnapshot();
219
- if (!(getRealCustomerId(currentCustomer) !== undefined)) {
220
- _context6.next = 5;
221
- break;
222
- }
223
- return _context6.abrupt("return", {
224
- status: 'success',
225
- kind: 'customer'
226
- });
227
- case 5:
219
+ currentCustomerId = getRealCustomerId(currentCustomer);
228
220
  _customer = data;
229
221
  if (!isCrossShopWallet) {
230
- _context6.next = 21;
222
+ _context6.next = 20;
231
223
  break;
232
224
  }
233
225
  sourceCustomerId = getRealCustomerId({
234
226
  id: formattedCustomerId
235
227
  });
236
228
  if (!(sourceCustomerId === undefined || !host.resolveCustomerById)) {
237
- _context6.next = 11;
229
+ _context6.next = 10;
238
230
  break;
239
231
  }
240
232
  bridge === null || bridge === void 0 || (_bridge$onNotify = bridge.onNotify) === null || _bridge$onNotify === void 0 || _bridge$onNotify.call(bridge, 'fail', 'pisell2.text.scan-global-failed');
@@ -242,28 +234,28 @@ function _applyGlobalScan() {
242
234
  status: 'failed',
243
235
  reason: 'invalid_data'
244
236
  });
245
- case 11:
246
- _context6.prev = 11;
247
- _context6.next = 14;
237
+ case 10:
238
+ _context6.prev = 10;
239
+ _context6.next = 13;
248
240
  return host.resolveCustomerById(sourceCustomerId);
249
- case 14:
241
+ case 13:
250
242
  _customer = _context6.sent;
251
- _context6.next = 21;
243
+ _context6.next = 20;
252
244
  break;
253
- case 17:
254
- _context6.prev = 17;
255
- _context6.t0 = _context6["catch"](11);
245
+ case 16:
246
+ _context6.prev = 16;
247
+ _context6.t0 = _context6["catch"](10);
256
248
  bridge === null || bridge === void 0 || (_bridge$onNotify2 = bridge.onNotify) === null || _bridge$onNotify2 === void 0 || _bridge$onNotify2.call(bridge, 'fail', getErrorMessage(_context6.t0) || 'pisell2.text.scan-global-failed');
257
249
  return _context6.abrupt("return", {
258
250
  status: 'failed',
259
251
  reason: 'invalid_data'
260
252
  });
261
- case 21:
253
+ case 20:
262
254
  _customerId = (_getRealCustomerId = getRealCustomerId(_customer)) !== null && _getRealCustomerId !== void 0 ? _getRealCustomerId : !isCrossShopWallet ? getRealCustomerId({
263
255
  id: formattedCustomerId
264
256
  }) : undefined;
265
257
  if (!(!_customer || _customerId === undefined)) {
266
- _context6.next = 25;
258
+ _context6.next = 24;
267
259
  break;
268
260
  }
269
261
  bridge === null || bridge === void 0 || (_bridge$onNotify3 = bridge.onNotify) === null || _bridge$onNotify3 === void 0 || _bridge$onNotify3.call(bridge, 'fail', 'pisell2.text.scan-global-failed');
@@ -271,37 +263,89 @@ function _applyGlobalScan() {
271
263
  status: 'failed',
272
264
  reason: 'invalid_data'
273
265
  });
274
- case 25:
266
+ case 24:
275
267
  orderCustomer = _customer.id === undefined || _customer.id === null ? _objectSpread(_objectSpread({}, _customer), {}, {
276
268
  id: _customerId
277
269
  }) : _customer;
270
+ if (!(currentCustomerId === _customerId)) {
271
+ _context6.next = 27;
272
+ break;
273
+ }
274
+ return _context6.abrupt("return", {
275
+ status: 'success',
276
+ kind: 'customer'
277
+ });
278
+ case 27:
279
+ if (!(currentCustomerId !== undefined)) {
280
+ _context6.next = 41;
281
+ break;
282
+ }
283
+ if (bridge !== null && bridge !== void 0 && bridge.requestCustomerSwitch) {
284
+ _context6.next = 30;
285
+ break;
286
+ }
287
+ return _context6.abrupt("return", {
288
+ status: 'success',
289
+ kind: 'customer'
290
+ });
291
+ case 30:
292
+ _context6.prev = 30;
293
+ _context6.next = 33;
294
+ return bridge.requestCustomerSwitch(orderCustomer);
295
+ case 33:
296
+ switched = _context6.sent;
297
+ return _context6.abrupt("return", switched ? {
298
+ status: 'success',
299
+ kind: 'customer'
300
+ } : {
301
+ status: 'cancelled'
302
+ });
303
+ case 37:
304
+ _context6.prev = 37;
305
+ _context6.t1 = _context6["catch"](30);
306
+ (_bridge$onNotify4 = bridge.onNotify) === null || _bridge$onNotify4 === void 0 || _bridge$onNotify4.call(bridge, 'fail', getErrorMessage(_context6.t1) || 'pisell2.text.scan-global-failed');
307
+ return _context6.abrupt("return", {
308
+ status: 'failed',
309
+ reason: 'invalid_data'
310
+ });
311
+ case 41:
278
312
  host.setOrderCustomer(orderCustomer);
279
- bridge === null || bridge === void 0 || (_bridge$onNotify4 = bridge.onNotify) === null || _bridge$onNotify4 === void 0 || _bridge$onNotify4.call(bridge, 'success', 'pisell2.text.add-client-success');
313
+ bridge === null || bridge === void 0 || (_bridge$onNotify5 = bridge.onNotify) === null || _bridge$onNotify5 === void 0 || _bridge$onNotify5.call(bridge, 'success', 'pisell2.text.add-client-success');
280
314
  return _context6.abrupt("return", {
281
315
  status: 'success',
282
316
  kind: 'customer'
283
317
  });
284
- case 29:
318
+ case 44:
285
319
  if (!(searchType === 'walletPass')) {
286
- _context6.next = 50;
320
+ _context6.next = 78;
321
+ break;
322
+ }
323
+ if (!isWalletPassUnavailableAtStore) {
324
+ _context6.next = 48;
287
325
  break;
288
326
  }
327
+ bridge === null || bridge === void 0 || (_bridge$onNotify6 = bridge.onNotify) === null || _bridge$onNotify6 === void 0 || _bridge$onNotify6.call(bridge, 'fail', 'pisell2.text.wallet-pass-not-available-at-store');
328
+ return _context6.abrupt("return", {
329
+ status: 'failed',
330
+ reason: 'invalid_data'
331
+ });
332
+ case 48:
289
333
  snapshot = host.getOrderCustomerSnapshot();
290
- currentCustomerIsWalkIn = getRealCustomerId(snapshot) === undefined;
291
334
  activeCustomer = snapshot;
292
335
  bindWalletPassCustomer = /*#__PURE__*/function () {
293
336
  var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(asset) {
294
337
  var _getWalletAssetCustom, _host$refreshWalletAs;
295
- var assetCustomerId, customer, _bridge$onNotify5, _bridge$onNotify6, customerId, _bridge$onNotify7, orderCustomer;
338
+ var assetCustomerId, customer, _bridge$onNotify7, _bridge$onNotify8, customerId, _bridge$onNotify9, orderCustomer;
296
339
  return _regeneratorRuntime().wrap(function _callee4$(_context4) {
297
340
  while (1) switch (_context4.prev = _context4.next) {
298
341
  case 0:
299
- if (currentCustomerIsWalkIn) {
342
+ if (!(getRealCustomerId(activeCustomer) !== undefined)) {
300
343
  _context4.next = 2;
301
344
  break;
302
345
  }
303
346
  return _context4.abrupt("return", {
304
- resolveFailed: false
347
+ resolveFailed: false,
348
+ customerBound: false
305
349
  });
306
350
  case 2:
307
351
  assetCustomerId = (_getWalletAssetCustom = getWalletAssetCustomerId(asset)) !== null && _getWalletAssetCustom !== void 0 ? _getWalletAssetCustom : getRealCustomerId({
@@ -316,9 +360,10 @@ function _applyGlobalScan() {
316
360
  _context4.next = 8;
317
361
  break;
318
362
  }
319
- bridge === null || bridge === void 0 || (_bridge$onNotify5 = bridge.onNotify) === null || _bridge$onNotify5 === void 0 || _bridge$onNotify5.call(bridge, 'fail', 'pisell2.text.scan-global-failed');
363
+ bridge === null || bridge === void 0 || (_bridge$onNotify7 = bridge.onNotify) === null || _bridge$onNotify7 === void 0 || _bridge$onNotify7.call(bridge, 'fail', 'pisell2.text.scan-global-failed');
320
364
  return _context4.abrupt("return", {
321
- resolveFailed: true
365
+ resolveFailed: true,
366
+ customerBound: false
322
367
  });
323
368
  case 8:
324
369
  _context4.prev = 8;
@@ -332,9 +377,10 @@ function _applyGlobalScan() {
332
377
  _context4.prev = 14;
333
378
  _context4.t0 = _context4["catch"](8);
334
379
  console.warn('[GlobalScan] Wallet asset customer lookup failed', _context4.t0);
335
- bridge === null || bridge === void 0 || (_bridge$onNotify6 = bridge.onNotify) === null || _bridge$onNotify6 === void 0 || _bridge$onNotify6.call(bridge, 'fail', getErrorMessage(_context4.t0) || 'pisell2.text.scan-global-failed');
380
+ bridge === null || bridge === void 0 || (_bridge$onNotify8 = bridge.onNotify) === null || _bridge$onNotify8 === void 0 || _bridge$onNotify8.call(bridge, 'fail', getErrorMessage(_context4.t0) || 'pisell2.text.scan-global-failed');
336
381
  return _context4.abrupt("return", {
337
- resolveFailed: true
382
+ resolveFailed: true,
383
+ customerBound: false
338
384
  });
339
385
  case 19:
340
386
  customerId = getRealCustomerId(customer);
@@ -343,10 +389,11 @@ function _applyGlobalScan() {
343
389
  break;
344
390
  }
345
391
  if (assetCustomerId !== undefined) {
346
- bridge === null || bridge === void 0 || (_bridge$onNotify7 = bridge.onNotify) === null || _bridge$onNotify7 === void 0 || _bridge$onNotify7.call(bridge, 'fail', 'pisell2.text.scan-global-failed');
392
+ bridge === null || bridge === void 0 || (_bridge$onNotify9 = bridge.onNotify) === null || _bridge$onNotify9 === void 0 || _bridge$onNotify9.call(bridge, 'fail', 'pisell2.text.scan-global-failed');
347
393
  }
348
394
  return _context4.abrupt("return", {
349
- resolveFailed: assetCustomerId !== undefined
395
+ resolveFailed: assetCustomerId !== undefined,
396
+ customerBound: false
350
397
  });
351
398
  case 23:
352
399
  orderCustomer = customer.id === undefined || customer.id === null ? _objectSpread(_objectSpread({}, customer), {}, {
@@ -361,7 +408,8 @@ function _applyGlobalScan() {
361
408
  });
362
409
  case 28:
363
410
  return _context4.abrupt("return", {
364
- resolveFailed: false
411
+ resolveFailed: false,
412
+ customerBound: true
365
413
  });
366
414
  case 29:
367
415
  case "end":
@@ -375,7 +423,7 @@ function _applyGlobalScan() {
375
423
  }();
376
424
  trySelectWalletAsset = /*#__PURE__*/function () {
377
425
  var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5() {
378
- var walletResult, bindResult, _bridge$onNotify8, _bridge$onNotify9;
426
+ var walletResult, bindResult, _bridge$onNotify10, _bridge$onNotify11;
379
427
  return _regeneratorRuntime().wrap(function _callee5$(_context5) {
380
428
  while (1) switch (_context5.prev = _context5.next) {
381
429
  case 0:
@@ -413,7 +461,7 @@ function _applyGlobalScan() {
413
461
  break;
414
462
  }
415
463
  if (!bindResult.resolveFailed) {
416
- bridge === null || bridge === void 0 || (_bridge$onNotify8 = bridge.onNotify) === null || _bridge$onNotify8 === void 0 || _bridge$onNotify8.call(bridge, 'success');
464
+ bridge === null || bridge === void 0 || (_bridge$onNotify10 = bridge.onNotify) === null || _bridge$onNotify10 === void 0 || _bridge$onNotify10.call(bridge, 'success');
417
465
  }
418
466
  return _context5.abrupt("return", {
419
467
  status: 'success',
@@ -422,7 +470,7 @@ function _applyGlobalScan() {
422
470
  case 15:
423
471
  // 已识别为 Wallet 支付资产但当前不可用:保留禁用展示,不回退优惠码。
424
472
  if (!bindResult.resolveFailed) {
425
- bridge === null || bridge === void 0 || (_bridge$onNotify9 = bridge.onNotify) === null || _bridge$onNotify9 === void 0 || _bridge$onNotify9.call(bridge, 'fail', 'pisell2.text.goodpass.code-invalid-cart');
473
+ bridge === null || bridge === void 0 || (_bridge$onNotify11 = bridge.onNotify) === null || _bridge$onNotify11 === void 0 || _bridge$onNotify11.call(bridge, 'fail', 'pisell2.text.goodpass.code-invalid-cart');
426
474
  }
427
475
  return _context5.abrupt("return", {
428
476
  status: 'failed',
@@ -437,115 +485,142 @@ function _applyGlobalScan() {
437
485
  return function trySelectWalletAsset() {
438
486
  return _ref3.apply(this, arguments);
439
487
  };
440
- }();
441
- _context6.next = 37;
488
+ }(); // batch-search 可能返回来源门店客户;先映射到当前门店,确保 Wallet
489
+ // 支付资产查询使用本店客户上下文。
490
+ _context6.next = 54;
491
+ return bindWalletPassCustomer();
492
+ case 54:
493
+ bindResult = _context6.sent;
494
+ _context6.next = 57;
442
495
  return trySelectWalletAsset();
443
- case 37:
496
+ case 57:
444
497
  walletSelection = _context6.sent;
445
498
  if (!walletSelection) {
446
- _context6.next = 40;
499
+ _context6.next = 60;
447
500
  break;
448
501
  }
449
502
  return _context6.abrupt("return", walletSelection);
450
- case 40:
451
- _context6.next = 42;
452
- return bindWalletPassCustomer();
453
- case 42:
503
+ case 60:
454
504
  if (bridge !== null && bridge !== void 0 && bridge.applyPromotionCode) {
455
- _context6.next = 44;
505
+ _context6.next = 62;
456
506
  break;
457
507
  }
458
508
  return _context6.abrupt("return", {
459
509
  status: 'failed',
460
510
  reason: 'no_bridge'
461
511
  });
462
- case 44:
463
- _context6.next = 46;
464
- return bridge.applyPromotionCode(scanCode, getRealCustomerId(activeCustomer));
465
- case 46:
466
- promotionResult = _context6.sent;
512
+ case 62:
513
+ promotionCustomerId = getRealCustomerId(activeCustomer);
514
+ if (!bindResult.customerBound) {
515
+ _context6.next = 69;
516
+ break;
517
+ }
518
+ _context6.next = 66;
519
+ return bridge.applyPromotionCode(scanCode, promotionCustomerId, {
520
+ suppressFailureNotification: true
521
+ });
522
+ case 66:
523
+ _context6.t2 = _context6.sent;
524
+ _context6.next = 72;
525
+ break;
526
+ case 69:
527
+ _context6.next = 71;
528
+ return bridge.applyPromotionCode(scanCode, promotionCustomerId);
529
+ case 71:
530
+ _context6.t2 = _context6.sent;
531
+ case 72:
532
+ promotionResult = _context6.t2;
467
533
  if (!((_promotionResult$isAc = promotionResult === null || promotionResult === void 0 ? void 0 : promotionResult.isAccepted) !== null && _promotionResult$isAc !== void 0 ? _promotionResult$isAc : promotionResult === null || promotionResult === void 0 ? void 0 : promotionResult.isAvailable)) {
468
- _context6.next = 49;
534
+ _context6.next = 75;
469
535
  break;
470
536
  }
471
537
  return _context6.abrupt("return", {
472
538
  status: 'success',
473
539
  kind: 'promotion'
474
540
  });
475
- case 49:
541
+ case 75:
542
+ if (!bindResult.customerBound) {
543
+ _context6.next = 77;
544
+ break;
545
+ }
546
+ return _context6.abrupt("return", {
547
+ status: 'success',
548
+ kind: 'customer'
549
+ });
550
+ case 77:
476
551
  return _context6.abrupt("return", {
477
552
  status: 'failed',
478
553
  reason: 'invalid_data'
479
554
  });
480
- case 50:
555
+ case 78:
481
556
  if (!(searchType === 'product' || searchType === 'local_product')) {
482
- _context6.next = 83;
557
+ _context6.next = 111;
483
558
  break;
484
559
  }
485
560
  list = data === null || data === void 0 ? void 0 : data.list;
486
561
  if (!(!Array.isArray(list) || list.length === 0)) {
487
- _context6.next = 55;
562
+ _context6.next = 83;
488
563
  break;
489
564
  }
490
- bridge === null || bridge === void 0 || (_bridge$onNotify10 = bridge.onNotify) === null || _bridge$onNotify10 === void 0 || _bridge$onNotify10.call(bridge, 'fail', 'pisell2.text.scan-global-failed');
565
+ bridge === null || bridge === void 0 || (_bridge$onNotify12 = bridge.onNotify) === null || _bridge$onNotify12 === void 0 || _bridge$onNotify12.call(bridge, 'fail', 'pisell2.text.scan-global-failed');
491
566
  return _context6.abrupt("return", {
492
567
  status: 'failed',
493
568
  reason: 'invalid_data'
494
569
  });
495
- case 55:
570
+ case 83:
496
571
  addedCount = 0;
497
572
  _iterator = _createForOfIteratorHelper(list);
498
- _context6.prev = 57;
573
+ _context6.prev = 85;
499
574
  _iterator.s();
500
- case 59:
575
+ case 87:
501
576
  if ((_step = _iterator.n()).done) {
502
- _context6.next = 71;
577
+ _context6.next = 99;
503
578
  break;
504
579
  }
505
580
  _item = _step.value;
506
- _context6.next = 63;
581
+ _context6.next = 91;
507
582
  return processScannedProductItem(host, _item, scanCode, bridge);
508
- case 63:
583
+ case 91:
509
584
  outcome = _context6.sent;
510
585
  if (outcome === 'added') {
511
586
  addedCount += 1;
512
587
  }
513
588
  if (!(outcome === 'cancelled')) {
514
- _context6.next = 67;
589
+ _context6.next = 95;
515
590
  break;
516
591
  }
517
592
  return _context6.abrupt("return", {
518
593
  status: 'cancelled'
519
594
  });
520
- case 67:
595
+ case 95:
521
596
  if (!(outcome === 'pending')) {
522
- _context6.next = 69;
597
+ _context6.next = 97;
523
598
  break;
524
599
  }
525
600
  return _context6.abrupt("return", {
526
601
  status: 'pending',
527
602
  kind: 'requiresDetail'
528
603
  });
529
- case 69:
530
- _context6.next = 59;
604
+ case 97:
605
+ _context6.next = 87;
531
606
  break;
532
- case 71:
533
- _context6.next = 76;
607
+ case 99:
608
+ _context6.next = 104;
534
609
  break;
535
- case 73:
536
- _context6.prev = 73;
537
- _context6.t1 = _context6["catch"](57);
538
- _iterator.e(_context6.t1);
539
- case 76:
540
- _context6.prev = 76;
610
+ case 101:
611
+ _context6.prev = 101;
612
+ _context6.t3 = _context6["catch"](85);
613
+ _iterator.e(_context6.t3);
614
+ case 104:
615
+ _context6.prev = 104;
541
616
  _iterator.f();
542
- return _context6.finish(76);
543
- case 79:
617
+ return _context6.finish(104);
618
+ case 107:
544
619
  if (!(addedCount > 0)) {
545
- _context6.next = 82;
620
+ _context6.next = 110;
546
621
  break;
547
622
  }
548
- bridge === null || bridge === void 0 || (_bridge$onNotify11 = bridge.onNotify) === null || _bridge$onNotify11 === void 0 || _bridge$onNotify11.call(bridge, 'success');
623
+ bridge === null || bridge === void 0 || (_bridge$onNotify13 = bridge.onNotify) === null || _bridge$onNotify13 === void 0 || _bridge$onNotify13.call(bridge, 'success');
549
624
  return _context6.abrupt("return", {
550
625
  status: 'success',
551
626
  kind: 'products',
@@ -553,36 +628,36 @@ function _applyGlobalScan() {
553
628
  count: addedCount
554
629
  }
555
630
  });
556
- case 82:
631
+ case 110:
557
632
  return _context6.abrupt("return", {
558
633
  status: 'failed',
559
634
  reason: 'no_bridge'
560
635
  });
561
- case 83:
636
+ case 111:
562
637
  if (!(searchType === 'order')) {
563
- _context6.next = 92;
638
+ _context6.next = 120;
564
639
  break;
565
640
  }
566
641
  orderId = (_data$order_id = data === null || data === void 0 ? void 0 : data.order_id) !== null && _data$order_id !== void 0 ? _data$order_id : data === null || data === void 0 ? void 0 : data.id;
567
642
  if (orderId) {
568
- _context6.next = 88;
643
+ _context6.next = 116;
569
644
  break;
570
645
  }
571
- bridge === null || bridge === void 0 || (_bridge$onNotify12 = bridge.onNotify) === null || _bridge$onNotify12 === void 0 || _bridge$onNotify12.call(bridge, 'fail', 'pisell2.text.scan-global-failed');
646
+ bridge === null || bridge === void 0 || (_bridge$onNotify14 = bridge.onNotify) === null || _bridge$onNotify14 === void 0 || _bridge$onNotify14.call(bridge, 'fail', 'pisell2.text.scan-global-failed');
572
647
  return _context6.abrupt("return", {
573
648
  status: 'failed',
574
649
  reason: 'invalid_data'
575
650
  });
576
- case 88:
651
+ case 116:
577
652
  if (bridge !== null && bridge !== void 0 && bridge.openOrder) {
578
- _context6.next = 90;
653
+ _context6.next = 118;
579
654
  break;
580
655
  }
581
656
  return _context6.abrupt("return", {
582
657
  status: 'pending',
583
658
  kind: 'openOrder'
584
659
  });
585
- case 90:
660
+ case 118:
586
661
  bridge.openOrder({
587
662
  order_id: Number(orderId),
588
663
  business_code: (_data$business_code = data === null || data === void 0 ? void 0 : data.business_code) !== null && _data$business_code !== void 0 ? _data$business_code : host.getBusinessCode()
@@ -591,16 +666,16 @@ function _applyGlobalScan() {
591
666
  status: 'pending',
592
667
  kind: 'openOrder'
593
668
  });
594
- case 92:
669
+ case 120:
595
670
  return _context6.abrupt("return", {
596
671
  status: 'failed',
597
672
  reason: 'invalid_data'
598
673
  });
599
- case 93:
674
+ case 121:
600
675
  case "end":
601
676
  return _context6.stop();
602
677
  }
603
- }, _callee6, null, [[11, 17], [57, 73, 76, 79]]);
678
+ }, _callee6, null, [[10, 16], [30, 37], [85, 101, 104, 107]]);
604
679
  }));
605
680
  return _applyGlobalScan.apply(this, arguments);
606
681
  }
@@ -18,7 +18,7 @@ export var searchWalletPass = /*#__PURE__*/function () {
18
18
  relation_product: 1,
19
19
  // 组装关联商品: 0不处理 1处理
20
20
  with_franchisor_data: 1,
21
- with: ['customer'],
21
+ with: ['customer', 'franchiseeWalletPass:shop_id,source_shop_id,product_id,use'],
22
22
  tags: ['point_card',
23
23
  // 积分卡
24
24
  'gift_card',
@@ -10,6 +10,8 @@ export interface GlobalScanFormattedResult {
10
10
  customerId?: string | number;
11
11
  /** 仅 Wallet 返回;true 时禁止直接使用响应内的来源客户。 */
12
12
  isCrossShopWallet?: boolean;
13
+ /** 总店 Wallet Pass 未共享给当前子店。 */
14
+ isWalletPassUnavailableAtStore?: boolean;
13
15
  }
14
16
  interface RawScanSearchResult {
15
17
  searchType?: GlobalScanSearchType;
@@ -1,3 +1,9 @@
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 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; }
3
+ 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; }
4
+ 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; }
5
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
6
+ 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); }
1
7
  /**
2
8
  * 全局扫码搜索结果格式化(对齐 ticketBooking `formatScanGlobal`)。
3
9
  */
@@ -33,14 +39,17 @@ export function formatGlobalScanResult(raw, scanCode) {
33
39
  };
34
40
  }
35
41
  if (searchType === 'walletPass') {
36
- var _ref2, _ref3, _firstResult$customer, _firstResult$holder, _firstResult$customer2, _firstResult$customer3;
42
+ var _firstResult$franchis, _ref2, _ref3, _firstResult$customer, _firstResult$holder, _firstResult$customer2, _firstResult$customer3;
37
43
  var firstResult = resultData === null || resultData === void 0 ? void 0 : resultData[0];
38
- return {
44
+ var isWalletPassUnavailableAtStore = (firstResult === null || firstResult === void 0 ? void 0 : firstResult.is_franchisor_pass) === 1 && (firstResult === null || firstResult === void 0 || (_firstResult$franchis = firstResult.franchisee_wallet_pass) === null || _firstResult$franchis === void 0 ? void 0 : _firstResult$franchis.use) !== 'enabled';
45
+ return _objectSpread({
39
46
  searchType: searchType,
40
47
  data: firstResult === null || firstResult === void 0 ? void 0 : firstResult.customer,
41
48
  scanCode: scanCode,
42
49
  customerId: (_ref2 = (_ref3 = (_firstResult$customer = firstResult === null || firstResult === void 0 ? void 0 : firstResult.customer_id) !== null && _firstResult$customer !== void 0 ? _firstResult$customer : firstResult === null || firstResult === void 0 || (_firstResult$holder = firstResult.holder) === null || _firstResult$holder === void 0 ? void 0 : _firstResult$holder.customer_id) !== null && _ref3 !== void 0 ? _ref3 : firstResult === null || firstResult === void 0 || (_firstResult$customer2 = firstResult.customer) === null || _firstResult$customer2 === void 0 ? void 0 : _firstResult$customer2.id) !== null && _ref2 !== void 0 ? _ref2 : firstResult === null || firstResult === void 0 || (_firstResult$customer3 = firstResult.customer) === null || _firstResult$customer3 === void 0 ? void 0 : _firstResult$customer3.customer_id
43
- };
50
+ }, isWalletPassUnavailableAtStore ? {
51
+ isWalletPassUnavailableAtStore: true
52
+ } : {});
44
53
  }
45
54
  if (searchType === 'product' || searchType === 'local_product') {
46
55
  return {
@@ -1,46 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- Object.defineProperty(exports, "BUY_X_GET_Y_FREE_STRATEGY", {
7
- enumerable: true,
8
- get: function () {
9
- return _examples.BUY_X_GET_Y_FREE_STRATEGY;
10
- }
11
- });
12
- Object.defineProperty(exports, "ITEM_REWARD_STRATEGY", {
13
- enumerable: true,
14
- get: function () {
15
- return _examples.ITEM_REWARD_STRATEGY;
16
- }
17
- });
18
- Object.defineProperty(exports, "PromotionAdapter", {
19
- enumerable: true,
20
- get: function () {
21
- return _adapter.PromotionAdapter;
22
- }
23
- });
24
- Object.defineProperty(exports, "PromotionEvaluator", {
25
- enumerable: true,
26
- get: function () {
27
- return _evaluator.PromotionEvaluator;
28
- }
29
- });
30
- Object.defineProperty(exports, "X_ITEMS_FOR_Y_PRICE_STRATEGY", {
31
- enumerable: true,
32
- get: function () {
33
- return _examples.X_ITEMS_FOR_Y_PRICE_STRATEGY;
34
- }
35
- });
36
- Object.defineProperty(exports, "default", {
37
- enumerable: true,
38
- get: function () {
39
- return _adapter.default;
40
- }
41
- });
42
- var _evaluator = require("./evaluator");
43
- var _adapter = _interopRequireWildcard(require("./adapter"));
44
- var _examples = require("./examples");
45
- function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
46
- function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
1
+ "use strict";
@@ -540,7 +540,7 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
540
540
  generateIdempotencyToken(): string;
541
541
  syncPaymentsToOrder<T = any>(params: SyncPaymentsToOrderParams): Promise<SyncPaymentsToOrderResult<T>>;
542
542
  createOrder(params: CommitOrderParams['query']): {
543
- type: "virtual" | "appointment_booking";
543
+ type: "appointment_booking" | "virtual";
544
544
  platform: string;
545
545
  sales_channel: string;
546
546
  order_sales_channel: string;
@@ -1501,7 +1501,8 @@ class RulesModule extends _BaseModule.BaseModule {
1501
1501
 
1502
1502
  // 计算折扣后的价格(使用 getDiscountAmount,内部已处理 maxDeductionAmount)
1503
1503
  const discountedPrice = (0, _utils.getDiscountAmount)(selectedDiscount, product.origin_total, product.origin_total);
1504
- const bundleDiscountAmount = new _decimal.default(product.origin_total || 0).minus(discountedPrice).toNumber();
1504
+ const bundleDiscountAmountPerItem = new _decimal.default(product.origin_total || 0).minus(discountedPrice).toNumber();
1505
+ const bundleDiscountAmount = new _decimal.default(bundleDiscountAmountPerItem).mul(appliedUseCount).toNumber();
1505
1506
  debugger;
1506
1507
  const discountDetail = {
1507
1508
  amount: bundleDiscountAmount,
@@ -326,7 +326,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
326
326
  date: string;
327
327
  status: string;
328
328
  week: string;
329
- weekNum: 0 | 1 | 2 | 3 | 4 | 5 | 6;
329
+ weekNum: 0 | 2 | 1 | 3 | 4 | 5 | 6;
330
330
  }[]>;
331
331
  submitTimeSlot(timeSlots: TimeSliceItem): void;
332
332
  private getScheduleDataByIds;
@@ -230,12 +230,16 @@ export interface GlobalScanHostBridge {
230
230
  /**
231
231
  * walk-in 扫 walletPass:直接核销优惠码(对齐 SaleDetail Voucher.handleApplyCode / cart.scanCode)。
232
232
  */
233
- applyPromotionCode?: (code: string, customerId?: number) => Promise<{
233
+ applyPromotionCode?: (code: string, customerId?: number, options?: {
234
+ suppressFailureNotification?: boolean;
235
+ }) => Promise<{
234
236
  isAvailable?: boolean;
235
237
  isAccepted?: boolean;
236
238
  type?: string;
237
239
  unavailableReason?: string;
238
240
  }>;
241
+ /** 当前订单已有其他客户时,由宿主复用客户组件完成确认及切换。 */
242
+ requestCustomerSwitch?: (customer: ICustomer) => Promise<boolean | null>;
239
243
  onNotify?: (type: 'success' | 'fail' | 'info', messageKey?: string) => void;
240
244
  refresh?: () => void;
241
245
  }
@@ -106,16 +106,12 @@ async function applyGlobalScan(host, formatted, bridge) {
106
106
  data,
107
107
  scanCode,
108
108
  customerId: formattedCustomerId,
109
- isCrossShopWallet
109
+ isCrossShopWallet,
110
+ isWalletPassUnavailableAtStore
110
111
  } = formatted;
111
112
  if (searchType === 'wallet') {
112
113
  const currentCustomer = host.getOrderCustomerSnapshot();
113
- if (getRealCustomerId(currentCustomer) !== undefined) {
114
- return {
115
- status: 'success',
116
- kind: 'customer'
117
- };
118
- }
114
+ const currentCustomerId = getRealCustomerId(currentCustomer);
119
115
  let customer = data;
120
116
  if (isCrossShopWallet) {
121
117
  const sourceCustomerId = getRealCustomerId({
@@ -152,6 +148,36 @@ async function applyGlobalScan(host, formatted, bridge) {
152
148
  ...customer,
153
149
  id: customerId
154
150
  } : customer;
151
+ if (currentCustomerId === customerId) {
152
+ return {
153
+ status: 'success',
154
+ kind: 'customer'
155
+ };
156
+ }
157
+ if (currentCustomerId !== undefined) {
158
+ // 未接入新桥接的宿主保持原行为:已有客户时不直接覆盖。
159
+ if (!bridge?.requestCustomerSwitch) {
160
+ return {
161
+ status: 'success',
162
+ kind: 'customer'
163
+ };
164
+ }
165
+ try {
166
+ const switched = await bridge.requestCustomerSwitch(orderCustomer);
167
+ return switched ? {
168
+ status: 'success',
169
+ kind: 'customer'
170
+ } : {
171
+ status: 'cancelled'
172
+ };
173
+ } catch (error) {
174
+ bridge.onNotify?.('fail', getErrorMessage(error) || 'pisell2.text.scan-global-failed');
175
+ return {
176
+ status: 'failed',
177
+ reason: 'invalid_data'
178
+ };
179
+ }
180
+ }
155
181
  host.setOrderCustomer(orderCustomer);
156
182
  bridge?.onNotify?.('success', 'pisell2.text.add-client-success');
157
183
  return {
@@ -160,13 +186,20 @@ async function applyGlobalScan(host, formatted, bridge) {
160
186
  };
161
187
  }
162
188
  if (searchType === 'walletPass') {
189
+ if (isWalletPassUnavailableAtStore) {
190
+ bridge?.onNotify?.('fail', 'pisell2.text.wallet-pass-not-available-at-store');
191
+ return {
192
+ status: 'failed',
193
+ reason: 'invalid_data'
194
+ };
195
+ }
163
196
  const snapshot = host.getOrderCustomerSnapshot();
164
- const currentCustomerIsWalkIn = getRealCustomerId(snapshot) === undefined;
165
197
  let activeCustomer = snapshot;
166
198
  const bindWalletPassCustomer = async asset => {
167
- if (!currentCustomerIsWalkIn) {
199
+ if (getRealCustomerId(activeCustomer) !== undefined) {
168
200
  return {
169
- resolveFailed: false
201
+ resolveFailed: false,
202
+ customerBound: false
170
203
  };
171
204
  }
172
205
  const assetCustomerId = getWalletAssetCustomerId(asset) ?? getRealCustomerId({
@@ -177,7 +210,8 @@ async function applyGlobalScan(host, formatted, bridge) {
177
210
  if (!host.resolveCustomerById) {
178
211
  bridge?.onNotify?.('fail', 'pisell2.text.scan-global-failed');
179
212
  return {
180
- resolveFailed: true
213
+ resolveFailed: true,
214
+ customerBound: false
181
215
  };
182
216
  }
183
217
  try {
@@ -186,7 +220,8 @@ async function applyGlobalScan(host, formatted, bridge) {
186
220
  console.warn('[GlobalScan] Wallet asset customer lookup failed', error);
187
221
  bridge?.onNotify?.('fail', getErrorMessage(error) || 'pisell2.text.scan-global-failed');
188
222
  return {
189
- resolveFailed: true
223
+ resolveFailed: true,
224
+ customerBound: false
190
225
  };
191
226
  }
192
227
  }
@@ -196,7 +231,8 @@ async function applyGlobalScan(host, formatted, bridge) {
196
231
  bridge?.onNotify?.('fail', 'pisell2.text.scan-global-failed');
197
232
  }
198
233
  return {
199
- resolveFailed: assetCustomerId !== undefined
234
+ resolveFailed: assetCustomerId !== undefined,
235
+ customerBound: false
200
236
  };
201
237
  }
202
238
  const orderCustomer = customer.id === undefined || customer.id === null ? {
@@ -210,7 +246,8 @@ async function applyGlobalScan(host, formatted, bridge) {
210
246
  retainSearchResultCodes: [scanCode]
211
247
  });
212
248
  return {
213
- resolveFailed: false
249
+ resolveFailed: false,
250
+ customerBound: true
214
251
  };
215
252
  };
216
253
  const trySelectWalletAsset = async () => {
@@ -242,24 +279,34 @@ async function applyGlobalScan(host, formatted, bridge) {
242
279
  reason: 'invalid_data'
243
280
  };
244
281
  };
282
+
283
+ // batch-search 可能返回来源门店客户;先映射到当前门店,确保 Wallet
284
+ // 支付资产查询使用本店客户上下文。
285
+ const bindResult = await bindWalletPassCustomer();
245
286
  const walletSelection = await trySelectWalletAsset();
246
287
  if (walletSelection) return walletSelection;
247
-
248
- // 非支付类 Wallet Pass 仍可能由 batch-search 返回所属客户。
249
- await bindWalletPassCustomer();
250
288
  if (!bridge?.applyPromotionCode) {
251
289
  return {
252
290
  status: 'failed',
253
291
  reason: 'no_bridge'
254
292
  };
255
293
  }
256
- const promotionResult = await bridge.applyPromotionCode(scanCode, getRealCustomerId(activeCustomer));
294
+ const promotionCustomerId = getRealCustomerId(activeCustomer);
295
+ const promotionResult = bindResult.customerBound ? await bridge.applyPromotionCode(scanCode, promotionCustomerId, {
296
+ suppressFailureNotification: true
297
+ }) : await bridge.applyPromotionCode(scanCode, promotionCustomerId);
257
298
  if (promotionResult?.isAccepted ?? promotionResult?.isAvailable) {
258
299
  return {
259
300
  status: 'success',
260
301
  kind: 'promotion'
261
302
  };
262
303
  }
304
+ if (bindResult.customerBound) {
305
+ return {
306
+ status: 'success',
307
+ kind: 'customer'
308
+ };
309
+ }
263
310
  return {
264
311
  status: 'failed',
265
312
  reason: 'invalid_data'
@@ -15,7 +15,7 @@ const searchWalletPass = async (request, code) => {
15
15
  relation_product: 1,
16
16
  // 组装关联商品: 0不处理 1处理
17
17
  with_franchisor_data: 1,
18
- with: ['customer'],
18
+ with: ['customer', 'franchiseeWalletPass:shop_id,source_shop_id,product_id,use'],
19
19
  tags: ['point_card',
20
20
  // 积分卡
21
21
  'gift_card',
@@ -10,6 +10,8 @@ export interface GlobalScanFormattedResult {
10
10
  customerId?: string | number;
11
11
  /** 仅 Wallet 返回;true 时禁止直接使用响应内的来源客户。 */
12
12
  isCrossShopWallet?: boolean;
13
+ /** 总店 Wallet Pass 未共享给当前子店。 */
14
+ isWalletPassUnavailableAtStore?: boolean;
13
15
  }
14
16
  interface RawScanSearchResult {
15
17
  searchType?: GlobalScanSearchType;
@@ -43,11 +43,15 @@ function formatGlobalScanResult(raw, scanCode) {
43
43
  }
44
44
  if (searchType === 'walletPass') {
45
45
  const firstResult = resultData?.[0];
46
+ const isWalletPassUnavailableAtStore = firstResult?.is_franchisor_pass === 1 && firstResult?.franchisee_wallet_pass?.use !== 'enabled';
46
47
  return {
47
48
  searchType,
48
49
  data: firstResult?.customer,
49
50
  scanCode,
50
- customerId: firstResult?.customer_id ?? firstResult?.holder?.customer_id ?? firstResult?.customer?.id ?? firstResult?.customer?.customer_id
51
+ customerId: firstResult?.customer_id ?? firstResult?.holder?.customer_id ?? firstResult?.customer?.id ?? firstResult?.customer?.customer_id,
52
+ ...(isWalletPassUnavailableAtStore ? {
53
+ isWalletPassUnavailableAtStore: true
54
+ } : {})
51
55
  };
52
56
  }
53
57
  if (searchType === 'product' || searchType === 'local_product') {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "0.10.42",
4
+ "version": "0.10.43",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",