@pisell/pisellos 0.10.68 → 0.10.70
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/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +5 -4
- package/dist/modules/Holder/utils.d.ts +2 -0
- package/dist/modules/Holder/utils.js +32 -2
- package/dist/modules/Rules/index.js +59 -58
- package/dist/server/modules/products/index.js +3 -2
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +3 -2
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.js +177 -112
- package/dist/solution/BookingTicket/types.d.ts +14 -4
- package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.js +94 -58
- package/dist/solution/BookingTicket/utils/scan/applyProductVoucherCollectionScan.d.ts +10 -0
- package/dist/solution/BookingTicket/utils/scan/applyProductVoucherCollectionScan.js +117 -0
- package/lib/model/strategy/adapter/promotion/index.js +46 -1
- package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +2 -1
- package/lib/modules/Holder/utils.d.ts +2 -0
- package/lib/modules/Holder/utils.js +27 -1
- package/lib/modules/Rules/index.js +2 -1
- package/lib/server/modules/products/index.js +2 -1
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +9 -8
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.js +22 -2
- package/lib/solution/BookingTicket/types.d.ts +14 -4
- package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.js +14 -2
- package/lib/solution/BookingTicket/utils/scan/applyProductVoucherCollectionScan.d.ts +10 -0
- package/lib/solution/BookingTicket/utils/scan/applyProductVoucherCollectionScan.js +71 -0
- package/package.json +1 -1
|
@@ -210,7 +210,7 @@ export function applyGlobalScan(_x14, _x15, _x16) {
|
|
|
210
210
|
}
|
|
211
211
|
function _applyGlobalScan() {
|
|
212
212
|
_applyGlobalScan = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(host, formatted, bridge) {
|
|
213
|
-
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;
|
|
213
|
+
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, _collectionPromotion$, _promotionResult$isAc, _bridge$onNotify6, snapshot, activeCustomer, bindWalletPassCustomer, trySelectWalletAsset, bindResult, collectionPromotion, walletSelection, promotionCustomerId, promotionResult, list, _bridge$onNotify12, addedCount, _iterator, _step, _item, outcome, _bridge$onNotify13, _data$order_id, _data$business_code, orderId, _bridge$onNotify14;
|
|
214
214
|
return _regeneratorRuntime().wrap(function _callee6$(_context6) {
|
|
215
215
|
while (1) switch (_context6.prev = _context6.next) {
|
|
216
216
|
case 0:
|
|
@@ -321,7 +321,7 @@ function _applyGlobalScan() {
|
|
|
321
321
|
});
|
|
322
322
|
case 44:
|
|
323
323
|
if (!(searchType === 'walletPass')) {
|
|
324
|
-
_context6.next =
|
|
324
|
+
_context6.next = 93;
|
|
325
325
|
break;
|
|
326
326
|
}
|
|
327
327
|
if (!isWalletPassUnavailableAtStore) {
|
|
@@ -495,75 +495,111 @@ function _applyGlobalScan() {
|
|
|
495
495
|
return bindWalletPassCustomer();
|
|
496
496
|
case 54:
|
|
497
497
|
bindResult = _context6.sent;
|
|
498
|
-
|
|
498
|
+
if (!((bridge === null || bridge === void 0 ? void 0 : bridge.scanScope) === 'product-voucher-collection' && bridge.applyPromotionCode)) {
|
|
499
|
+
_context6.next = 61;
|
|
500
|
+
break;
|
|
501
|
+
}
|
|
502
|
+
_context6.next = 58;
|
|
503
|
+
return bridge.applyPromotionCode(scanCode, getRealCustomerId(activeCustomer), {
|
|
504
|
+
suppressFailureNotification: true,
|
|
505
|
+
productVouchersOnly: true
|
|
506
|
+
});
|
|
507
|
+
case 58:
|
|
508
|
+
_context6.t2 = _context6.sent;
|
|
509
|
+
_context6.next = 62;
|
|
510
|
+
break;
|
|
511
|
+
case 61:
|
|
512
|
+
_context6.t2 = undefined;
|
|
513
|
+
case 62:
|
|
514
|
+
collectionPromotion = _context6.t2;
|
|
515
|
+
if (!((_collectionPromotion$ = collectionPromotion === null || collectionPromotion === void 0 ? void 0 : collectionPromotion.isAccepted) !== null && _collectionPromotion$ !== void 0 ? _collectionPromotion$ : collectionPromotion === null || collectionPromotion === void 0 ? void 0 : collectionPromotion.isAvailable)) {
|
|
516
|
+
_context6.next = 65;
|
|
517
|
+
break;
|
|
518
|
+
}
|
|
519
|
+
return _context6.abrupt("return", {
|
|
520
|
+
status: 'success',
|
|
521
|
+
kind: 'promotion'
|
|
522
|
+
});
|
|
523
|
+
case 65:
|
|
524
|
+
_context6.next = 67;
|
|
499
525
|
return trySelectWalletAsset();
|
|
500
|
-
case
|
|
526
|
+
case 67:
|
|
501
527
|
walletSelection = _context6.sent;
|
|
502
528
|
if (!walletSelection) {
|
|
503
|
-
_context6.next =
|
|
529
|
+
_context6.next = 70;
|
|
504
530
|
break;
|
|
505
531
|
}
|
|
506
532
|
return _context6.abrupt("return", walletSelection);
|
|
507
|
-
case
|
|
533
|
+
case 70:
|
|
508
534
|
if (bridge !== null && bridge !== void 0 && bridge.applyPromotionCode) {
|
|
509
|
-
_context6.next =
|
|
535
|
+
_context6.next = 72;
|
|
510
536
|
break;
|
|
511
537
|
}
|
|
512
538
|
return _context6.abrupt("return", {
|
|
513
539
|
status: 'failed',
|
|
514
540
|
reason: 'no_bridge'
|
|
515
541
|
});
|
|
516
|
-
case
|
|
542
|
+
case 72:
|
|
517
543
|
promotionCustomerId = getRealCustomerId(activeCustomer);
|
|
544
|
+
if (!(collectionPromotion !== null && collectionPromotion !== void 0)) {
|
|
545
|
+
_context6.next = 77;
|
|
546
|
+
break;
|
|
547
|
+
}
|
|
548
|
+
_context6.t3 = collectionPromotion;
|
|
549
|
+
_context6.next = 87;
|
|
550
|
+
break;
|
|
551
|
+
case 77:
|
|
518
552
|
if (!bindResult.customerBound) {
|
|
519
|
-
_context6.next =
|
|
553
|
+
_context6.next = 83;
|
|
520
554
|
break;
|
|
521
555
|
}
|
|
522
|
-
_context6.next =
|
|
556
|
+
_context6.next = 80;
|
|
523
557
|
return bridge.applyPromotionCode(scanCode, promotionCustomerId, {
|
|
524
558
|
suppressFailureNotification: true
|
|
525
559
|
});
|
|
526
|
-
case
|
|
527
|
-
_context6.
|
|
528
|
-
_context6.next =
|
|
560
|
+
case 80:
|
|
561
|
+
_context6.t4 = _context6.sent;
|
|
562
|
+
_context6.next = 86;
|
|
529
563
|
break;
|
|
530
|
-
case
|
|
531
|
-
_context6.next =
|
|
564
|
+
case 83:
|
|
565
|
+
_context6.next = 85;
|
|
532
566
|
return bridge.applyPromotionCode(scanCode, promotionCustomerId);
|
|
533
|
-
case
|
|
534
|
-
_context6.
|
|
535
|
-
case
|
|
536
|
-
|
|
567
|
+
case 85:
|
|
568
|
+
_context6.t4 = _context6.sent;
|
|
569
|
+
case 86:
|
|
570
|
+
_context6.t3 = _context6.t4;
|
|
571
|
+
case 87:
|
|
572
|
+
promotionResult = _context6.t3;
|
|
537
573
|
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)) {
|
|
538
|
-
_context6.next =
|
|
574
|
+
_context6.next = 90;
|
|
539
575
|
break;
|
|
540
576
|
}
|
|
541
577
|
return _context6.abrupt("return", {
|
|
542
578
|
status: 'success',
|
|
543
579
|
kind: 'promotion'
|
|
544
580
|
});
|
|
545
|
-
case
|
|
581
|
+
case 90:
|
|
546
582
|
if (!bindResult.customerBound) {
|
|
547
|
-
_context6.next =
|
|
583
|
+
_context6.next = 92;
|
|
548
584
|
break;
|
|
549
585
|
}
|
|
550
586
|
return _context6.abrupt("return", {
|
|
551
587
|
status: 'success',
|
|
552
588
|
kind: 'customer'
|
|
553
589
|
});
|
|
554
|
-
case
|
|
590
|
+
case 92:
|
|
555
591
|
return _context6.abrupt("return", {
|
|
556
592
|
status: 'failed',
|
|
557
593
|
reason: 'invalid_data'
|
|
558
594
|
});
|
|
559
|
-
case
|
|
595
|
+
case 93:
|
|
560
596
|
if (!(searchType === 'product' || searchType === 'local_product')) {
|
|
561
|
-
_context6.next =
|
|
597
|
+
_context6.next = 126;
|
|
562
598
|
break;
|
|
563
599
|
}
|
|
564
600
|
list = data === null || data === void 0 ? void 0 : data.list;
|
|
565
601
|
if (!(!Array.isArray(list) || list.length === 0)) {
|
|
566
|
-
_context6.next =
|
|
602
|
+
_context6.next = 98;
|
|
567
603
|
break;
|
|
568
604
|
}
|
|
569
605
|
bridge === null || bridge === void 0 || (_bridge$onNotify12 = bridge.onNotify) === null || _bridge$onNotify12 === void 0 || _bridge$onNotify12.call(bridge, 'fail', 'pisell2.text.scan-global-failed');
|
|
@@ -571,57 +607,57 @@ function _applyGlobalScan() {
|
|
|
571
607
|
status: 'failed',
|
|
572
608
|
reason: 'invalid_data'
|
|
573
609
|
});
|
|
574
|
-
case
|
|
610
|
+
case 98:
|
|
575
611
|
addedCount = 0;
|
|
576
612
|
_iterator = _createForOfIteratorHelper(list);
|
|
577
|
-
_context6.prev =
|
|
613
|
+
_context6.prev = 100;
|
|
578
614
|
_iterator.s();
|
|
579
|
-
case
|
|
615
|
+
case 102:
|
|
580
616
|
if ((_step = _iterator.n()).done) {
|
|
581
|
-
_context6.next =
|
|
617
|
+
_context6.next = 114;
|
|
582
618
|
break;
|
|
583
619
|
}
|
|
584
620
|
_item = _step.value;
|
|
585
|
-
_context6.next =
|
|
621
|
+
_context6.next = 106;
|
|
586
622
|
return processScannedProductItem(host, _item, scanCode, bridge);
|
|
587
|
-
case
|
|
623
|
+
case 106:
|
|
588
624
|
outcome = _context6.sent;
|
|
589
625
|
if (outcome === 'added') {
|
|
590
626
|
addedCount += 1;
|
|
591
627
|
}
|
|
592
628
|
if (!(outcome === 'cancelled')) {
|
|
593
|
-
_context6.next =
|
|
629
|
+
_context6.next = 110;
|
|
594
630
|
break;
|
|
595
631
|
}
|
|
596
632
|
return _context6.abrupt("return", {
|
|
597
633
|
status: 'cancelled'
|
|
598
634
|
});
|
|
599
|
-
case
|
|
635
|
+
case 110:
|
|
600
636
|
if (!(outcome === 'pending')) {
|
|
601
|
-
_context6.next =
|
|
637
|
+
_context6.next = 112;
|
|
602
638
|
break;
|
|
603
639
|
}
|
|
604
640
|
return _context6.abrupt("return", {
|
|
605
641
|
status: 'pending',
|
|
606
642
|
kind: 'requiresDetail'
|
|
607
643
|
});
|
|
608
|
-
case
|
|
609
|
-
_context6.next =
|
|
644
|
+
case 112:
|
|
645
|
+
_context6.next = 102;
|
|
610
646
|
break;
|
|
611
|
-
case
|
|
612
|
-
_context6.next =
|
|
647
|
+
case 114:
|
|
648
|
+
_context6.next = 119;
|
|
613
649
|
break;
|
|
614
|
-
case
|
|
615
|
-
_context6.prev =
|
|
616
|
-
_context6.
|
|
617
|
-
_iterator.e(_context6.
|
|
618
|
-
case
|
|
619
|
-
_context6.prev =
|
|
650
|
+
case 116:
|
|
651
|
+
_context6.prev = 116;
|
|
652
|
+
_context6.t5 = _context6["catch"](100);
|
|
653
|
+
_iterator.e(_context6.t5);
|
|
654
|
+
case 119:
|
|
655
|
+
_context6.prev = 119;
|
|
620
656
|
_iterator.f();
|
|
621
|
-
return _context6.finish(
|
|
622
|
-
case
|
|
657
|
+
return _context6.finish(119);
|
|
658
|
+
case 122:
|
|
623
659
|
if (!(addedCount > 0)) {
|
|
624
|
-
_context6.next =
|
|
660
|
+
_context6.next = 125;
|
|
625
661
|
break;
|
|
626
662
|
}
|
|
627
663
|
bridge === null || bridge === void 0 || (_bridge$onNotify13 = bridge.onNotify) === null || _bridge$onNotify13 === void 0 || _bridge$onNotify13.call(bridge, 'success');
|
|
@@ -632,19 +668,19 @@ function _applyGlobalScan() {
|
|
|
632
668
|
count: addedCount
|
|
633
669
|
}
|
|
634
670
|
});
|
|
635
|
-
case
|
|
671
|
+
case 125:
|
|
636
672
|
return _context6.abrupt("return", {
|
|
637
673
|
status: 'failed',
|
|
638
674
|
reason: 'no_bridge'
|
|
639
675
|
});
|
|
640
|
-
case
|
|
676
|
+
case 126:
|
|
641
677
|
if (!(searchType === 'order')) {
|
|
642
|
-
_context6.next =
|
|
678
|
+
_context6.next = 135;
|
|
643
679
|
break;
|
|
644
680
|
}
|
|
645
681
|
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;
|
|
646
682
|
if (orderId) {
|
|
647
|
-
_context6.next =
|
|
683
|
+
_context6.next = 131;
|
|
648
684
|
break;
|
|
649
685
|
}
|
|
650
686
|
bridge === null || bridge === void 0 || (_bridge$onNotify14 = bridge.onNotify) === null || _bridge$onNotify14 === void 0 || _bridge$onNotify14.call(bridge, 'fail', 'pisell2.text.scan-global-failed');
|
|
@@ -652,16 +688,16 @@ function _applyGlobalScan() {
|
|
|
652
688
|
status: 'failed',
|
|
653
689
|
reason: 'invalid_data'
|
|
654
690
|
});
|
|
655
|
-
case
|
|
691
|
+
case 131:
|
|
656
692
|
if (bridge !== null && bridge !== void 0 && bridge.openOrder) {
|
|
657
|
-
_context6.next =
|
|
693
|
+
_context6.next = 133;
|
|
658
694
|
break;
|
|
659
695
|
}
|
|
660
696
|
return _context6.abrupt("return", {
|
|
661
697
|
status: 'pending',
|
|
662
698
|
kind: 'openOrder'
|
|
663
699
|
});
|
|
664
|
-
case
|
|
700
|
+
case 133:
|
|
665
701
|
bridge.openOrder({
|
|
666
702
|
order_id: Number(orderId),
|
|
667
703
|
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()
|
|
@@ -670,16 +706,16 @@ function _applyGlobalScan() {
|
|
|
670
706
|
status: 'pending',
|
|
671
707
|
kind: 'openOrder'
|
|
672
708
|
});
|
|
673
|
-
case
|
|
709
|
+
case 135:
|
|
674
710
|
return _context6.abrupt("return", {
|
|
675
711
|
status: 'failed',
|
|
676
712
|
reason: 'invalid_data'
|
|
677
713
|
});
|
|
678
|
-
case
|
|
714
|
+
case 136:
|
|
679
715
|
case "end":
|
|
680
716
|
return _context6.stop();
|
|
681
717
|
}
|
|
682
|
-
}, _callee6, null, [[10, 16], [30, 37], [
|
|
718
|
+
}, _callee6, null, [[10, 16], [30, 37], [100, 116, 119, 122]]);
|
|
683
719
|
}));
|
|
684
720
|
return _applyGlobalScan.apply(this, arguments);
|
|
685
721
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { GlobalScanHandleResult, GlobalScanHostBridge } from '../../types';
|
|
2
|
+
import { type GlobalScanApplyHost } from './applyGlobalScan';
|
|
3
|
+
import type { GlobalScanFormattedResult } from './formatGlobalScan';
|
|
4
|
+
export interface ProductVoucherCollectionScanHost extends GlobalScanApplyHost {
|
|
5
|
+
waitForCustomerDiscounts(): Promise<void>;
|
|
6
|
+
loadCustomerDiscounts(): Promise<Record<string, any>[]>;
|
|
7
|
+
}
|
|
8
|
+
/** Collect voucher candidates after customer binding and coupon loading finish.
|
|
9
|
+
* Never expand a wristband's result to other orders of the same customer. */
|
|
10
|
+
export declare function applyProductVoucherCollectionScan(host: ProductVoucherCollectionScanHost, formatted: GlobalScanFormattedResult, bridge: GlobalScanHostBridge): Promise<GlobalScanHandleResult>;
|
|
@@ -0,0 +1,117 @@
|
|
|
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 _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
|
|
3
|
+
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; }
|
|
4
|
+
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; }
|
|
5
|
+
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; }
|
|
6
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
7
|
+
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); }
|
|
8
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
9
|
+
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
10
|
+
import { applyGlobalScan } from "./applyGlobalScan";
|
|
11
|
+
/** Collect voucher candidates after customer binding and coupon loading finish.
|
|
12
|
+
* Never expand a wristband's result to other orders of the same customer. */
|
|
13
|
+
export function applyProductVoucherCollectionScan(_x, _x2, _x3) {
|
|
14
|
+
return _applyProductVoucherCollectionScan.apply(this, arguments);
|
|
15
|
+
}
|
|
16
|
+
function _applyProductVoucherCollectionScan() {
|
|
17
|
+
_applyProductVoucherCollectionScan = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(host, formatted, bridge) {
|
|
18
|
+
var assertCurrent, vouchers, result;
|
|
19
|
+
return _regeneratorRuntime().wrap(function _callee2$(_context2) {
|
|
20
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
21
|
+
case 0:
|
|
22
|
+
assertCurrent = function assertCurrent() {
|
|
23
|
+
var _bridge$isCurrent;
|
|
24
|
+
if (((_bridge$isCurrent = bridge.isCurrent) === null || _bridge$isCurrent === void 0 ? void 0 : _bridge$isCurrent.call(bridge)) === false) {
|
|
25
|
+
throw new DOMException('Scan session ended', 'AbortError');
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
vouchers = [];
|
|
29
|
+
assertCurrent();
|
|
30
|
+
_context2.next = 5;
|
|
31
|
+
return applyGlobalScan(_objectSpread(_objectSpread({}, host), {}, {
|
|
32
|
+
setOrderCustomer: function setOrderCustomer(customer) {
|
|
33
|
+
assertCurrent();
|
|
34
|
+
host.setOrderCustomer(customer);
|
|
35
|
+
},
|
|
36
|
+
addProductToOrder: function addProductToOrder(product, booking) {
|
|
37
|
+
assertCurrent();
|
|
38
|
+
return host.addProductToOrder(product, booking);
|
|
39
|
+
}
|
|
40
|
+
}), formatted, _objectSpread(_objectSpread({}, bridge), {}, {
|
|
41
|
+
applyPromotionCode: bridge.applyPromotionCode && ( /*#__PURE__*/function () {
|
|
42
|
+
var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(code, customerId, options) {
|
|
43
|
+
var promotion;
|
|
44
|
+
return _regeneratorRuntime().wrap(function _callee$(_context) {
|
|
45
|
+
while (1) switch (_context.prev = _context.next) {
|
|
46
|
+
case 0:
|
|
47
|
+
_context.next = 2;
|
|
48
|
+
return host.waitForCustomerDiscounts();
|
|
49
|
+
case 2:
|
|
50
|
+
assertCurrent();
|
|
51
|
+
_context.next = 5;
|
|
52
|
+
return bridge.applyPromotionCode(code, customerId, _objectSpread(_objectSpread({}, options), {}, {
|
|
53
|
+
productVouchersOnly: true,
|
|
54
|
+
suppressFailureNotification: true
|
|
55
|
+
}));
|
|
56
|
+
case 5:
|
|
57
|
+
promotion = _context.sent;
|
|
58
|
+
assertCurrent();
|
|
59
|
+
// An empty successful search is different from a swallowed request error.
|
|
60
|
+
if (Array.isArray(promotion.scannedDiscountList)) {
|
|
61
|
+
_context.next = 9;
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
throw new Error('Could not resolve scanned vouchers');
|
|
65
|
+
case 9:
|
|
66
|
+
vouchers = promotion.scannedDiscountList;
|
|
67
|
+
return _context.abrupt("return", promotion);
|
|
68
|
+
case 11:
|
|
69
|
+
case "end":
|
|
70
|
+
return _context.stop();
|
|
71
|
+
}
|
|
72
|
+
}, _callee);
|
|
73
|
+
}));
|
|
74
|
+
return function (_x4, _x5, _x6) {
|
|
75
|
+
return _ref.apply(this, arguments);
|
|
76
|
+
};
|
|
77
|
+
}())
|
|
78
|
+
}));
|
|
79
|
+
case 5:
|
|
80
|
+
result = _context2.sent;
|
|
81
|
+
assertCurrent();
|
|
82
|
+
if (!(formatted.searchType === 'wallet' && result.status === 'success')) {
|
|
83
|
+
_context2.next = 13;
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
_context2.next = 10;
|
|
87
|
+
return host.loadCustomerDiscounts();
|
|
88
|
+
case 10:
|
|
89
|
+
vouchers = _context2.sent;
|
|
90
|
+
assertCurrent();
|
|
91
|
+
return _context2.abrupt("return", _objectSpread(_objectSpread({}, result), {}, {
|
|
92
|
+
redemption: {
|
|
93
|
+
source: 'wallet',
|
|
94
|
+
vouchers: vouchers
|
|
95
|
+
}
|
|
96
|
+
}));
|
|
97
|
+
case 13:
|
|
98
|
+
if (!(formatted.searchType === 'walletPass')) {
|
|
99
|
+
_context2.next = 15;
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
return _context2.abrupt("return", _objectSpread(_objectSpread({}, result), {}, {
|
|
103
|
+
redemption: {
|
|
104
|
+
source: 'scan',
|
|
105
|
+
vouchers: vouchers
|
|
106
|
+
}
|
|
107
|
+
}));
|
|
108
|
+
case 15:
|
|
109
|
+
return _context2.abrupt("return", result);
|
|
110
|
+
case 16:
|
|
111
|
+
case "end":
|
|
112
|
+
return _context2.stop();
|
|
113
|
+
}
|
|
114
|
+
}, _callee2);
|
|
115
|
+
}));
|
|
116
|
+
return _applyProductVoucherCollectionScan.apply(this, arguments);
|
|
117
|
+
}
|
|
@@ -1 +1,46 @@
|
|
|
1
|
-
"use strict";
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "BUY_X_GET_Y_FREE_STRATEGY", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _examples.BUY_X_GET_Y_FREE_STRATEGY;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(exports, "ITEM_REWARD_STRATEGY", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () {
|
|
15
|
+
return _examples.ITEM_REWARD_STRATEGY;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
Object.defineProperty(exports, "PromotionAdapter", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () {
|
|
21
|
+
return _adapter.PromotionAdapter;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(exports, "PromotionEvaluator", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () {
|
|
27
|
+
return _evaluator.PromotionEvaluator;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(exports, "X_ITEMS_FOR_Y_PRICE_STRATEGY", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
get: function () {
|
|
33
|
+
return _examples.X_ITEMS_FOR_Y_PRICE_STRATEGY;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(exports, "default", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
get: function () {
|
|
39
|
+
return _adapter.default;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
var _evaluator = require("./evaluator");
|
|
43
|
+
var _adapter = _interopRequireWildcard(require("./adapter"));
|
|
44
|
+
var _examples = require("./examples");
|
|
45
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
46
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
@@ -8,6 +8,7 @@ var _lodashEs = require("lodash-es");
|
|
|
8
8
|
var _holderRelations = require("../../Order/holderRelations");
|
|
9
9
|
var _utils = require("../../Order/utils");
|
|
10
10
|
var _entitlementPass = require("../../Discount/entitlementPass");
|
|
11
|
+
var _utils2 = require("../../Holder/utils");
|
|
11
12
|
var _orderLineDisplay = require("./orderLineDisplay");
|
|
12
13
|
/**
|
|
13
14
|
* 从已加车的普通商品 order line 反查 SkuDetailModal edit 所需的 cacheItem。
|
|
@@ -148,7 +149,7 @@ function buildNormalProductCacheItemFromOrderLine(input) {
|
|
|
148
149
|
}
|
|
149
150
|
return {
|
|
150
151
|
...(sourceProduct || {}),
|
|
151
|
-
holder_config: sourceProduct
|
|
152
|
+
holder_config: (0, _utils2.resolveProductHolderConfig)(sourceProduct) ?? (0, _utils2.resolveProductHolderConfig)(product) ?? undefined,
|
|
152
153
|
id: resolvedId,
|
|
153
154
|
product_id: resolvedId,
|
|
154
155
|
_id: uid,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { ProductData } from '../Product/types';
|
|
2
2
|
import { IFormItemData, IHolderConfig } from './types';
|
|
3
|
+
/** 保留显式禁用配置;仅在新配置缺失时兼容商品旧 holder 定义。 */
|
|
4
|
+
export declare function resolveProductHolderConfig(product?: ProductData | Record<string, any> | null): Record<string, any> | null;
|
|
3
5
|
export declare function getProductHolderConfig(product?: ProductData | Record<string, any> | null): IHolderConfig | null;
|
|
4
6
|
export declare function getFormIdFromHolderConfig(config: IHolderConfig): number;
|
|
5
7
|
export declare function normalizeFormId(formId: number | string): number;
|
|
@@ -8,9 +8,35 @@ exports.getFormIdFromHolderConfig = getFormIdFromHolderConfig;
|
|
|
8
8
|
exports.getProductHolderConfig = getProductHolderConfig;
|
|
9
9
|
exports.normalizeFormId = normalizeFormId;
|
|
10
10
|
exports.resolveFormMetaFromHolderItem = resolveFormMetaFromHolderItem;
|
|
11
|
+
exports.resolveProductHolderConfig = resolveProductHolderConfig;
|
|
12
|
+
/** 保留显式禁用配置;仅在新配置缺失时兼容商品旧 holder 定义。 */
|
|
13
|
+
function resolveProductHolderConfig(product) {
|
|
14
|
+
if (!product || typeof product !== 'object') return null;
|
|
15
|
+
const source = product;
|
|
16
|
+
const configSources = [source.holder_config, source.metadata?.holder_config, source.origin?.holder_config, source.metadata?.origin?.holder_config, source._origin?.holder_config, source._extend?.holder_config, source._extend?.product?.holder_config, source._extend?.product?.origin?.holder_config, source._extend?.product?.metadata?.holder_config, source._extend?.product?.metadata?.origin?.holder_config, source._extend?.product?._origin?.holder_config, source._extend?.product?._extend?.holder_config];
|
|
17
|
+
const config = configSources.find(value => value !== null && typeof value === 'object');
|
|
18
|
+
if (config) return config;
|
|
19
|
+
|
|
20
|
+
// metadata.holder / _extend.holder 是选择结果,不能作为商品配置读取。
|
|
21
|
+
const legacySources = [source.holder, source.origin?.holder, source.metadata?.origin?.holder, source._origin?.holder, source._extend?.product?.holder, source._extend?.product?.origin?.holder, source._extend?.product?.metadata?.origin?.holder, source._extend?.product?._origin?.holder];
|
|
22
|
+
const legacy = legacySources.find(value => value && typeof value === 'object' && !Array.isArray(value) && typeof value.type === 'string');
|
|
23
|
+
if (!legacy) return null;
|
|
24
|
+
const formId = legacy.custom?.custom_id;
|
|
25
|
+
if (legacy.type === 'custom' && legacy.custom?.type === 'form' && (typeof formId === 'number' || typeof formId === 'string') && Number.isInteger(Number(formId)) && Number(formId) > 0) {
|
|
26
|
+
return {
|
|
27
|
+
status: 'enable',
|
|
28
|
+
required: 0,
|
|
29
|
+
resource_id: formId
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
status: 'disable',
|
|
34
|
+
required: 0
|
|
35
|
+
};
|
|
36
|
+
}
|
|
11
37
|
function getProductHolderConfig(product) {
|
|
12
38
|
if (!product) return null;
|
|
13
|
-
const config = product
|
|
39
|
+
const config = resolveProductHolderConfig(product);
|
|
14
40
|
if (config?.status && config?.status !== 'enable') return null;
|
|
15
41
|
if (!config?.resource_id) return null;
|
|
16
42
|
return config;
|
|
@@ -8,6 +8,7 @@ var _BaseModule = require("../BaseModule");
|
|
|
8
8
|
var _types = require("./types");
|
|
9
9
|
var _utils = require("../../solution/ShopDiscount/utils");
|
|
10
10
|
var _utils2 = require("../Cart/utils");
|
|
11
|
+
var _utils3 = require("../Holder/utils");
|
|
11
12
|
var _decimal = _interopRequireDefault(require("decimal.js"));
|
|
12
13
|
var _lodashEs = require("lodash-es");
|
|
13
14
|
var _dayjs = _interopRequireDefault(require("dayjs"));
|
|
@@ -63,7 +64,7 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
63
64
|
if (discount.holder?.holder_type !== 'form') return true;
|
|
64
65
|
|
|
65
66
|
// getProduct 会裁剪商品字段,从原始商品读取配置,套餐子项沿用父商品。
|
|
66
|
-
const holderConfig =
|
|
67
|
+
const holderConfig = (0, _utils3.resolveProductHolderConfig)(holderSource);
|
|
67
68
|
const holderStatus = holderConfig?.status;
|
|
68
69
|
const holderEnabled = holderStatus === true || ['enable', '1'].includes(String(holderStatus).trim().toLowerCase());
|
|
69
70
|
if (!holderEnabled || holderConfig?.resource_id === undefined || holderConfig?.resource_id === null || holderConfig?.resource_id === '') {
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.ProductsModule = void 0;
|
|
7
7
|
var _BaseModule = require("../../../modules/BaseModule");
|
|
8
|
+
var _utils = require("../../../modules/Holder/utils");
|
|
8
9
|
var _Quotation = require("../../../modules/Quotation");
|
|
9
10
|
var _types = require("./types");
|
|
10
11
|
var _product = require("../../utils/product");
|
|
@@ -983,7 +984,7 @@ class ProductsModule extends _BaseModule.BaseModule {
|
|
|
983
984
|
if (!product) continue;
|
|
984
985
|
snapshots[String(id)] = {
|
|
985
986
|
cover: product.cover,
|
|
986
|
-
holder_config: product
|
|
987
|
+
holder_config: (0, _utils.resolveProductHolderConfig)(product) ?? undefined
|
|
987
988
|
};
|
|
988
989
|
}
|
|
989
990
|
return snapshots;
|