@pisell/private-materials 6.12.286 → 6.12.288

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 (41) 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 +14 -14
  6. package/build/lowcode/view.js +14 -14
  7. package/es/components/HDLKiosk/ui/entry/Screen/assets/PHOSPHOR-LICENSE +21 -21
  8. package/es/plus/invoice/ReceiptRenderer.js +86 -42
  9. package/es/plus/invoice/VirtualCurrencyLines.js +21 -8
  10. package/es/plus/invoice/VirtualCurrencyReceiptRenderer.js +21 -10
  11. package/es/plus/invoice/invoiceVisibility.js +94 -0
  12. package/es/plus/invoice/receipt.js +4 -3
  13. package/es/plus/piPaymentUI/eftpos/logger.js +10 -7
  14. package/es/plus/piPaymentUI/sendWarningLog.js +33 -22
  15. package/es/plus/saasDevice/devicePasscodes/model.js +4 -4
  16. package/es/plus/saleDetail/actions/index.js +11 -4
  17. package/es/plus/saleDetail/serve.js +7 -8
  18. package/es/plus/saleDetail/tmpl/B/components/Invoice/VirtualCurrencyInvoice.js +1 -1
  19. package/es/plus/saleDetail/tmpl/B/components/Invoice/index.js +29 -5
  20. package/es/plus/saleDetail/tmpl/B/components/Invoice/useInvoiceReceiptPreview.js +85 -43
  21. package/es/plus/salesSdk/context/SalesSdkCartContext.js +5 -1
  22. package/es/plus/salesSdk/context/SalesSdkProvider.js +3 -0
  23. package/es/plus/salesSdk/utils/receiptPrintWarning.js +16 -0
  24. package/es/plus/walletPassGallery/components/timelineSection/index.js +4 -4
  25. package/lib/components/HDLKiosk/ui/entry/Screen/assets/PHOSPHOR-LICENSE +21 -21
  26. package/lib/plus/invoice/ReceiptRenderer.js +86 -42
  27. package/lib/plus/invoice/VirtualCurrencyLines.js +21 -8
  28. package/lib/plus/invoice/VirtualCurrencyReceiptRenderer.js +21 -10
  29. package/lib/plus/invoice/invoiceVisibility.js +99 -0
  30. package/lib/plus/invoice/receipt.js +4 -3
  31. package/lib/plus/piPaymentUI/eftpos/logger.js +10 -7
  32. package/lib/plus/piPaymentUI/sendWarningLog.js +32 -20
  33. package/lib/plus/saleDetail/actions/index.js +11 -4
  34. package/lib/plus/saleDetail/serve.js +7 -8
  35. package/lib/plus/saleDetail/tmpl/B/components/Invoice/VirtualCurrencyInvoice.js +1 -1
  36. package/lib/plus/saleDetail/tmpl/B/components/Invoice/index.js +29 -5
  37. package/lib/plus/saleDetail/tmpl/B/components/Invoice/useInvoiceReceiptPreview.js +85 -43
  38. package/lib/plus/salesSdk/context/SalesSdkCartContext.js +5 -1
  39. package/lib/plus/salesSdk/context/SalesSdkProvider.js +3 -0
  40. package/lib/plus/salesSdk/utils/receiptPrintWarning.js +16 -0
  41. package/package.json +3 -3
@@ -60,13 +60,14 @@ var PiPaymentLogger = class PiPaymentLogger {
60
60
  /** 立即取走缓冲并异步上报;关闭、卸载及快照调用共享一次性标记。 */
61
61
  "reportToFeishu",
62
62
  () => {
63
+ var _this$shared3, _this$shared3$splice;
63
64
  if (this.shared.reported) return;
64
65
  this.shared.reported = true;
65
- const timeline = this.shared.timeline.splice(0);
66
+ const timeline = (_this$shared3 = this.shared) === null || _this$shared3 === void 0 || (_this$shared3 = _this$shared3.timeline) === null || _this$shared3 === void 0 || (_this$shared3$splice = _this$shared3.splice) === null || _this$shared3$splice === void 0 ? void 0 : _this$shared3$splice.call(_this$shared3, 0);
66
67
  if (!timeline.length) return;
67
68
  try {
68
- var _this$context, _this$context2, _this$context3, _this$context4, _this$context5;
69
- const _this$shared$context = this.shared.context, { transactionNumber, attemptIndex } = _this$shared$context, common = _objectWithoutProperties(_this$shared$context, _excluded);
69
+ var _this, _this$context, _this$context2, _this$context3, _this$context4, _this$context5;
70
+ const _ref = ((_this = this) === null || _this === void 0 || (_this = _this.shared) === null || _this === void 0 ? void 0 : _this.context) || {}, { transactionNumber, attemptIndex } = _ref, common = _objectWithoutProperties(_ref, _excluded);
70
71
  Promise.resolve(sendWarningLog({
71
72
  title: `Pi_${common.provider}_${common.salesId || ""}`,
72
73
  content: [
@@ -96,14 +97,16 @@ var PiPaymentLogger = class PiPaymentLogger {
96
97
  }
97
98
  ]
98
99
  })).catch(() => void 0);
99
- } catch (_unused4) {}
100
+ } catch (error) {
101
+ console.warn("[PiPayment] 飞书上报准备失败", error);
102
+ }
100
103
  }
101
104
  );
