@pisell/private-materials 6.12.170 → 6.12.172

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 (58) hide show
  1. package/build/lowcode/assets-daily.json +11 -11
  2. package/build/lowcode/assets-dev.json +2 -2
  3. package/build/lowcode/assets-prod.json +11 -11
  4. package/build/lowcode/meta.js +1 -1
  5. package/build/lowcode/render/default/view.js +18 -18
  6. package/build/lowcode/view.js +18 -18
  7. package/es/components/HDLKiosk/app/workflow/predicates.js +1 -1
  8. package/es/components/HDLKiosk/runtime/operations/coordinator.js +2 -1
  9. package/es/components/HDLKiosk/runtime/operations/session.js +3 -2
  10. package/es/components/HDLKiosk/runtime/session/createSession.js +26 -3
  11. package/es/components/HDLKiosk/runtime/session/transitionRunner.js +6 -2
  12. package/es/components/HDLKiosk/slices/payment/view.js +13 -4
  13. package/es/components/bigSale/components/BookingFloatingPanel/useBookingPanelController.js +1 -0
  14. package/es/components/bigSale/components/TimeBar/index.js +1 -0
  15. package/es/components/bigSale/dialog.js +1 -0
  16. package/es/components/bigSale/hooks/useBigSaleContext.js +1 -0
  17. package/es/components/bigSale/hooks/useSelectFloorMapResourceForBigSale.js +1 -0
  18. package/es/components/bigSale/index.js +1 -0
  19. package/es/components/bigSale/templates/HDLKiosk/adapter/host/projection.js +1 -1
  20. package/es/components/bigSale/templates/HDLKiosk/adapter/sales/session.js +7 -2
  21. package/es/components/bigSale/templates/HDLKiosk/runtime/HDLKioskPaymentRuntime.js +95 -148
  22. package/es/components/bigSale/templates/HDLKiosk/runtime/eftposPayment.js +110 -0
  23. package/es/components/bigSale/templates/HDLKiosk/runtime/staffPaymentAuthorization.js +183 -0
  24. package/es/components/bigSale/templates/Kiosk/index.js +1 -0
  25. package/es/components/sharedSecondaryBigSale/SharedSecondaryBigSaleReceiver.js +1 -0
  26. package/es/index.js +2 -0
  27. package/es/plus/pisellReservation/data/bookingToReservationTables.js +1 -1
  28. package/es/plus/pisellReservation/floorMap/floorPlanApi.js +1 -1
  29. package/es/plus/pisellReservation/floorMap/reservationMock.js +1 -1
  30. package/es/plus/pisellReservation/index.js +17 -0
  31. package/es/plus/saleDetail/Base.js +1 -0
  32. package/es/plus/saleDetail/components/Client/hooks/useClientSelectorProps.js +1 -0
  33. package/es/plus/saleDetail/components/DetailActions/index.js +1 -0
  34. package/es/plus/saleDetail/components/SummaryFinancialSections/index.js +1 -0
  35. package/es/plus/saleDetail/index.js +1 -0
  36. package/es/plus/saleDetail/tmpl/B/components/Dish/index.js +1 -0
  37. package/es/plus/saleDetail/tmpl/B/index.js +1 -0
  38. package/es/plus/salesSdk/index.js +52 -0
  39. package/es/plus/salesSdk/utils/addProductWithFlowDebounced.js +1 -1
  40. package/es/plus/salesSdk/utils/bookingDate.js +1 -1
  41. package/es/plus/salesSdk/utils/customerAuthGate.js +1 -1
  42. package/es/plus/salesSdk/utils/enrichCartLineHolderDisplay.js +1 -1
  43. package/es/pro/Login2.0/AuthModal.d.ts +1 -1
  44. package/es/pro/Login2.0/index.d.ts +2 -1
  45. package/es/pro/Login2.0/shared/types.d.ts +1 -1
  46. package/lib/components/HDLKiosk/app/workflow/predicates.js +1 -1
  47. package/lib/components/HDLKiosk/runtime/operations/coordinator.js +2 -1
  48. package/lib/components/HDLKiosk/runtime/operations/session.js +3 -2
  49. package/lib/components/HDLKiosk/runtime/session/createSession.js +26 -3
  50. package/lib/components/HDLKiosk/runtime/session/transitionRunner.js +6 -2
  51. package/lib/components/HDLKiosk/slices/payment/view.js +13 -4
  52. package/lib/components/bigSale/templates/HDLKiosk/adapter/host/projection.js +1 -1
  53. package/lib/components/bigSale/templates/HDLKiosk/adapter/sales/session.js +7 -2
  54. package/lib/components/bigSale/templates/HDLKiosk/runtime/HDLKioskPaymentRuntime.js +92 -145
  55. package/lib/components/bigSale/templates/HDLKiosk/runtime/eftposPayment.js +110 -0
  56. package/lib/components/bigSale/templates/HDLKiosk/runtime/staffPaymentAuthorization.js +186 -0
  57. package/package.json +4 -4
  58. package/es/private-materials/lowcode/authmodal/meta.d.ts +0 -1
@@ -7,7 +7,7 @@ const DEFAULT_PREDICATES = Object.freeze({
7
7
  "fulfillment.selected": ({ workflow }) => workflow.fulfillment === "dine_in" || workflow.fulfillment === "takeaway",
8
8
  "checkout.locallyEligible": ({ sales }) => sales.cart.lineCount > 0 && !sales.cart.consistencyPending && sales.summary.status === "ready" && sales.payment.status !== "pending" && sales.payment.status !== "unknown",
9
9
  "payment.notPending": ({ sales }) => sales.payment.status !== "pending" && sales.payment.status !== "unknown",
10
- "payment.succeeded": ({ sales }) => sales.payment.status === "succeeded"
10
+ "payment.succeeded": ({ sales, receipt }) => sales.payment.status === "succeeded" || receipt != null && typeof receipt === "object" && typeof receipt.orderId === "string" && receipt.orderId.trim() !== "" && Number.isFinite(Number(receipt.amount))
11
11
  });
