@pisell/pisellos 0.10.55 → 0.10.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +0,0 @@
1
- // 导出评估器
2
- export { PromotionEvaluator } from "./evaluator";
3
-
4
- // 导出适配器
5
- export { PromotionAdapter } from "./adapter";
6
- export { default } from "./adapter";
7
-
8
- // 导出策略配置示例常量
9
- export { X_ITEMS_FOR_Y_PRICE_STRATEGY, BUY_X_GET_Y_FREE_STRATEGY, ITEM_REWARD_STRATEGY } from "./examples";
@@ -591,7 +591,7 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
591
591
  generateIdempotencyToken(): string;
592
592
  syncPaymentsToOrder<T = any>(params: SyncPaymentsToOrderParams): Promise<SyncPaymentsToOrderResult<T>>;
593
593
  createOrder(params: CommitOrderParams['query']): {
594
- type: "virtual" | "appointment_booking";
594
+ type: "appointment_booking" | "virtual";
595
595
  platform: string;
596
596
  sales_channel: string;
597
597
  order_sales_channel: string;
@@ -56,6 +56,10 @@ export interface CacheProps {
56
56
  * 请求配置
57
57
  */
58
58
  export interface RequestOptions {
59
+ /** Customer-only, credential-free GET /open/document/{id} on picoding. */
60
+ publicInvoiceDocument?: boolean;
61
+ /** Route through the host's configured picoding environment. */
62
+ pisell2?: boolean;
59
63
  /** Let the caller handle read-only preview failures without host navigation/toasts. */
60
64
  manualErrorHandling?: boolean;
61
65
  skipErrorHandler?: boolean;
@@ -0,0 +1,22 @@
1
+ import type { RequestPlugin } from '../../plugins/request';
2
+ import { type InvoiceLayoutConfig } from '../../modules/OpenData';
3
+ export interface PublicInvoiceDocumentResponse {
4
+ status: boolean;
5
+ code: number;
6
+ message?: string;
7
+ data: {
8
+ id: number;
9
+ data?: {
10
+ template_settings?: unknown;
11
+ } | null;
12
+ } | null;
13
+ }
14
+ interface TemplateScope {
15
+ tenantId: string | number;
16
+ shopId: string | number;
17
+ identity: string;
18
+ businessCode: string;
19
+ channel: string;
20
+ }
21
+ export declare function loadCustomerInvoiceLayout(request: RequestPlugin, scope: TemplateScope): Promise<InvoiceLayoutConfig>;
22
+ export {};
@@ -0,0 +1,142 @@
1
+ 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; }
2
+ 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); } }
3
+ 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); }); }; }
4
+ 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); }
5
+ import { getDefaultInvoiceLayoutConfig, normalizeInvoiceLayoutFromTemplateSettings, normalizeInvoiceTemplateSettings, normalizeRawInvoiceTemplateSettings } from "../../modules/OpenData";
6
+ // Page-runtime caches: also retain DEFAULT on failure, without automatic retries.
7
+ var caches = new WeakMap();
8
+ var isRecord = function isRecord(value) {
9
+ return !!value && _typeof(value) === 'object' && !Array.isArray(value);
10
+ };
11
+ function documentId(value) {
12
+ if (typeof value !== 'string' && typeof value !== 'number') return null;
13
+ var text = String(value).trim();
14
+ if (!/^\d+$/.test(text)) return null;
15
+ var id = Number(text);
16
+ return Number.isSafeInteger(id) && id > 0 ? String(id) : null;
17
+ }
18
+ export function loadCustomerInvoiceLayout(request, scope) {
19
+ var cache = caches.get(request);
20
+ if (!cache) {
21
+ cache = {
22
+ scopes: new Map(),
23
+ documents: new Map()
24
+ };
25
+ caches.set(request, cache);
26
+ }
27
+ var target = "".concat(scope.businessCode, "+").concat(scope.channel);
28
+ var key = JSON.stringify([scope.tenantId, scope.shopId, scope.identity, scope.businessCode, scope.channel]);
29
+ var cached = cache.scopes.get(key);
30
+ if (cached) return cached;
31
+ var id = null;
32
+ var task = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {
33
+ var response, config, raw, numericLike, docKey, pending, expectedId;
34
+ return _regeneratorRuntime().wrap(function _callee2$(_context2) {
35
+ while (1) switch (_context2.prev = _context2.next) {
36
+ case 0:
37
+ _context2.next = 2;
38
+ return request.post("/open/my-pisell/".concat(encodeURIComponent(String(scope.shopId)), "/setting"), {
39
+ scope: 'board',
40
+ target: target,
41
+ section_code: ['documents']
42
+ }, {
43
+ pisell2: true,
44
+ prefix: false,
45
+ headers: scope.tenantId ? {
46
+ 'Tenant-Id': String(scope.tenantId)
47
+ } : {},
48
+ manualErrorHandling: true,
49
+ skipErrorHandler: true,
50
+ timeout: 15000
51
+ });
52
+ case 2:
53
+ response = _context2.sent;
54
+ if (!((response === null || response === void 0 ? void 0 : response.status) !== true || response.code !== 200 || !isRecord(response.data))) {
55
+ _context2.next = 5;
56
+ break;
57
+ }
58
+ throw new Error((response === null || response === void 0 ? void 0 : response.message) || 'Invoice OpenData is unavailable');
59
+ case 5:
60
+ config = response.data;
61
+ raw = config['documents.invoice_template'];
62
+ id = documentId(raw);
63
+ if (id) {
64
+ _context2.next = 11;
65
+ break;
66
+ }
67
+ // Preserve the existing non-numeric legacy template / invoice_edit contract.
68
+ numericLike = /^[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?$/i;
69
+ return _context2.abrupt("return", typeof raw === 'string' && raw.trim() && !numericLike.test(raw.trim()) ? normalizeInvoiceLayoutFromTemplateSettings(normalizeInvoiceTemplateSettings(config)) : getDefaultInvoiceLayoutConfig());
70
+ case 11:
71
+ docKey = JSON.stringify([key, id]);
72
+ pending = cache.documents.get(docKey);
73
+ if (!pending) {
74
+ expectedId = id;
75
+ pending = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
76
+ var result, doc, settings;
77
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
78
+ while (1) switch (_context.prev = _context.next) {
79
+ case 0:
80
+ _context.next = 2;
81
+ return request.get("/open/document/".concat(expectedId), {}, {
82
+ publicInvoiceDocument: true
83
+ });
84
+ case 2:
85
+ result = _context.sent;
86
+ if (!((result === null || result === void 0 ? void 0 : result.status) !== true || result.code !== 200)) {
87
+ _context.next = 5;
88
+ break;
89
+ }
90
+ throw new Error((result === null || result === void 0 ? void 0 : result.message) || 'Invoice Document request failed');
91
+ case 5:
92
+ doc = result.data;
93
+ if (!(!doc || documentId(doc.id) !== expectedId)) {
94
+ _context.next = 8;
95
+ break;
96
+ }
97
+ throw new Error('Invoice Document is unavailable or its ID does not match');
98
+ case 8:
99
+ if (!(!isRecord(doc.data) || !isRecord(doc.data.template_settings))) {
100
+ _context.next = 10;
101
+ break;
102
+ }
103
+ throw new Error('Invoice Document has no template_settings');
104
+ case 10:
105
+ settings = normalizeRawInvoiceTemplateSettings(doc.data.template_settings);
106
+ if (!(settings.modules.length === 0)) {
107
+ _context.next = 13;
108
+ break;
109
+ }
110
+ throw new Error('Invoice Document has no usable template modules');
111
+ case 13:
112
+ return _context.abrupt("return", normalizeInvoiceLayoutFromTemplateSettings(settings));
113
+ case 14:
114
+ case "end":
115
+ return _context.stop();
116
+ }
117
+ }, _callee);
118
+ }))().catch(function (error) {
119
+ return fallback(error, target, expectedId);
120
+ });
121
+ cache.documents.set(docKey, pending);
122
+ }
123
+ return _context2.abrupt("return", pending);
124
+ case 15:
125
+ case "end":
126
+ return _context2.stop();
127
+ }
128
+ }, _callee2);
129
+ }))().catch(function (error) {
130
+ return fallback(error, target, id);
131
+ });
132
+ cache.scopes.set(key, task);
133
+ return task;
134
+ }
135
+ function fallback(error, target, id) {
136
+ console.warn('[OrderInvoicePreview] Template unavailable; using DEFAULT', {
137
+ target: target,
138
+ documentId: id,
139
+ message: error instanceof Error ? error.message : 'Template request failed'
140
+ });
141
+ return getDefaultInvoiceLayoutConfig();
142
+ }
@@ -26,7 +26,7 @@ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key i
26
26
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
27
27
  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); }