102
105
  _defineProperty(this, "addLog", (entry) => {
103
106
  let host;
104
107
  try {
105
108
  host = this.getHostLogger();
106
- } catch (_unused5) {}
109
+ } catch (_unused4) {}
107
110
  try {
108
111
  var _this$context$salesId, _this$context$payment, _this$context$deviceN, _this$context$provide, _this$context$session, _this$context$transac, _this$context$attempt;
109
112
  writePiPaymentEftposLog(host, _objectSpread2(_objectSpread2({}, entry), {}, { metadata: {
@@ -117,7 +120,7 @@ var PiPaymentLogger = class PiPaymentLogger {
117
120
  attemptIndex: (_this$context$attempt = this.context.attemptIndex) !== null && _this$context$attempt !== void 0 ? _this$context$attempt : null,
118
121
  sequence: ++this.shared.value
119
122
  } }), this.collect);
120
- } catch (_unused6) {}
123
+ } catch (_unused5) {}
121
124
  });
122
125
  this.context = _objectSpread2({}, context);
123
126
  }
@@ -130,7 +133,7 @@ var PiPaymentLogger = class PiPaymentLogger {
130
133
  let host;
131
134
  try {
132
135
  host = this.getHostLogger();
133
- } catch (_unused7) {}
136
+ } catch (_unused6) {}
134
137
  return new PiPaymentLogger(() => host, this.context, this.shared);
135
138
  }
136
139
  };
@@ -1,4 +1,5 @@
1
1
  import { _asyncToGenerator } from "../../_virtual/_@oxc-project_runtime@0.122.0/helpers/asyncToGenerator.js";
2
+ import { getPisellUtilsConfig } from "@pisell/utils";
2
3
  //#region src/plus/piPaymentUI/sendWarningLog.ts
3
4
  /** 支付专用机器人完整 webhook URL(包含独立 key);留空时不上报。 */