12
12
  function createPredicateRegistry(overrides = {}) {
13
13
  const predicates = Object.freeze(_objectSpread2(_objectSpread2({}, DEFAULT_PREDICATES), overrides));
@@ -56,7 +56,7 @@ function createOperationCoordinator(host, registry, options = {}) {
56
56
  } catch (_unused2) {}
57
57
  if (event.type === "finished") emitError(event.metadata.definitionId, request, event.result);
58
58
  };
59
- return createKernelOperationCoordinator(registry, {
59
+ const coordinator = createKernelOperationCoordinator(registry, {
60
60
  createContext: ({ request }) => {
61
61
  var _options$getWorkflowC, _options$getWorkflowC2;
62
62
  return {
@@ -103,6 +103,7 @@ function createOperationCoordinator(host, registry, options = {}) {
103
103
  matches: (operation) => operation.conflictScope === "cart"
104
104
  }
105
105
  }, { initialSessionEpoch: options.initialSessionEpoch });
106
+ return Object.freeze(_objectSpread2(_objectSpread2({}, coordinator), {}, { confirmPaymentSucceeded: checkoutSafety.markSucceeded }));
106
107
  }
107
108
  //#endregion
108
109
  export { createOperationCoordinator };
@@ -8,9 +8,10 @@ function forwardFailure(result) {
8
8
  }
9
9
  const sessionEnsureOperationBinding = bindOperation(sessionEnsureOperation, { execute: ({ host }, _input, signal) => host.sales.ensureSession(signal) });
10
10
  const sessionResetOperationBinding = bindOperation(sessionResetOperation, { execute: function() {
11
- var _ref = _asyncToGenerator(function* ({ host }, _input, signal) {
11
+ var _ref = _asyncToGenerator(function* (context, _input, signal) {
12
+ const { host } = context;
12
13
  const before = host.sales.getObservedSnapshot();
13
- if (before.payment.status === "pending" || before.payment.status === "unknown") return operationUnknown("resetBlockedByPaymentState");
14
+ if ((before.payment.status === "pending" || before.payment.status === "unknown") && context.checkoutSafety.state() !== "succeeded") return operationUnknown("resetBlockedByPaymentState");
14
15
  const reset = yield host.sales.clearAndReset(signal);
15
16
  if (reset.status !== "succeeded") return forwardFailure(reset);
16
17
  if (!reset.data.cartEmpty) return operationUnknown("resetHostResultNotEmpty");
@@ -69,27 +69,49 @@ function createHDLKioskWorkflowSession(entry, host, options = {}) {
69
69
  });
70
70
  actorRef = workflowActor;
71
71
  let paymentProjectionObservationId;
72
+ let staffPaymentPending = false;
73
+ let staffPaymentOutcome;
72
74
  const advanceConfirmedPayment = () => {
73
- var _definition$nodes$sna;
75
+ var _staffPaymentOutcome, _definition$nodes$sna;
74
76
  const snapshot = workflowActor.getSnapshot();
75
77
  const projection = host.sales.getObservedSnapshot();
76
- if (snapshot.status !== "idle" || ((_definition$nodes$sna = definition.nodes[snapshot.nodeId]) === null || _definition$nodes$sna === void 0 ? void 0 : _definition$nodes$sna.activity) !== "paymentMethod" || projection.payment.status !== "succeeded" || paymentProjectionObservationId === projection.observationId) return;
78
+ const projectionOutcome = projection.payment.status === "succeeded" ? Object.freeze(_objectSpread2(_objectSpread2(_objectSpread2({
79
+ orderId: projection.payment.orderId,
80
+ amount: projection.payment.amount
81
+ }, projection.summary.status === "ready" && projection.summary.currencySymbol ? { currencySymbol: projection.summary.currencySymbol } : {}), projection.pickupNumber ? { pickupNumber: projection.pickupNumber } : {}), projection.customer ? { member: projection.customer.member === true } : {})) : void 0;
82
+ const outcome = (_staffPaymentOutcome = staffPaymentOutcome) !== null && _staffPaymentOutcome !== void 0 ? _staffPaymentOutcome : projectionOutcome;
83
+ if (snapshot.status !== "idle" || ((_definition$nodes$sna = definition.nodes[snapshot.nodeId]) === null || _definition$nodes$sna === void 0 ? void 0 : _definition$nodes$sna.activity) !== "paymentMethod" || staffPaymentPending && !staffPaymentOutcome || !outcome || !staffPaymentOutcome && paymentProjectionObservationId === projection.observationId) return;
77
84
  paymentProjectionObservationId = projection.observationId;
78
85
  workflowActor.send({
79
86
  type: "ACTIVITY_INTENT",
80
87
  stepId: snapshot.nodeId,
81
88
  activityId: "paymentMethod",
82
89
  intent: "complete",
83
- intentId: `projection:payment:${snapshot.sessionEpoch}:${projection.observationId}`
90
+ intentId: staffPaymentOutcome ? `staff-payment:${snapshot.sessionEpoch}:${projection.observationId}` : `projection:payment:${snapshot.sessionEpoch}:${projection.observationId}`,
91
+ receipt: outcome
84
92
  });
85
93
  };
86
94
  let unsubscribePaymentProjection = () => void 0;
87
95
  let unsubscribePaymentWorkflow = () => void 0;
96
+ let unsubscribeStaffPayment = () => void 0;
88
97
  try {
89
98
  unsubscribePaymentProjection = host.sales.subscribe(advanceConfirmedPayment);
90
99
  unsubscribePaymentWorkflow = workflowActor.subscribe(advanceConfirmedPayment);
100
+ unsubscribeStaffPayment = host.sales.subscribeStaffPaymentAuthorizationResult((result) => {
101
+ if (result.status === "pending") {
102
+ staffPaymentPending = true;
103
+ staffPaymentOutcome = void 0;
104
+ return;
105
+ }
106
+ staffPaymentPending = false;
107
+ staffPaymentOutcome = result.status === "succeeded" ? result.data : void 0;
108
+ if (staffPaymentOutcome) coordinator.confirmPaymentSucceeded();
109
+ advanceConfirmedPayment();
110
+ });
91
111
  } catch (error) {
92
112
  unsubscribePaymentProjection();
113
+ unsubscribePaymentWorkflow();
114
+ unsubscribeStaffPayment();
93
115
  workflowActor.dispose();
94
116
  throw error;
95
117
  }
@@ -120,6 +142,7 @@ function createHDLKioskWorkflowSession(entry, host, options = {}) {
120
142
  disposed = true;
121
143
  unsubscribePaymentProjection();
122
144
  unsubscribePaymentWorkflow();
145
+ unsubscribeStaffPayment();
123
146
  workflowActor.dispose();
124
147
  };
125
148
  const publicActor = Object.freeze(_objectSpread2(_objectSpread2({}, workflowActor), {}, { dispose: disposeSession }));
@@ -39,7 +39,8 @@ function createHDLKioskTransitionRunner({ host, coordinator, predicates, now = D
39
39
  if (exitPolicy === null || exitPolicy === void 0 ? void 0 : exitPolicy.precondition) try {
40
40
  if (!predicates.evaluate(exitPolicy.precondition, {
41
41
  workflow: context,
42
- sales: host.sales.getObservedSnapshot()
42
+ sales: host.sales.getObservedSnapshot(),
43
+ receipt: "receipt" in event ? event.receipt : void 0
43
44
  })) return { status: "stay" };
44
45
  } catch (cause) {
45
46
  const error = createDomainWorkflowError("workflowPredicateEvaluationFailed", "staff", cause);
@@ -51,7 +52,10 @@ function createHDLKioskTransitionRunner({ host, coordinator, predicates, now = D
51
52
  }
52
53
  const operationInput = "operationInput" in event ? event.operationInput : void 0;
53
54
  const command = exitPolicy === null || exitPolicy === void 0 ? void 0 : exitPolicy.command;
54
- if (!command) return { status: "advance" };
55
+ if (!command) return {
56
+ status: "advance",
57
+ receipt: "receipt" in event ? event.receipt : void 0
58
+ };
55
59
  const result = yield coordinator.execute(command.id, {
56
60
  operationId: executionId,
57
61
  intentId: event.intentId,
@@ -51,7 +51,16 @@ function createPaymentFeedback(snapshot, sales) {
51
51
  message: locales.getText("pisell2.hdl-kiosk.payment-failed-retry")
52
52
  };
53
53
  }
54
+ function readPaymentResultReceipt(snapshot) {
55
+ const receipt = snapshot.receipt;
56
+ if (!receipt || typeof receipt !== "object") return void 0;
57
+ const candidate = receipt;
58
+ if (typeof candidate.orderId !== "string" || !candidate.orderId.trim() || candidate.amount === void 0 || candidate.amount === null || !Number.isFinite(Number(candidate.amount))) return;
59
+ return candidate;
60
+ }
54
61
  function createCheckoutScreenModel(snapshot, sales, payment, completed = false, resetting = false) {
62
+ var _paymentResultReceipt, _paymentResultReceipt2;
63
+ const paymentResultReceipt = completed ? readPaymentResultReceipt(snapshot) : void 0;
55
64
  const paymentSafeToChange = sales.payment.status === "idle" || sales.payment.status === "failed";
56
65
  const interactionAvailable = !completed && !resetting && snapshot.status === "idle" && paymentSafeToChange;
57
66
  const totalText = sales.summary.status === "ready" ? formatCurrencyAmount(sales.summary.due, sales.summary.currencySymbol) : void 0;
@@ -72,12 +81,12 @@ function createCheckoutScreenModel(snapshot, sales, payment, completed = false,
72
81
  paymentResult: completed ? resolvePaymentResultToastV2ViewModel({
73
82
  status: "success",
74
83
  paymentStatus: "paid",
75
- currencySymbol: sales.summary.status === "ready" ? sales.summary.currencySymbol : void 0,
76
- orderTotalAmount: sales.payment.status === "succeeded" ? sales.payment.amount : sales.summary.status === "ready" ? sales.summary.total : void 0,
84
+ currencySymbol: (_paymentResultReceipt = paymentResultReceipt === null || paymentResultReceipt === void 0 ? void 0 : paymentResultReceipt.currencySymbol) !== null && _paymentResultReceipt !== void 0 ? _paymentResultReceipt : sales.summary.status === "ready" ? sales.summary.currencySymbol : void 0,
85
+ orderTotalAmount: (_paymentResultReceipt2 = paymentResultReceipt === null || paymentResultReceipt === void 0 ? void 0 : paymentResultReceipt.amount) !== null && _paymentResultReceipt2 !== void 0 ? _paymentResultReceipt2 : sales.payment.status === "succeeded" ? sales.payment.amount : sales.summary.status === "ready" ? sales.summary.total : void 0,
77
86
  prominentReference: {
78
87
  label: locales.getText("pisell2.hdl-kiosk.pickup-number"),
79
- value: sales.pickupNumber || locales.getText("pisell2.hdl-kiosk.pickup-number-pending"),
80
- pending: !sales.pickupNumber
88
+ value: (paymentResultReceipt === null || paymentResultReceipt === void 0 ? void 0 : paymentResultReceipt.pickupNumber) || sales.pickupNumber || locales.getText("pisell2.hdl-kiosk.pickup-number-pending"),
89
+ pending: !((paymentResultReceipt === null || paymentResultReceipt === void 0 ? void 0 : paymentResultReceipt.pickupNumber) || sales.pickupNumber)
81
90
  },
82
91
  disableDetail: true
83
92
  }) : void 0,
@@ -1,5 +1,6 @@
1
1
  import useEngineContext from "../../../../hooks/useEngineContext.js";
2
2
  import { subscribeBookingDateChange } from "../../../../plus/salesSdk/utils/bookingDate.js";
3
+ import "../../../../plus/salesSdk/index.js";
3
4
  import dayjs from "dayjs";
4
5
  import { useCallback, useEffect, useState } from "react";
5
6
  //#region src/components/bigSale/components/BookingFloatingPanel/useBookingPanelController.ts
@@ -4,6 +4,7 @@ import withResponsive from "../../../../responsive/withResponsive.js";
4
4
  import useInitLocalesOnce from "../../../../hooks/useInitLocalesOnce.js";
5
5
  import { subscribeBookingDateChange } from "../../../../plus/salesSdk/utils/bookingDate.js";
6
6
  import { useSalesSdkBookingContext } from "../../../../plus/salesSdk/context/SalesSdkBookingContext.js";
7
+ import "../../../../plus/salesSdk/index.js";
7
8
  import locales_default from "../../locales/index.js";
8
9
  import dayjs from "dayjs";
9
10
  import React, { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
@@ -5,6 +5,7 @@ import { buildInitBookingContextParams, collectBookingIdsFromTempOrder } from ".
5
5
  import { useSalesSdk } from "../../plus/salesSdk/hooks/useSalesSdk.js";
6
6
  import { useSalesSdkCart } from "../../plus/salesSdk/hooks/useSalesSdkCart.js";
7
7
  import { SalesSdkPrepareOrderSwitchContext, SalesSdkRootRefreshContext } from "../../plus/salesSdk/context/SalesSdkProvider.js";
8
+ import "../../plus/salesSdk/index.js";
8
9
  import { seedDineInReservationToCart } from "../../plus/pisellReservation/utils/seedDineInReservationToCart.js";
9
10
  import BigSale from "./index.js";
10
11
  import dayjs from "dayjs";
@@ -4,6 +4,7 @@ import { useSalesSdkCustomer } from "../../../plus/salesSdk/hooks/useSalesSdkCus
4
4
  import { useSalesSdkBookingContext } from "../../../plus/salesSdk/context/SalesSdkBookingContext.js";
5
5
  import { useSalesSdkSummary } from "../../../plus/salesSdk/hooks/useSalesSdkSummary.js";
6
6
  import { useSalesSdkProducts } from "../../../plus/salesSdk/hooks/useSalesSdkProducts.js";
7
+ import "../../../plus/salesSdk/index.js";
7
8
  import { useMemo } from "react";
8
9
  //#region src/components/bigSale/hooks/useBigSaleContext.ts
9
10
  /**
@@ -3,6 +3,7 @@ import useEngineContext from "../../../hooks/useEngineContext.js";
3
3
  import { buildInitBookingContextParams, collectBookingIdsFromTempOrder } from "../../../plus/salesSdk/utils/buildDefaultLoadProductsParams.js";
4
4
  import { useSalesSdkUIHosts } from "../../../plus/salesSdk/context/SalesSdkUIHostsContext.js";
5
5
  import { SalesSdkRootRefreshContext } from "../../../plus/salesSdk/context/SalesSdkProvider.js";
6
+ import "../../../plus/salesSdk/index.js";
6
7
  import { resolveOrderIdForHostActions } from "../../../plus/pisellReservation/components/bookingDetailModal/bookingDetailHostActions.js";
7
8
  import { usePicoCodingOpenData } from "../../../plus/pisellReservation/hooks/usePicoCodingOpenData.js";
8
9
  import { seedDineInReservationToCart } from "../../../plus/pisellReservation/utils/seedDineInReservationToCart.js";
@@ -8,6 +8,7 @@ import { useSalesSdk } from "../../plus/salesSdk/hooks/useSalesSdk.js";
8
8
  import { useSalesSdkCustomer } from "../../plus/salesSdk/hooks/useSalesSdkCustomer.js";
9
9
  import { SalesSdkProvider } from "../../plus/salesSdk/context/SalesSdkProvider.js";
10
10
  import { SalesSdkBookingContextProvider } from "../../plus/salesSdk/context/SalesSdkBookingContext.js";
11
+ import "../../plus/salesSdk/index.js";
11
12
  import { ResponsiveBigSaleBase } from "./Base.js";
12
13
  import { isBigSaleProductSelectionFlowScene, resolveBigSaleSelectionFlowConfig } from "./selectionFlowConfig.js";
13
14
  import { isKioskPresentation } from "./templateCapabilities.js";
@@ -142,7 +142,7 @@ function buildSnapshot(context, observationId, pickupReferenceMode) {
142
142
  currency: String((_context$sales$tempOr2 = (_context$sales$tempOr3 = context.sales.tempOrder) === null || _context$sales$tempOr3 === void 0 ? void 0 : _context$sales$tempOr3.currency_code) !== null && _context$sales$tempOr2 !== void 0 ? _context$sales$tempOr2 : ""),
143
143
  currencySymbol: String((_context$sales$tempOr4 = (_context$sales$tempOr5 = context.sales.tempOrder) === null || _context$sales$tempOr5 === void 0 ? void 0 : _context$sales$tempOr5.currency_symbol) !== null && _context$sales$tempOr4 !== void 0 ? _context$sales$tempOr4 : ""),
144
144
  total: String(summary.total_amount),
145
- due: String(summary.expect_amount)
145
+ due: String(summary.amount_gap)
146
146
  }) : context.sales.status === "loading" ? Object.freeze({ status: "calculating" }) : Object.freeze({ status: "missing" });
147
147
  const avatarUrl = typeof ((_context$customer$sel = context.customer.selected) === null || _context$customer$sel === void 0 ? void 0 : _context$customer$sel.avatar) === "string" && context.customer.selected.avatar.trim() ? context.customer.selected.avatar.trim() : void 0;
148
148
  const customer = context.customer.selected ? Object.freeze(_objectSpread2(_objectSpread2({
@@ -28,7 +28,9 @@ function createBigSaleSessionOperations({ getContext }) {
28
28
  data: void 0
29
29
  };
30
30
  try {
31
- const createdOrder = isCommittedPaidOrder(currentOrder) ? yield context.sales.clearCartAndReset() : yield context.sales.createNew();
31
+ const resetPaidOrder = isCommittedPaidOrder(currentOrder);
32
+ const createdOrder = resetPaidOrder ? yield context.sales.clearCartAndReset() : yield context.sales.createNew();
33
+ if (resetPaidOrder) yield context.cart.recalcSummary();
32
34
  if (signal.aborted) return unknown("ensureSessionAbortedAfterDispatch");
33
35
  const liveCreatedOrder = resolveBigSaleLiveTempOrder(getContext());
34
36
  const createdPaymentStatus = readPaymentStatus(liveCreatedOrder !== null && liveCreatedOrder !== void 0 ? liveCreatedOrder : createdOrder);
@@ -50,9 +52,12 @@ function createBigSaleSessionOperations({ getContext }) {
50
52
  if (signal.aborted) return { status: "cancelled" };
51
53
  try {
52
54
  var _resetOrder$products$, _resetOrder$products, _resetOrder$bookings$, _resetOrder$bookings;
53
- const resetOrder = yield getContext().sales.clearCartAndReset();
55
+ const context = getContext();
56
+ const resetOrder = yield context.sales.clearCartAndReset();
54
57
  if (signal.aborted) return unknown("resetAbortedAfterDispatch");
55
58
  if (!(((_resetOrder$products$ = (_resetOrder$products = resetOrder.products) === null || _resetOrder$products === void 0 ? void 0 : _resetOrder$products.length) !== null && _resetOrder$products$ !== void 0 ? _resetOrder$products$ : 0) === 0 && ((_resetOrder$bookings$ = (_resetOrder$bookings = resetOrder.bookings) === null || _resetOrder$bookings === void 0 ? void 0 : _resetOrder$bookings.length) !== null && _resetOrder$bookings$ !== void 0 ? _resetOrder$bookings$ : 0) === 0)) return unknown("resetHostResultNotEmpty");
59
+ yield context.cart.recalcSummary();
60
+ if (signal.aborted) return unknown("resetAbortedAfterRecalculation");
56
61
  return {
57
62
  status: "succeeded",
58
63
  data: { cartEmpty: true }
@@ -1,18 +1,17 @@
1
1
  import { _asyncToGenerator } from "../../../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/asyncToGenerator.js";
2
- import { _objectWithoutProperties } from "../../../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectWithoutProperties.js";
3
2
  import useEngineContext from "../../../../../hooks/useEngineContext.js";
4
- import { CHECKOUT_VISIBLE_PAYMENT_CODES, resolvePiPaymentProvider } from "../../../../checkout/constants.js";
3
+ import { CHECKOUT_VISIBLE_PAYMENT_CODES } from "../../../../checkout/constants.js";
5
4
  import PaymentMethodRuntime_default from "../../../../checkout/paymentRuntime/PaymentMethodRuntime.js";
6
- import { completePendingEftposPayment, discardPendingEftposPayment, preparePendingEftposPayment } from "../../../../checkout/paymentRuntime/pendingEftposLifecycle.js";
7
- import { getCurrentDeviceNumber, reorderPaymentMethodList } from "../../../../checkout/utils.js";
8
- import { failed, unknown } from "../adapter/normalize.js";
5
+ import { reorderPaymentMethodList } from "../../../../checkout/utils.js";
6
+ import { failed } from "../adapter/normalize.js";
7
+ import { executeEftposPayment } from "./eftposPayment.js";
8
+ import { createStaffPaymentAuthorizationStore, finalizeStaffPaymentOutcome, isStaffPaymentAuthorizationCancelled, resolveStaffPaymentResult } from "./staffPaymentAuthorization.js";
9
9
  import React, { useEffect, useMemo, useRef } from "react";
10
10
  //#region src/components/bigSale/templates/HDLKiosk/runtime/HDLKioskPaymentRuntime.tsx
11
11
  /**
12
12
  * BigSale 模板内的 Kiosk 支付桥。它持有需要 React/设备 UI 的 PaymentMethodRuntime,
13
13
  * 再把窄命令交给独立 HDLKiosk Host;Core 不感知 BigSale、PiPayment 或 window.app。
14
14
  */
15
- const _excluded = ["unique_payment_number"];
16
15
  function asKioskMethod(method) {
17
16
  var _raw$channel_applicat;
18
17
  const raw = method;
@@ -35,45 +34,26 @@ function currentAmount(context) {
35
34
  const amount = Number((_ref = (_summary$expect_amoun = summary === null || summary === void 0 ? void 0 : summary.expect_amount) !== null && _summary$expect_amoun !== void 0 ? _summary$expect_amoun : summary === null || summary === void 0 ? void 0 : summary.product_expect_amount) !== null && _ref !== void 0 ? _ref : summary === null || summary === void 0 ? void 0 : summary.total_amount);
36
35
  return Number.isFinite(amount) && amount > 0 ? amount : 0;
37
36
  }
38
- function isStaffPaymentAuthorizationCancelled(result) {
39
- var _record$status, _record$reason;
40
- if (!result || typeof result !== "object") return false;
41
- const record = result;
42
- return [
43
- "cancelled",
44
- "canceled",
45
- "closed"
46
- ].includes(String((_record$status = record.status) !== null && _record$status !== void 0 ? _record$status : "").toLowerCase()) || [
47
- "cancelled",
48
- "canceled",
49
- "cancel"
50
- ].includes(String((_record$reason = record.reason) !== null && _record$reason !== void 0 ? _record$reason : "").toLowerCase());
51
- }
52
- function checkoutSuccess(baseSales) {
53
- var _baseSales$getTempOrd, _baseSales$getOrderId, _ref2, _baseSales$getOrderAm, _baseSales$getOrderAm2;
54
- const order = (baseSales === null || baseSales === void 0 || (_baseSales$getTempOrd = baseSales.getTempOrder) === null || _baseSales$getTempOrd === void 0 ? void 0 : _baseSales$getTempOrd.call(baseSales)) || {};
55
- const orderId = ((baseSales === null || baseSales === void 0 || (_baseSales$getOrderId = baseSales.getOrderIdentity) === null || _baseSales$getOrderId === void 0 ? void 0 : _baseSales$getOrderId.call(baseSales)) || {}).orderId || order.order_id;
56
- if (!orderId) return unknown("eftposSuccessMissingOrderId");
57
- return {
58
- status: "succeeded",
59
- data: {
60
- orderId: String(orderId),
61
- amount: String((_ref2 = (_baseSales$getOrderAm = baseSales === null || baseSales === void 0 || (_baseSales$getOrderAm2 = baseSales.getOrderAmountSnapshot) === null || _baseSales$getOrderAm2 === void 0 || (_baseSales$getOrderAm2 = _baseSales$getOrderAm2.call(baseSales)) === null || _baseSales$getOrderAm2 === void 0 ? void 0 : _baseSales$getOrderAm2.expectAmount) !== null && _baseSales$getOrderAm !== void 0 ? _baseSales$getOrderAm : order.expect_amount) !== null && _ref2 !== void 0 ? _ref2 : 0)
62
- }
63
- };
64
- }
65
37
  function HDLKioskPaymentRuntime({ context, controllerRef }) {
66
38
  var _context$sales$tempOr, _engineContext$appHel5;
67
39
  const engineContext = useEngineContext();
68
40
  const runtimeRef = useRef(null);
69
41
  const methodsRef = useRef([]);
70
42
  const rawMethodsRef = useRef(/* @__PURE__ */ new Map());
71
- const authorizationListenersRef = useRef(/* @__PURE__ */ new Set());
43
+ const authorizationStore = useMemo(() => createStaffPaymentAuthorizationStore(), []);
72
44
  const baseSales = context.sales.bookingTicket;
73
45
  const currencySymbol = ((_context$sales$tempOr = context.sales.tempOrder) === null || _context$sales$tempOr === void 0 ? void 0 : _context$sales$tempOr.currency_symbol) || "$";
46
+ const staffPaymentOutcomeContextRef = useRef({
47
+ baseSales,
48
+ loadDetail: context.sales.loadDetail
49
+ });
50
+ staffPaymentOutcomeContextRef.current = {
51
+ baseSales,
52
+ loadDetail: context.sales.loadDetail
53
+ };
74
54
  const controller = useMemo(() => ({
75
55
  loadPaymentMethods: function() {
76
- var _ref3 = _asyncToGenerator(function* () {
56
+ var _ref2 = _asyncToGenerator(function* () {
77
57
  if (!(baseSales === null || baseSales === void 0 ? void 0 : baseSales.getPaymentMethodsAsync)) return failed("paymentMethodsUnavailable", "staff");
78
58
  try {
79
59
  var _engineContext$appHel;
@@ -92,12 +72,12 @@ function HDLKioskPaymentRuntime({ context, controllerRef }) {
92
72
  }
93
73
  });
94
74
  return function loadPaymentMethods() {
95
- return _ref3.apply(this, arguments);
75
+ return _ref2.apply(this, arguments);
96
76
  };
97
77
  }(),
98
78
  payEftpos: function() {
99
- var _ref5 = _asyncToGenerator(function* ({ paymentMethodId }) {
100
- var _engineContext$appHel2, _engineContext$appHel3;
79
+ var _ref3 = _asyncToGenerator(function* ({ paymentMethodId }) {
80
+ var _engineContext$appHel2, _engineContext$appHel3, _engineContext$appHel4;
101
81
  const method = methodsRef.current.find((item) => item.id === paymentMethodId);
102
82
  if (!(method === null || method === void 0 ? void 0 : method.eftpos)) return failed("eftposMethodUnavailable", "back");
103
83
  const rawMethod = rawMethodsRef.current.get(paymentMethodId);
@@ -106,103 +86,39 @@ function HDLKioskPaymentRuntime({ context, controllerRef }) {
106
86
  if (amount <= 0) return failed("paymentAmountInvalid", "back");
107
87
  const runtime = runtimeRef.current;
108
88
  if (!runtime) return failed("paymentRuntimeUnavailable", "retry");
109
- const piProvider = resolvePiPaymentProvider(method.code, Boolean((_engineContext$appHel2 = engineContext.appHelper) === null || _engineContext$appHel2 === void 0 || (_engineContext$appHel2 = _engineContext$appHel2.utils) === null || _engineContext$appHel2 === void 0 || (_engineContext$appHel2 = _engineContext$appHel2.businessUtils) === null || _engineContext$appHel2 === void 0 || (_engineContext$appHel3 = _engineContext$appHel2.isPiPaymentEnabled) === null || _engineContext$appHel3 === void 0 ? void 0 : _engineContext$appHel3.call(_engineContext$appHel2)));
110
- let prepared;
111
- let shouldDiscardPrepared = false;
112
- try {
113
- var _engineContext$appHel4, _baseSales$getOrderId2, _baseSales$getTempOrd2;
114
- if (piProvider) {
115
- prepared = yield preparePendingEftposPayment({
116
- amount,
117
- baseSales,
118
- method: rawMethod
119
- });
120
- shouldDiscardPrepared = true;
121
- if (!prepared.salesId) throw new Error("Unable to resolve sales id before opening PiPayment.");
122
- }
123
- const deviceNumber = yield getCurrentDeviceNumber((_engineContext$appHel4 = engineContext.appHelper) === null || _engineContext$appHel4 === void 0 || (_engineContext$appHel4 = _engineContext$appHel4.utils) === null || _engineContext$appHel4 === void 0 ? void 0 : _engineContext$appHel4.interaction);
124
- const result = yield runtime.execute({
125
- method: rawMethod,
126
- amount,
127
- currencySymbol,
128
- deviceNumber,
129
- preparedPayment: prepared ? {
130
- paymentNumber: prepared.paymentNumber,
131
- salesId: prepared.salesId
132
- } : void 0
133
- });
134
- if (result.preservePendingPayment) shouldDiscardPrepared = false;
135
- if (prepared && result.preservePendingPayment && result.status !== "success") return unknown("eftposPendingPaymentUnresolved", result);
136
- if (result.status === "cancelled" || result.status === "provider-handled") {
137
- if (prepared && shouldDiscardPrepared) yield discardPendingEftposPayment(baseSales, prepared.paymentNumber);
138
- return {
139
- status: "cancelled",
140
- reason: result.status
141
- };
142
- }
143
- if (result.status === "cancel-order") {
144
- if (prepared && shouldDiscardPrepared) yield discardPendingEftposPayment(baseSales, prepared.paymentNumber);
145
- return {
146
- status: "cancelled",
147
- reason: "cancelOrder"
148
- };
149
- }
150
- if (result.status !== "success") {
151
- if (prepared && shouldDiscardPrepared) yield discardPendingEftposPayment(baseSales, prepared.paymentNumber);
152
- return failed("eftposPaymentFailed", "retry", result.message);
153
- }
154
- if (prepared) {
155
- shouldDiscardPrepared = false;
156
- const _ref4 = result.metadata || {}, { unique_payment_number: transactionNumber } = _ref4, metadata = _objectWithoutProperties(_ref4, _excluded);
157
- yield completePendingEftposPayment({
158
- amount: result.amount,
159
- baseSales,
160
- paymentNumber: prepared.paymentNumber,
161
- transactionNumber,
162
- serviceCharge: result.serviceCharge,
163
- updates: { metadata }
164
- });
165
- } else if (typeof (baseSales === null || baseSales === void 0 ? void 0 : baseSales.commitPaymentMethodPayment) === "function") yield baseSales.commitPaymentMethodPayment({
166
- paymentMethodId: method.id,
167
- paymentMethodCode: method.code,
168
- amount: result.amount,
169
- serviceCharge: result.serviceCharge,
170
- metadata: result.metadata
171
- });
172
- else return failed("paymentCommitUnavailable", "staff");
173
- const orderId = (baseSales === null || baseSales === void 0 || (_baseSales$getOrderId2 = baseSales.getOrderIdentity) === null || _baseSales$getOrderId2 === void 0 || (_baseSales$getOrderId2 = _baseSales$getOrderId2.call(baseSales)) === null || _baseSales$getOrderId2 === void 0 ? void 0 : _baseSales$getOrderId2.orderId) || (baseSales === null || baseSales === void 0 || (_baseSales$getTempOrd2 = baseSales.getTempOrder) === null || _baseSales$getTempOrd2 === void 0 || (_baseSales$getTempOrd2 = _baseSales$getTempOrd2.call(baseSales)) === null || _baseSales$getTempOrd2 === void 0 ? void 0 : _baseSales$getTempOrd2.order_id);
174
- if (orderId && typeof context.sales.loadDetail === "function") yield context.sales.loadDetail({
175
- orderId,
176
- forceRemote: true
177
- });
178
- return checkoutSuccess(baseSales);
179
- } catch (error) {
180
- try {
181
- if (prepared && shouldDiscardPrepared) yield discardPendingEftposPayment(baseSales, prepared.paymentNumber);
182
- } catch (discardError) {
183
- return unknown("eftposPendingRollbackFailed", discardError);
184
- }
185
- if (prepared && !shouldDiscardPrepared) return unknown("eftposPaymentFinalizationUnresolved", error);
186
- return failed("eftposPaymentFailed", "retry", error);
187
- }
89
+ return executeEftposPayment({
90
+ amount,
91
+ baseSales,
92
+ currencySymbol,
93
+ interaction: (_engineContext$appHel2 = engineContext.appHelper) === null || _engineContext$appHel2 === void 0 || (_engineContext$appHel2 = _engineContext$appHel2.utils) === null || _engineContext$appHel2 === void 0 ? void 0 : _engineContext$appHel2.interaction,
94
+ isPiPaymentEnabled: Boolean((_engineContext$appHel3 = engineContext.appHelper) === null || _engineContext$appHel3 === void 0 || (_engineContext$appHel3 = _engineContext$appHel3.utils) === null || _engineContext$appHel3 === void 0 || (_engineContext$appHel3 = _engineContext$appHel3.businessUtils) === null || _engineContext$appHel3 === void 0 || (_engineContext$appHel4 = _engineContext$appHel3.isPiPaymentEnabled) === null || _engineContext$appHel4 === void 0 ? void 0 : _engineContext$appHel4.call(_engineContext$appHel3)),
95
+ loadDetail: context.sales.loadDetail,
96
+ method,
97
+ rawMethod,
98
+ runtime
99
+ });
188
100
  });
189
101
  return function payEftpos(_x) {
190
- return _ref5.apply(this, arguments);
102
+ return _ref3.apply(this, arguments);
191
103
  };
192
104
  }(),
193
105
  requestStaffPaymentApproval: function() {
194
- var _ref6 = _asyncToGenerator(function* ({ paymentMethodId }) {
106
+ var _ref4 = _asyncToGenerator(function* ({ paymentMethodId }) {
107
+ var _window;
195
108
  const method = methodsRef.current.find((item) => item.id === paymentMethodId);
196
109
  const amount = currentAmount(context);
197
110
  if (!method || method.eftpos || amount <= 0) return failed("staffPaymentAuthorizationInvalid", "back");
111
+ const globalApp = (_window = window) === null || _window === void 0 || (_window = _window.app) === null || _window === void 0 || (_window = _window.applicationManager) === null || _window === void 0 ? void 0 : _window.get("global");
112
+ if (typeof (globalApp === null || globalApp === void 0 ? void 0 : globalApp.runFunction) !== "function") return failed("staffPaymentAuthorizationUnavailable", "staff");
113
+ const authorization = authorizationStore.begin({
114
+ amount,
115
+ currencySymbol,
116
+ member: context.customer.selected != null
117
+ });
118
+ if (!authorization) return failed("staffPaymentAuthorizationInProgress", "retry");
198
119
  try {
199
- var _baseSales$getOtherPa, _window;
120
+ var _baseSales$getOtherPa;
200
121
  const otherParams = (yield baseSales === null || baseSales === void 0 || (_baseSales$getOtherPa = baseSales.getOtherParams) === null || _baseSales$getOtherPa === void 0 ? void 0 : _baseSales$getOtherPa.call(baseSales)) || (baseSales === null || baseSales === void 0 ? void 0 : baseSales.otherParams) || {};
201
- const globalApp = (_window = window) === null || _window === void 0 || (_window = _window.app) === null || _window === void 0 || (_window = _window.applicationManager) === null || _window === void 0 ? void 0 : _window.get("global");
202
- if (typeof (globalApp === null || globalApp === void 0 ? void 0 : globalApp.runFunction) !== "function") return failed("staffPaymentAuthorizationUnavailable", "staff");
203
- const notifyClosed = () => {
204
- authorizationListenersRef.current.forEach((listener) => listener({ status: "cancelled" }));
205
- };
206
122
  const result = yield globalApp.runFunction("authorizeAction", {
207
123
  params: {
208
124
  action: "pay",
@@ -211,27 +127,40 @@ function HDLKioskPaymentRuntime({ context, controllerRef }) {
211
127
  paymentMethodType: method.type,
212
128
  amount
213
129
  },
214
- onClose: notifyClosed
130
+ onClose: () => authorizationStore.cancel(authorization)
215
131
  });
216
- if (isStaffPaymentAuthorizationCancelled(result)) return failed("staffPaymentAuthorizationCancelled", "retry");
217
- if ((result === null || result === void 0 ? void 0 : result.status) !== "success") return failed("staffPaymentAuthorizationDispatchFailed", "retry", result.msg);
132
+ if (authorizationStore.isSettling(authorization)) return {
133
+ status: "succeeded",
134
+ data: void 0
135
+ };
136
+ if (isStaffPaymentAuthorizationCancelled(result)) {
137
+ authorizationStore.cancel(authorization);
138
+ return failed("staffPaymentAuthorizationCancelled", "retry");
139
+ }
140
+ if ((result === null || result === void 0 ? void 0 : result.status) !== "success") {
141
+ authorizationStore.fail(authorization);
142
+ return failed("staffPaymentAuthorizationDispatchFailed", "retry", result.msg);
143
+ }
218
144
  return {
219
145
  status: "succeeded",
220
146
  data: void 0
221
147
  };
222
148
  } catch (error) {
149
+ if (authorizationStore.isSettling(authorization)) return {
150
+ status: "succeeded",
151
+ data: void 0
152
+ };
153
+ authorizationStore.fail(authorization);
223
154
  return failed("staffPaymentAuthorizationDispatchFailed", "retry", error);
224
155
  }
225
156
  });
226
157
  return function requestStaffPaymentApproval(_x2) {
227
- return _ref6.apply(this, arguments);
158
+ return _ref4.apply(this, arguments);
228
159
  };
229
160
  }(),
230
- subscribeStaffPaymentAuthorizationResult: (listener) => {
231
- authorizationListenersRef.current.add(listener);
232
- return () => authorizationListenersRef.current.delete(listener);
233
- }
161
+ subscribeStaffPaymentAuthorizationResult: authorizationStore.subscribe
234
162
  }), [
163
+ authorizationStore,
235
164
  baseSales,
236
165
  context,
237
166
  currencySymbol,
@@ -239,32 +168,50 @@ function HDLKioskPaymentRuntime({ context, controllerRef }) {
239
168
  ]);
240
169
  useEffect(() => {
241
170
  let cleanup;
171
+ let globalApp;
242
172
  try {
243
173
  var _window2, _app$applicationManag, _globalApp$runFunctio;
244
174
  const app = (_window2 = window) === null || _window2 === void 0 ? void 0 : _window2.app;
245
- const globalApp = app === null || app === void 0 || (_app$applicationManag = app.applicationManager) === null || _app$applicationManag === void 0 ? void 0 : _app$applicationManag.get("global");
175
+ globalApp = app === null || app === void 0 || (_app$applicationManag = app.applicationManager) === null || _app$applicationManag === void 0 ? void 0 : _app$applicationManag.get("global");
246
176
  cleanup = globalApp === null || globalApp === void 0 || (_globalApp$runFunctio = globalApp.runFunction) === null || _globalApp$runFunctio === void 0 ? void 0 : _globalApp$runFunctio.call(globalApp, "listenExternalCommand", {
247
177
  app,
248
- handler: (command) => {
249
- var _globalApp$runFunctio2, _command$params;
250
- if (command.command === "authorization_close") {
251
- authorizationListenersRef.current.forEach((listener) => listener({ status: "cancelled" }));
252
- return;
253
- }
254
- if (command.command !== "payment_result") return;
255
- globalApp === null || globalApp === void 0 || (_globalApp$runFunctio2 = globalApp.runFunction) === null || _globalApp$runFunctio2 === void 0 || _globalApp$runFunctio2.call(globalApp, "closeAuthorization");
256
- const status = (_command$params = command.params) === null || _command$params === void 0 ? void 0 : _command$params.status;
257
- authorizationListenersRef.current.forEach((listener) => {
258
- var _command$params2;
259
- return listener({ status: ((_command$params2 = command.params) === null || _command$params2 === void 0 ? void 0 : _command$params2.ok) === true && status === "success" ? "succeeded" : status === "cancelled" ? "cancelled" : "failed" });
178
+ handler: function() {
179
+ var _ref5 = _asyncToGenerator(function* (command) {
180
+ if (command.command !== "payment_result") return;
181
+ const authorization = authorizationStore.beginSettlement();
182
+ if (!authorization) return;
183
+ const outcomeContext = staffPaymentOutcomeContextRef.current;
184
+ const result = yield resolveStaffPaymentResult({
185
+ params: command.params || {},
186
+ closeAuthorization: () => {
187
+ var _globalApp$runFunctio2;
188
+ return globalApp === null || globalApp === void 0 || (_globalApp$runFunctio2 = globalApp.runFunction) === null || _globalApp$runFunctio2 === void 0 ? void 0 : _globalApp$runFunctio2.call(globalApp, "closeAuthorization");
189
+ },
190
+ finalizeOutcome: () => finalizeStaffPaymentOutcome({
191
+ params: command.params || {},
192
+ baseSales: outcomeContext.baseSales,
193
+ loadDetail: outcomeContext.loadDetail,
194
+ fallbackAmount: authorization.amount,
195
+ currencySymbol: authorization.currencySymbol,
196
+ member: authorization.member
197
+ })
198
+ });
199
+ authorizationStore.complete(authorization, result);
260
200
  });
261
- }
201
+ return function handler(_x3) {
202
+ return _ref5.apply(this, arguments);
203
+ };
204
+ }()
262
205
  });
263
206
  } catch (_unused) {}
264
207
  return () => {
265
208
  if (typeof cleanup === "function") cleanup();
209
+ if (authorizationStore.dispose()) try {
210
+ var _globalApp$runFunctio3;
211
+ globalApp === null || globalApp === void 0 || (_globalApp$runFunctio3 = globalApp.runFunction) === null || _globalApp$runFunctio3 === void 0 || _globalApp$runFunctio3.call(globalApp, "closeAuthorization");
212
+ } catch (_unused2) {}
266
213
  };
267
- }, []);
214
+ }, [authorizationStore]);
268
215
  useEffect(() => {
269
216
  controllerRef.current = controller;
270
217
  return () => {