28
28
  import { BaseModule } from "../../modules/BaseModule";
29
- import { getDefaultInvoiceLayoutConfig } from "../../modules/OpenData";
29
+ import { loadCustomerInvoiceLayout } from "../../shared/receipt/loadCustomerInvoiceLayout";
30
30
  import { buildSmallTicketData } from "../../shared/receipt/small-ticket";
31
31
  import { loadSalesOrderSnapshot } from "../../shared/sales/loadSalesOrderSnapshot";
32
32
  import { loadPaymentMethods, withPaymentMethodNames } from "../../shared/payment/loadPaymentMethods";
@@ -176,19 +176,19 @@ export var OrderInvoicePreviewImpl = /*#__PURE__*/function (_BaseModule) {
176
176
  });
177
177
  var task = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
178
178
  var _this3$core$getPlugin, _this3$core$getPlugin2, _coreData$core;
179
- var _yield$Promise$all, _yield$Promise$all2, snapshot, context, source, layout, getData, coreData, shop, requestedLocale, locale, result;
179
+ var _yield$Promise$all, _yield$Promise$all2, snapshot, context, layout, source, getData, coreData, shop, requestedLocale, locale, result;
180
180
  return _regeneratorRuntime().wrap(function _callee$(_context) {
181
181
  while (1) switch (_context.prev = _context.next) {
182
182
  case 0:
183
183
  _context.next = 2;
184
- return Promise.all([_this3.loadSource(input), _this3.loadContext(input)]);
184
+ return Promise.all([_this3.loadSource(input), _this3.loadContext(input), loadCustomerInvoiceLayout(_this3.request, input)]);
185
185
  case 2:
186
186
  _yield$Promise$all = _context.sent;
187
- _yield$Promise$all2 = _slicedToArray(_yield$Promise$all, 2);
187
+ _yield$Promise$all2 = _slicedToArray(_yield$Promise$all, 3);
188
188
  snapshot = _yield$Promise$all2[0];
189
189
  context = _yield$Promise$all2[1];
190
- source = withPaymentMethodNames(snapshot, context.methods); // Customer templates will use a dedicated backend API. Do not request NocoBase.
191
- layout = getDefaultInvoiceLayoutConfig();
190
+ layout = _yield$Promise$all2[2];
191
+ source = withPaymentMethodNames(snapshot, context.methods);
192
192
  getData = (_this3$core$getPlugin = _this3.core.getPlugin('app')) === null || _this3$core$getPlugin === void 0 || (_this3$core$getPlugin2 = _this3$core$getPlugin.getData) === null || _this3$core$getPlugin2 === void 0 ? void 0 : _this3$core$getPlugin2.call(_this3$core$getPlugin);
193
193
  if (!((getData === null || getData === void 0 ? void 0 : getData('shop_id')) != null && String(getData('shop_id')) !== String(input.shopId))) {
194
194
  _context.next = 11;
@@ -591,7 +591,7 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
591
591
  generateIdempotencyToken(): string;
592
592
  syncPaymentsToOrder<T = any>(params: SyncPaymentsToOrderParams): Promise<SyncPaymentsToOrderResult<T>>;
593
593
  createOrder(params: CommitOrderParams['query']): {
594
- type: "virtual" | "appointment_booking";
594
+ type: "appointment_booking" | "virtual";
595
595
  platform: string;
596
596
  sales_channel: string;
597
597
  order_sales_channel: string;
@@ -56,6 +56,10 @@ export interface CacheProps {
56
56
  * 请求配置
57
57
  */
58
58
  export interface RequestOptions {
59
+ /** Customer-only, credential-free GET /open/document/{id} on picoding. */
60
+ publicInvoiceDocument?: boolean;
61
+ /** Route through the host's configured picoding environment. */
62
+ pisell2?: boolean;
59
63
  /** Let the caller handle read-only preview failures without host navigation/toasts. */
60
64
  manualErrorHandling?: boolean;
61
65
  skipErrorHandler?: boolean;
@@ -0,0 +1,22 @@
1
+ import type { RequestPlugin } from '../../plugins/request';
2
+ import { type InvoiceLayoutConfig } from '../../modules/OpenData';
3
+ export interface PublicInvoiceDocumentResponse {
4
+ status: boolean;
5
+ code: number;
6
+ message?: string;
7
+ data: {
8
+ id: number;
9
+ data?: {
10
+ template_settings?: unknown;
11
+ } | null;
12
+ } | null;
13
+ }
14
+ interface TemplateScope {
15
+ tenantId: string | number;
16
+ shopId: string | number;
17
+ identity: string;
18
+ businessCode: string;
19
+ channel: string;
20
+ }
21
+ export declare function loadCustomerInvoiceLayout(request: RequestPlugin, scope: TemplateScope): Promise<InvoiceLayoutConfig>;
22
+ export {};
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.loadCustomerInvoiceLayout = loadCustomerInvoiceLayout;
7
+ var _OpenData = require("../../modules/OpenData");
8
+ // Page-runtime caches: also retain DEFAULT on failure, without automatic retries.
9
+ const caches = new WeakMap();
10
+ const isRecord = value => !!value && typeof value === 'object' && !Array.isArray(value);
11
+ function documentId(value) {
12
+ if (typeof value !== 'string' && typeof value !== 'number') return null;
13
+ const text = String(value).trim();
14
+ if (!/^\d+$/.test(text)) return null;
15
+ const id = Number(text);
16
+ return Number.isSafeInteger(id) && id > 0 ? String(id) : null;
17
+ }
18
+ function loadCustomerInvoiceLayout(request, scope) {
19
+ let cache = caches.get(request);
20
+ if (!cache) {
21
+ cache = {
22
+ scopes: new Map(),
23
+ documents: new Map()
24
+ };
25
+ caches.set(request, cache);
26
+ }
27
+ const target = `${scope.businessCode}+${scope.channel}`;
28
+ const key = JSON.stringify([scope.tenantId, scope.shopId, scope.identity, scope.businessCode, scope.channel]);
29
+ const cached = cache.scopes.get(key);
30
+ if (cached) return cached;
31
+ let id = null;
32
+ const task = (async () => {
33
+ const response = await request.post(`/open/my-pisell/${encodeURIComponent(String(scope.shopId))}/setting`, {
34
+ scope: 'board',
35
+ target,
36
+ section_code: ['documents']
37
+ }, {
38
+ pisell2: true,
39
+ prefix: false,
40
+ headers: scope.tenantId ? {
41
+ 'Tenant-Id': String(scope.tenantId)
42
+ } : {},
43
+ manualErrorHandling: true,
44
+ skipErrorHandler: true,
45
+ timeout: 15000
46
+ });
47
+ if (response?.status !== true || response.code !== 200 || !isRecord(response.data)) throw new Error(response?.message || 'Invoice OpenData is unavailable');
48
+ const config = response.data;
49
+ const raw = config['documents.invoice_template'];
50
+ id = documentId(raw);
51
+ if (!id) {
52
+ // Preserve the existing non-numeric legacy template / invoice_edit contract.
53
+ const numericLike = /^[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?$/i;
54
+ return typeof raw === 'string' && raw.trim() && !numericLike.test(raw.trim()) ? (0, _OpenData.normalizeInvoiceLayoutFromTemplateSettings)((0, _OpenData.normalizeInvoiceTemplateSettings)(config)) : (0, _OpenData.getDefaultInvoiceLayoutConfig)();
55
+ }
56
+ const docKey = JSON.stringify([key, id]);
57
+ let pending = cache.documents.get(docKey);
58
+ if (!pending) {
59
+ const expectedId = id;
60
+ pending = (async () => {
61
+ const result = await request.get(`/open/document/${expectedId}`, {}, {
62
+ publicInvoiceDocument: true
63
+ });
64
+ if (result?.status !== true || result.code !== 200) throw new Error(result?.message || 'Invoice Document request failed');
65
+ const doc = result.data;
66
+ if (!doc || documentId(doc.id) !== expectedId) throw new Error('Invoice Document is unavailable or its ID does not match');
67
+ if (!isRecord(doc.data) || !isRecord(doc.data.template_settings)) throw new Error('Invoice Document has no template_settings');
68
+ const settings = (0, _OpenData.normalizeRawInvoiceTemplateSettings)(doc.data.template_settings);
69
+ if (settings.modules.length === 0) throw new Error('Invoice Document has no usable template modules');
70
+ return (0, _OpenData.normalizeInvoiceLayoutFromTemplateSettings)(settings);
71
+ })().catch(error => fallback(error, target, expectedId));
72
+ cache.documents.set(docKey, pending);
73
+ }
74
+ return pending;
75
+ })().catch(error => fallback(error, target, id));
76
+ cache.scopes.set(key, task);
77
+ return task;
78
+ }
79
+ function fallback(error, target, id) {
80
+ console.warn('[OrderInvoicePreview] Template unavailable; using DEFAULT', {
81
+ target,
82
+ documentId: id,
83
+ message: error instanceof Error ? error.message : 'Template request failed'
84
+ });
85
+ return (0, _OpenData.getDefaultInvoiceLayoutConfig)();
86
+ }
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.OrderInvoicePreviewImpl = void 0;
7
7
  var _BaseModule = require("../../modules/BaseModule");
8
- var _OpenData = require("../../modules/OpenData");
8
+ var _loadCustomerInvoiceLayout = require("../../shared/receipt/loadCustomerInvoiceLayout");
9
9
  var _smallTicket = require("../../shared/receipt/small-ticket");
10
10
  var _loadSalesOrderSnapshot = require("../../shared/sales/loadSalesOrderSnapshot");
11
11
  var _loadPaymentMethods = require("../../shared/payment/loadPaymentMethods");
@@ -124,10 +124,8 @@ class OrderInvoicePreviewImpl extends _BaseModule.BaseModule {
124
124
  error: null
125
125
  });
126
126
  const task = (async () => {
127
- const [snapshot, context] = await Promise.all([this.loadSource(input), this.loadContext(input)]);
127
+ const [snapshot, context, layout] = await Promise.all([this.loadSource(input), this.loadContext(input), (0, _loadCustomerInvoiceLayout.loadCustomerInvoiceLayout)(this.request, input)]);
128
128
  const source = (0, _loadPaymentMethods.withPaymentMethodNames)(snapshot, context.methods);
129
- // Customer templates will use a dedicated backend API. Do not request NocoBase.
130
- const layout = (0, _OpenData.getDefaultInvoiceLayoutConfig)();
131
129
  const getData = this.core.getPlugin('app')?.getData?.();
132
130
  if (getData?.('shop_id') != null && String(getData('shop_id')) !== String(input.shopId)) throw new Error('Invoice shop changed');
133
131
  const coreData = getData?.('core');
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "0.10.55",
4
+ "version": "0.10.56",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",