4
5
  const piPaymentWebhook = {
@@ -6,32 +7,42 @@ const piPaymentWebhook = {
6
7
  prod: "https://open.feishu.cn/open-apis/bot/v2/hook/1b16d0e2-e7aa-4803-a900-845ca0ff492d"
7
8
  };
8
9
  /** PiPaymentUI 自己的飞书上报入口,不使用公共告警机器人。 */
9
- const sendWarningLog = function() {
10
+ const sendWarningLog$1 = function() {
10
11
  var _ref = _asyncToGenerator(function* ({ title, content }) {
11
- var _process;
12
- const apiUrl = ((_process = process) === null || _process === void 0 || (_process = _process.env) === null || _process === void 0 ? void 0 : _process.NODE_ENV) === "development" ? piPaymentWebhook.test : piPaymentWebhook.prod;
13
- if (!apiUrl) return;
14
- return (yield fetch(apiUrl, {
15
- method: "POST",
16
- headers: { "Content-Type": "application/json" },
17
- body: JSON.stringify({
18
- msg_type: "post",
19
- content: { post: { zh_cn: {
20
- title,
21
- content: content.map(({ key, value }) => [{
22
- tag: "text",
23
- text: `${key}: `
24
- }, {
25
- tag: "text",
26
- text: value
27
- }])
28
- } } }
29
- })
30
- })).json();
12
+ let env;
13
+ try {
14
+ var _appHelper, _getPisellUtilsConfig;
15
+ const hostEnv = typeof window === "undefined" ? void 0 : (_appHelper = window.__appHelper) === null || _appHelper === void 0 || (_appHelper = _appHelper.constants) === null || _appHelper === void 0 ? void 0 : _appHelper.env;
16
+ env = hostEnv !== null && hostEnv !== void 0 ? hostEnv : (_getPisellUtilsConfig = getPisellUtilsConfig()) === null || _getPisellUtilsConfig === void 0 ? void 0 : _getPisellUtilsConfig.env;
17
+ const apiUrl = env === "dev" || env === "pre" || env === "release" ? piPaymentWebhook.test : piPaymentWebhook.prod;
18
+ return yield (yield fetch(apiUrl, {
19
+ method: "POST",
20
+ headers: { "Content-Type": "application/json" },
21
+ body: JSON.stringify({
22
+ msg_type: "post",
23
+ content: { post: { zh_cn: {
24
+ title,
25
+ content: content.map(({ key, value }) => [{
26
+ tag: "text",
27
+ text: `${key}: `
28
+ }, {
29
+ tag: "text",
30
+ text: `${value}`
31
+ }])
32
+ } } }
33
+ })
34
+ })).json();
35
+ } catch (error) {
36
+ console.warn("[PiPayment] 飞书上报失败", {
37
+ env,
38
+ error
39
+ });
40
+ return;
41
+ }
31
42
  });
32
43
  return function sendWarningLog(_x) {
33
44
  return _ref.apply(this, arguments);
34
45
  };
35
46
  }();
36
47
  //#endregion
37
- export { sendWarningLog };
48
+ export { sendWarningLog$1 as sendWarningLog };
@@ -1,10 +1,10 @@
1
1
  import { _objectSpread2 } from "../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectSpread2.js";
2
2
  import dayjs from "dayjs";
3
- import timezonePlugin from "dayjs/plugin/timezone";
4
- import utcPlugin from "dayjs/plugin/utc";
3
+ import timezone from "dayjs/plugin/timezone";
4
+ import utc from "dayjs/plugin/utc";
5
5
  //#region src/plus/saasDevice/devicePasscodes/model.ts
6
- dayjs.extend(utcPlugin);
7
- dayjs.extend(timezonePlugin);
6
+ dayjs.extend(utc);
7
+ dayjs.extend(timezone);
8
8
  const INITIAL_DEVICE_PASSCODE_STATE = {
9
9
  deviceIds: [],
10
10
  devicesById: {}
@@ -12,6 +12,7 @@ import locales_default from "../../../components/checkout/locales.js";
12
12
  import { closePaymentResultToastV2 } from "../../../components/checkout/components/PaymentResultToastV2/PaymentResultToastV2Provider.js";
13
13
  import clearCartModal_default from "../../../components/booking/components/clearCartModal/index.js";
14
14
  import customiseItemModal_default from "../../../components/booking/components/customiseItemModal/index.js";
15
+ import { getReceiptPrintWarning } from "../../salesSdk/utils/receiptPrintWarning.js";
15
16
  import { isFulfillmentTimingBooking } from "../../salesSdk/utils/fulfillmentTimingBooking.js";
16
17
  import { useSalesSdkGlobalScanActivity } from "../../salesSdk/context/SalesSdkGlobalScanActivityContext.js";
17
18
  import { getClientDisplayName, isWalkInCustomer, normalizeCustomer } from "../components/Client/utils.js";
@@ -747,12 +748,14 @@ function SaleOrderActionProvider({ actionConfigs, actionOverrides, children, con
747
748
  });
748
749
  const handleCashPaymentSuccess = useMemoizedFn(function() {
749
750
  var _ref9 = _asyncToGenerator(function* (result) {
750
- var _result$syncResult$su, _result$syncResult, _result$payment;
751
+ var _result$syncResult$su, _result$syncResult, _result$syncResult$su2, _result$syncResult2, _result$payment;
751
752
  setShowCashPayment(false);
752
753
  setSelectedCashPaymentMethodId(void 0);
754
+ const receiptWarning = getReceiptPrintWarning((_result$syncResult$su = result === null || result === void 0 || (_result$syncResult = result.syncResult) === null || _result$syncResult === void 0 ? void 0 : _result$syncResult.submitResult) !== null && _result$syncResult$su !== void 0 ? _result$syncResult$su : result, locales.getLocale());
755
+ if (receiptWarning) Toast.info(receiptWarning);
753
756
  const externalRequestId = cashExternalRequestIdRef.current;
754
757
  cashExternalRequestIdRef.current = void 0;
755
- const orderId = resolveSaleDetailOrderIdFromSalesResult(sales, (_result$syncResult$su = result === null || result === void 0 || (_result$syncResult = result.syncResult) === null || _result$syncResult === void 0 ? void 0 : _result$syncResult.submitResult) !== null && _result$syncResult$su !== void 0 ? _result$syncResult$su : result);
758
+ const orderId = resolveSaleDetailOrderIdFromSalesResult(sales, (_result$syncResult$su2 = result === null || result === void 0 || (_result$syncResult2 = result.syncResult) === null || _result$syncResult2 === void 0 ? void 0 : _result$syncResult2.submitResult) !== null && _result$syncResult$su2 !== void 0 ? _result$syncResult$su2 : result);
756
759
  const changeGivenAmount = Number((result === null || result === void 0 || (_result$payment = result.payment) === null || _result$payment === void 0 || (_result$payment = _result$payment.metadata) === null || _result$payment === void 0 ? void 0 : _result$payment.change_given_amount) || 0);
757
760
  const outcome = resolveSaleOrderQuickPaymentOutcome(result);
758
761
  settleExternalPayment(externalRequestId, {
@@ -858,7 +861,7 @@ function SaleOrderActionProvider({ actionConfigs, actionOverrides, children, con
858
861
  };
859
862
  }();
860
863
  try {
861
- var _engineContext$appHel17, _engineContext$appHel18, _paymentRuntimeRef$cu, _result$syncResult$su2, _result$syncResult2;
864
+ var _engineContext$appHel17, _engineContext$appHel18, _paymentRuntimeRef$cu, _result$syncResult$su3, _result$syncResult3, _result$syncResult$su4, _result$syncResult4;
862
865
  const method = methodOverride || paymentMethods.find((item) => String(item.code || "").toUpperCase() === code);
863
866
  if (!method) throw new Error(`Payment method ${code} is unavailable.`);
864
867
  baseSales = sales.bookingTicket;
@@ -930,8 +933,10 @@ function SaleOrderActionProvider({ actionConfigs, actionOverrides, children, con
930
933
  serviceCharge: runtimeResult.serviceCharge,
931
934
  metadata: runtimeResult.metadata
932
935
  });
933
- const orderId = resolveSaleDetailOrderIdFromSalesResult(sales, (_result$syncResult$su2 = result === null || result === void 0 || (_result$syncResult2 = result.syncResult) === null || _result$syncResult2 === void 0 ? void 0 : _result$syncResult2.submitResult) !== null && _result$syncResult$su2 !== void 0 ? _result$syncResult$su2 : result);
936
+ const orderId = resolveSaleDetailOrderIdFromSalesResult(sales, (_result$syncResult$su3 = result === null || result === void 0 || (_result$syncResult3 = result.syncResult) === null || _result$syncResult3 === void 0 ? void 0 : _result$syncResult3.submitResult) !== null && _result$syncResult$su3 !== void 0 ? _result$syncResult$su3 : result);
934
937
  const outcome = resolveSaleOrderQuickPaymentOutcome(result);
938
+ const receiptWarning = getReceiptPrintWarning((_result$syncResult$su4 = result === null || result === void 0 || (_result$syncResult4 = result.syncResult) === null || _result$syncResult4 === void 0 ? void 0 : _result$syncResult4.submitResult) !== null && _result$syncResult$su4 !== void 0 ? _result$syncResult$su4 : result, locales.getLocale());
939
+ if (receiptWarning) Toast.info(receiptWarning);
935
940
  settleExternalPayment(externalRequestId, {
936
941
  status: "success",
937
942
  result
@@ -1013,6 +1018,8 @@ function SaleOrderActionProvider({ actionConfigs, actionOverrides, children, con
1013
1018
  };
1014
1019
  }
1015
1020
  const submitResult = result === null || result === void 0 ? void 0 : result.submitResult;
1021
+ const receiptWarning = getReceiptPrintWarning(submitResult, locales.getLocale());
1022
+ if (receiptWarning) Toast.info(receiptWarning);
1016
1023
  if (!isSalesOrderSubmitSuccess(submitResult)) throw new Error(String((submitResult === null || submitResult === void 0 ? void 0 : submitResult.message) || (submitResult === null || submitResult === void 0 ? void 0 : submitResult.msg) || "Order confirmation failed"));
1017
1024
  const orderId = resolveSaleDetailOrderIdFromSalesResult(sales, submitResult);
1018
1025
  presentBaseSalesPaymentResult({
@@ -21,18 +21,14 @@ const getOrderSmallTicketData = function() {
21
21
  return _ref3.apply(this, arguments);
22
22
  };
23
23
  }();
24
- /**
25
- * 通过 PisellOS 按本地订单即时重建 Web Invoice 所需的小票快照。
26
- * 该接口只返回数据,不会派发打印任务。
27
- */
28
24
  const getLocalOrderReceiptSnapshot = function() {
29
- var _ref5 = _asyncToGenerator(function* (orderId, locales = []) {
25
+ var _ref5 = _asyncToGenerator(function* (orderId, locales = [], templateSettings) {
30
26
  var _ref4, _response$data$data2, _response$data2;
31
- const response = yield request.getRequest().post("/shop/local/order-receipt-snapshot", {
27
+ const response = yield request.getRequest().post("/shop/local/order-receipt-snapshot", _objectSpread2({
32
28
  order_id: orderId,
33
29
  lookup_order_from_db: 1,
34
30
  locales
35
- }, {
31
+ }, templateSettings ? { template_settings: { modules: templateSettings.module } } : {}), {
36
32
  fullResult: true,
37
33
  isShopApi: true,
38
34
  osServer: true,
@@ -40,7 +36,10 @@ const getLocalOrderReceiptSnapshot = function() {
40
36
  });
41
37
  const payload = (_ref4 = (_response$data$data2 = response === null || response === void 0 || (_response$data2 = response.data) === null || _response$data2 === void 0 ? void 0 : _response$data2.data) !== null && _response$data$data2 !== void 0 ? _response$data$data2 : response === null || response === void 0 ? void 0 : response.data) !== null && _ref4 !== void 0 ? _ref4 : response;
42
38
  const smallTicketData = payload === null || payload === void 0 ? void 0 : payload.small_ticket_data;
43
- return smallTicketData && typeof smallTicketData === "object" ? smallTicketData : null;
39
+ return smallTicketData && typeof smallTicketData === "object" && !Array.isArray(smallTicketData) ? _objectSpread2({
40
+ small_ticket_data: smallTicketData,
41
+ template_visibility_applied: payload.template_visibility_applied === true
42
+ }, payload.source && typeof payload.source === "object" && !Array.isArray(payload.source) ? { source: payload.source } : {}) : null;
44
43
  });
45
44
  return function getLocalOrderReceiptSnapshot(_x2) {
46
45
  return _ref5.apply(this, arguments);
@@ -3,9 +3,9 @@ import PisellSaleSummaryDetail from "../../../../../pisellSaleSummaryDetail/inde
3
3
  import { Contact } from "../../../../components/Contact/index.js";
4
4
  import { useEditBookingAction } from "../../../../components/DetailActions/index.js";
5
5
  import { useSaleSummaryDetailSnapshot } from "../../../../components/Summary/useSaleSummaryDetailSnapshot.js";
6
+ import { buildInvoiceBookingRows, buildInvoiceOpenItemCard } from "./utils.js";
6
7
  import { InvoiceBookingSection, InvoiceOpenItemsSection } from "../../../../../invoice/VirtualCurrencyLines.js";
7
8
  import { SummaryInfoBlocks } from "../SummaryInfoBlocks/index.js";
8
- import { buildInvoiceBookingRows, buildInvoiceOpenItemCard } from "./utils.js";
9
9
  import React, { useMemo } from "react";
10
10
  import { locales } from "@pisell/utils";
11
11
  import { Iconfont } from "@pisell/materials";
@@ -1,7 +1,8 @@
1
- import { isVirtualSettlementTempOrder } from "../../../../../multiCurrencySettlement/index.js";
1
+ import { _objectSpread2 } from "../../../../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectSpread2.js";
2
2
  import { getReceiptLabel } from "../../../../../invoice/receipt.js";
3
3
  import { InvoiceReceiptRenderer } from "../../../../../invoice/ReceiptRenderer.js";
4
4
  import { InvoiceReceiptSkeleton } from "../../../../../invoice/InvoiceReceiptSkeleton.js";
5
+ import { VirtualCurrencyReceiptRenderer } from "../../../../../invoice/VirtualCurrencyReceiptRenderer.js";
5
6
  import { useInvoiceReceiptPreview } from "./useInvoiceReceiptPreview.js";
6
7
  import { VirtualCurrencyInvoice } from "./VirtualCurrencyInvoice.js";
7
8
  import React, { useRef } from "react";
@@ -9,24 +10,47 @@ import { locales } from "@pisell/utils";
9
10
  import "./index.less";
10
11
  //#region src/plus/saleDetail/tmpl/B/components/Invoice/index.tsx
11
12
  const PREFIX = "pisell-sale-detail-invoice";
12
- function InvoiceReceiptPreview({ context }) {
13
+ function applyVirtualHostVisibility(receipt, hidden) {
14
+ return _objectSpread2(_objectSpread2({}, receipt), {}, {
15
+ orderNote: hidden.includes("orderNote") ? void 0 : receipt.orderNote,
16
+ paymentNotice: hidden.includes("amountDetails") ? void 0 : receipt.paymentNotice,
17
+ secondary: receipt.secondary ? applyVirtualHostVisibility(receipt.secondary, hidden) : void 0
18
+ });
19
+ }
20
+ function InvoiceReceiptPreview(props) {
13
21
  var _locales$getLocale;
22
+ const { context, moduleConfig } = props;
14
23
  const receiptRef = useRef(null);
15
- const { error, loading, receipt, retry } = useInvoiceReceiptPreview(context);
24
+ const { error, loading, receipt, source, retry, useLegacyVirtualCurrencyInvoice, useVirtualCurrencyReceipt } = useInvoiceReceiptPreview(context);
16
25
  const appLocale = ((_locales$getLocale = locales.getLocale) === null || _locales$getLocale === void 0 ? void 0 : _locales$getLocale.call(locales)) || "en";
26
+ const hidden = (moduleConfig === null || moduleConfig === void 0 ? void 0 : moduleConfig.hidden) || [];
27
+ const moduleOverrides = {};
28
+ if (hidden.includes("customer")) moduleOverrides.customer = null;
29
+ if (hidden.includes("cartItems")) moduleOverrides.line_groups = null;
30
+ if (hidden.includes("amountDetails")) {
31
+ moduleOverrides.settlement = null;
32
+ moduleOverrides.payment = null;
33
+ moduleOverrides.total_savings = null;
34
+ }
35
+ if (!loading && useLegacyVirtualCurrencyInvoice) return /* @__PURE__ */ React.createElement(VirtualCurrencyInvoice, props);
17
36
  return /* @__PURE__ */ React.createElement("main", { className: "pisell-sale-detail-main pisell-sale-detail-invoice-main" }, /* @__PURE__ */ React.createElement("div", { className: "pisell-sale-detail-cart-scroll-panel" }, /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}__receipt-stage` }, loading ? /* @__PURE__ */ React.createElement(InvoiceReceiptSkeleton, null) : null, !loading && error ? /* @__PURE__ */ React.createElement("div", {
18
37
  className: `${PREFIX}__preview-state`,
19
38
  role: "alert"
20
39
  }, /* @__PURE__ */ React.createElement("span", null, getReceiptLabel(appLocale, "Receipt preview is unavailable.")), /* @__PURE__ */ React.createElement("button", {
21
40
  onClick: retry,
22
41
  type: "button"
23
- }, getReceiptLabel(appLocale, "Retry"))) : null, !loading && receipt ? /* @__PURE__ */ React.createElement(InvoiceReceiptRenderer, {
42
+ }, getReceiptLabel(appLocale, "Retry"))) : null, !loading && receipt ? useVirtualCurrencyReceipt && source ? /* @__PURE__ */ React.createElement(VirtualCurrencyReceiptRenderer, {
43
+ receipt: applyVirtualHostVisibility(receipt, hidden),
44
+ source,
45
+ moduleOverrides,
46
+ ref: receiptRef
47
+ }) : /* @__PURE__ */ React.createElement(InvoiceReceiptRenderer, {
24
48
  receipt,
25
49
  ref: receiptRef
26
50
  }) : null)));
27
51
  }
28
52
  function Invoice(props) {
29
- return isVirtualSettlementTempOrder(props.context.sales.tempOrder) ? /* @__PURE__ */ React.createElement(VirtualCurrencyInvoice, props) : /* @__PURE__ */ React.createElement(InvoiceReceiptPreview, props);
53
+ return /* @__PURE__ */ React.createElement(InvoiceReceiptPreview, props);
30
54
  }
31
55
  //#endregion
32
56
  export { Invoice };
@@ -2,10 +2,20 @@ import useEngineContext, { usePlatform } from "../../../../../../hooks/useEngine
2
2
  import { _objectSpread2 } from "../../../../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectSpread2.js";
3
3
  import { _asyncToGenerator } from "../../../../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/asyncToGenerator.js";
4
4
  import useLocale from "../../../../../../hooks/useLocale.js";
5
+ import { isVirtualSettlementTempOrder } from "../../../../../multiCurrencySettlement/index.js";
5
6
  import { getLocalOrderReceiptSnapshot, getOrderSmallTicketData } from "../../../../serve.js";
7
+ import { hasInvoiceDetailSettings, requiresInvoiceDataFiltering } from "../../../../../invoice/invoiceVisibility.js";
6
8
  import { buildInvoiceReceiptViewModel, formatReceiptPreviewTime, isSmallTicketData, resolveInvoiceLayoutConfig, resolveSmallTicketData, selectSmallTicketLocale } from "../../../../../invoice/receipt.js";
7
9
  import { useEffect, useMemo, useState } from "react";
8
10
  //#region src/plus/saleDetail/tmpl/B/components/Invoice/useInvoiceReceiptPreview.ts
11
+ const LOADING_STATE = {
12
+ error: null,
13
+ loading: true,
14
+ receipt: null,
15
+ source: null,
16
+ useLegacyVirtualCurrencyInvoice: false,
17
+ useVirtualCurrencyReceipt: false
18
+ };
9
19
  function getOrderId(context) {
10
20
  var _ref, _context$sales$salesD, _context$sales$salesD2, _context$sales$tempOr;
11
21
  return (_ref = (_context$sales$salesD = (_context$sales$salesD2 = context.sales.salesDetail) === null || _context$sales$salesD2 === void 0 || (_context$sales$salesD2 = _context$sales$salesD2.header) === null || _context$sales$salesD2 === void 0 ? void 0 : _context$sales$salesD2.order_id) !== null && _context$sales$salesD !== void 0 ? _context$sales$salesD : (_context$sales$tempOr = context.sales.tempOrder) === null || _context$sales$tempOr === void 0 ? void 0 : _context$sales$tempOr.order_id) !== null && _ref !== void 0 ? _ref : null;
@@ -35,86 +45,118 @@ function useInvoiceReceiptPreview(context) {
35
45
  const [revision, setRevision] = useState(0);
36
46
  const orderId = getOrderId(context);
37
47
  const previewCreatedAt = useMemo(() => /* @__PURE__ */ new Date(), [orderId, revision]);
38
- const [state, setState] = useState({
39
- error: null,
40
- loading: true,
41
- receipt: null
42
- });
43
48
  const salesDetail = context.sales.salesDetail;
44
49
  const tempOrder = context.sales.tempOrder;
45
50
  const salesModule = context.sales.salesModule;
51
+ const scope = useMemo(() => ({
52
+ appLocale,
53
+ engineContext,
54
+ orderId,
55
+ platform,
56
+ previewCreatedAt,
57
+ salesDetail,
58
+ salesModule,
59
+ tempOrder
60
+ }), [
61
+ appLocale,
62
+ engineContext,
63
+ orderId,
64
+ platform,
65
+ previewCreatedAt,
66
+ salesDetail,
67
+ salesModule,
68
+ tempOrder
69
+ ]);
70
+ const [state, setState] = useState(_objectSpread2(_objectSpread2({}, LOADING_STATE), {}, { scope: null }));
46
71
  useEffect(() => {
47
72
  let cancelled = false;
48
- setState({
49
- error: null,
50
- loading: true,
51
- receipt: null
52
- });
73
+ setState(_objectSpread2(_objectSpread2({}, LOADING_STATE), {}, { scope }));
53
74
  (function() {
54
75
  var _ref3 = _asyncToGenerator(function* () {
76
+ const { appLocale, engineContext, orderId, platform, previewCreatedAt, salesDetail, salesModule, tempOrder } = scope;
77
+ const layout = yield resolveInvoiceLayoutConfig(salesModule);
78
+ if (cancelled) return null;
79
+ const mustFilter = requiresInvoiceDataFiltering(layout);
80
+ const useSharedConfig = hasInvoiceDetailSettings(layout) || mustFilter;
81
+ const isVirtualOrder = isVirtualSettlementTempOrder(tempOrder) || isVirtualSettlementTempOrder(salesDetail === null || salesDetail === void 0 ? void 0 : salesDetail.raw);
82
+ const legacyVirtualResult = {
83
+ receipt: null,
84
+ source: null,
85
+ useLegacyVirtualCurrencyInvoice: true,
86
+ useVirtualCurrencyReceipt: false
87
+ };
88
+ if (isVirtualOrder && !useSharedConfig) return legacyVirtualResult;
89
+ const requiresSource = isVirtualOrder && useSharedConfig;
55
90
  const embeddedSnapshot = resolveSmallTicketData(salesDetail, tempOrder);
56
- const loadSnapshot = function() {
91
+ const { snapshot, source } = yield function() {
57
92
  var _ref2 = _asyncToGenerator(function* () {
58
93
  if (platform !== "h5" && orderId !== null && orderId !== void 0) try {
59
- const freshSnapshot = yield getLocalOrderReceiptSnapshot(orderId, [appLocale]);
60
- if (isSmallTicketData(freshSnapshot)) return freshSnapshot;
94
+ const freshSnapshot = yield getLocalOrderReceiptSnapshot(orderId, [appLocale], layout);
95
+ if (!freshSnapshot || !isSmallTicketData(freshSnapshot.small_ticket_data)) throw new Error("Receipt snapshot is unavailable");
96
+ if (mustFilter && freshSnapshot.template_visibility_applied !== true) throw new Error("Receipt snapshot does not support template filtering");
97
+ if (requiresSource && !freshSnapshot.source) throw new Error("Virtual currency receipt source is unavailable");
98
+ return {
99
+ snapshot: freshSnapshot.small_ticket_data,
100
+ source: freshSnapshot.source || null
101
+ };
61
102
  } catch (error) {
103
+ if (mustFilter || requiresSource) throw error;
62
104
  console.warn("[SaleDetail.Invoice] Failed to rebuild local receipt snapshot", error);
63
105
  }
64
- if (embeddedSnapshot) return embeddedSnapshot;
65
- return orderId !== null && orderId !== void 0 ? getOrderSmallTicketData(orderId) : null;
106
+ if (mustFilter || requiresSource) throw new Error("A template-aware local receipt snapshot is required");
107
+ return {
108
+ snapshot: embeddedSnapshot || (orderId !== null && orderId !== void 0 ? yield getOrderSmallTicketData(orderId) : null),
109
+ source: null
110
+ };
66
111
  });
67
112
  return function loadSnapshot() {
68
113
  return _ref2.apply(this, arguments);
69
114
  };
70
- }();
71
- const [snapshot, layout] = yield Promise.all([loadSnapshot(), resolveInvoiceLayoutConfig(salesModule)]);
115
+ }()();
72
116
  if (!snapshot) throw new Error("Receipt snapshot is unavailable");
117
+ const isVirtualSource = isVirtualSettlementTempOrder(source);
118
+ if (isVirtualSource && !useSharedConfig) return legacyVirtualResult;
73
119
  const shopInfo = getShopInfo(engineContext);
74
120
  const selected = selectSmallTicketLocale(snapshot, appLocale, shopInfo.primary_locale);
75
121
  if (!selected) throw new Error("Receipt language data is unavailable");
76
- return buildInvoiceReceiptViewModel({
77
- data: selected.data,
78
- layout,
79
- locale: selected.locale,
80
- previewTime: formatReceiptPreviewTime(previewCreatedAt, selected.locale),
81
- shopLogo: getShopLogo(shopInfo),
82
- taxNumberLabel: shopInfo.tax_number_title || (String(shopInfo.tax_country_code || "").toUpperCase() === "AU" ? "ABN" : void 0)
83
- });
122
+ return {
123
+ receipt: buildInvoiceReceiptViewModel({
124
+ data: selected.data,
125
+ layout,
126
+ locale: selected.locale,
127
+ previewTime: formatReceiptPreviewTime(previewCreatedAt, selected.locale),
128
+ shopLogo: getShopLogo(shopInfo),
129
+ taxNumberLabel: shopInfo.tax_number_title || (String(shopInfo.tax_country_code || "").toUpperCase() === "AU" ? "ABN" : void 0)
130
+ }),
131
+ source,
132
+ useLegacyVirtualCurrencyInvoice: false,
133
+ useVirtualCurrencyReceipt: useSharedConfig && isVirtualSource
134
+ };
84
135
  });
85
136
  return function load() {
86
137
  return _ref3.apply(this, arguments);
87
138
  };
88
- })()().then((receipt) => {
89
- if (!cancelled) setState({
139
+ })()().then((result) => {
140
+ if (!cancelled && result) setState(_objectSpread2(_objectSpread2({}, result), {}, {
90
141
  error: null,
91
142
  loading: false,
92
- receipt
93
- });
143
+ scope
144
+ }));
94
145
  }).catch((error) => {
95
146
  if (cancelled) return;
96
147
  const normalizedError = error instanceof Error ? error : new Error(String(error));
97
148
  console.warn("[SaleDetail.Invoice] Failed to load receipt preview", normalizedError);
98
- setState({
149
+ setState(_objectSpread2(_objectSpread2({}, LOADING_STATE), {}, {
99
150
  error: normalizedError,
100
151
  loading: false,
101
- receipt: null
102
- });
152
+ scope
153
+ }));
103
154
  });
104
155
  return () => {
105
156
  cancelled = true;
106
157
  };
107
- }, [
108
- appLocale,
109
- engineContext,
110
- orderId,
111
- platform,
112
- previewCreatedAt,
113
- salesDetail,
114
- salesModule,
115
- tempOrder
116
- ]);
117
- return _objectSpread2(_objectSpread2({}, state), {}, { retry: () => setRevision((value) => value + 1) });
158
+ }, [scope]);
159
+ return _objectSpread2(_objectSpread2({}, state.scope === scope ? state : LOADING_STATE), {}, { retry: () => setRevision((value) => value + 1) });
118
160
  }
119
161
  //#endregion
120
162
  export { useInvoiceReceiptPreview };
@@ -6,6 +6,7 @@ import { SalesSdkContext } from "./SalesSdkContext.js";
6
6
  import { enrichCartBookingHolderDisplay, resolveHolderDisplayConfig } from "../utils/enrichCartLineHolderDisplay.js";
7
7
  import { useSalesSdkHolderOptional } from "./SalesSdkHolderContext.js";
8
8
  import { attachSelectedSettlement, hasSettlementOptions } from "../../multiCurrencySettlement/index.js";
9
+ import { getReceiptPrintWarning } from "../utils/receiptPrintWarning.js";
9
10
  import { useSalesSdkBusinessAvailability } from "./SalesSdkBusinessAvailabilityContext.js";
10
11
  import { SalesSdkProductContext } from "./SalesSdkProductContext.js";
11
12
  import { SalesSdkSummaryContext, SalesSdkSummaryPrepareContext, SalesSdkSummaryRefreshContext } from "./SalesSdkSummaryContext.js";
@@ -1870,7 +1871,10 @@ const SalesSdkCartProvider = ({ children, deferHolderAuthOnClose = false, enable
1870
1871
  }))) throw HOLDER_CONFIRM_CANCELLED;
1871
1872
  }
1872
1873
  if ((yield options === null || options === void 0 || (_options$beforeSubmit = options.beforeSubmit) === null || _options$beforeSubmit === void 0 ? void 0 : _options$beforeSubmit.call(options)) === false) throw HOLDER_CONFIRM_CANCELLED;
1873
- return bookingTicket.submitSalesOrder(params);
1874
+ const result = yield bookingTicket.submitSalesOrder(params);
1875
+ const receiptWarning = getReceiptPrintWarning(result, locales.getLocale());
1876
+ if (receiptWarning) Toast.info(receiptWarning);
1877
+ return result;
1874
1878
  });
1875
1879
  return function(_x45, _x46) {
1876
1880
  return _ref43.apply(this, arguments);
@@ -10,6 +10,7 @@ import { SalesSdkHolderProvider } from "./SalesSdkHolderContext.js";
10
10
  import { getMultiCurrencyText } from "../../multiCurrencySettlement/locales.js";
11
11
  import { hasSufficientVirtualCurrencyBalance, resolveSettlementOptionEntries } from "../../multiCurrencySettlement/index.js";
12
12
  import { normalizePaymentModalCallbackEvent } from "../../../components/checkout/payment-modal-utils.js";
13
+ import { getReceiptPrintWarning } from "../utils/receiptPrintWarning.js";
13
14
  import { BusinessAvailabilityShoppingHosts, SalesSdkBusinessAvailabilityProvider } from "./SalesSdkBusinessAvailabilityContext.js";
14
15
  import { resolveSalesSdkProductLoadChannel } from "../utils/buildStrategyContext.js";
15
16
  import { buildDefaultLoadProductsParamsWithOpenData, buildInitBookingContextParams, collectBookingIdsFromTempOrder, ensureBookingConfigForLoad, normalizeMenuListIds, omitDerivedScheduleParams, shouldLoadOnlyBookingConfig } from "../utils/buildDefaultLoadProductsParams.js";
@@ -1073,6 +1074,8 @@ const SalesSdkProvider = ({ osKey, enableMultiCurrencySettlement = false, soluti
1073
1074
  var _options$beforeSubmit2, _summaryProviderRef$c3;
1074
1075
  if ((yield options === null || options === void 0 || (_options$beforeSubmit2 = options.beforeSubmit) === null || _options$beforeSubmit2 === void 0 ? void 0 : _options$beforeSubmit2.call(options)) === false) throw HOLDER_CONFIRM_CANCELLED;
1075
1076
  const result = yield bookingTicket.submitSalesOrder(params);
1077
+ const receiptWarning = getReceiptPrintWarning(result, locales.getLocale());
1078
+ if (receiptWarning) Toast.info(receiptWarning);
1076
1079
  if (options === null || options === void 0 ? void 0 : options.skipRemoteRefresh) refreshRootSnapshot();
1077
1080
  else yield refreshSalesDetail();
1078
1081
  (_summaryProviderRef$c3 = summaryProviderRef.current) === null || _summaryProviderRef$c3 === void 0 || _summaryProviderRef$c3.refreshSummary();
@@ -0,0 +1,16 @@
1
+ //#region src/plus/salesSdk/utils/receiptPrintWarning.ts
2
+ const PRINT_WARNINGS = {
3
+ en: "The order was saved, but the receipt could not be generated. Please retry printing from order details.",
4
+ "zh-cn": "订单已保存,但小票生成失败。请在订单详情中重试打印。",
5
+ "zh-hk": "訂單已儲存,但小票產生失敗。請在訂單詳情中重試列印。",
6
+ ja: "注文は保存されましたが、レシートを作成できませんでした。注文詳細から印刷を再試行してください。",
7
+ pt: "O pedido foi salvo, mas não foi possível gerar o recibo. Tente imprimir novamente nos detalhes do pedido."
8
+ };
9
+ /** Receipt failure must be visible without turning a saved sale into a failed checkout. */
10
+ function getReceiptPrintWarning(result, locale) {
11
+ if (!result || typeof result !== "object" || !result.receipt_print_error) return null;
12
+ const language = String(locale || "en").replace(/_/g, "-").toLowerCase();
13
+ return PRINT_WARNINGS[language] || PRINT_WARNINGS[language.split("-")[0]] || PRINT_WARNINGS.en;
14
+ }
15
+ //#endregion
16
+ export { getReceiptPrintWarning };
@@ -6,12 +6,12 @@ import React, { useCallback, useEffect, useMemo, useRef } from "react";
6
6
  import { locales } from "@pisell/utils";
7
7
  import { Button, PisellEmpty, PisellModal, PisellStatisticList, Skeleton, Timeline, usePisellConfig } from "@pisell/materials";
8
8
  import { useRequest } from "ahooks";
9
- import timezonePlugin from "dayjs/plugin/timezone";
10
- import utcPlugin from "dayjs/plugin/utc";
9
+ import timezone from "dayjs/plugin/timezone";
10
+ import utc from "dayjs/plugin/utc";
11
11
  import "./index.less";
12
12
  //#region src/plus/walletPassGallery/components/timelineSection/index.tsx
13
- dayjs.extend(timezonePlugin);
14
- dayjs.extend(utcPlugin);
13
+ dayjs.extend(timezone);
14
+ dayjs.extend(utc);
15
15
  const stateTimeUnix = 1723255863;
16
16
  const POLL_INTERVAL = 2e3;
17
17
  const POLL_MAX_TIMES = 5;
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2023 Phosphor Icons
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Phosphor Icons
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.