rerobe-js-orm 4.9.8 → 4.9.10
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.
|
@@ -742,16 +742,30 @@ class OrderHelpers {
|
|
|
742
742
|
fractionDigits: 2,
|
|
743
743
|
}),
|
|
744
744
|
refundLineItems: (order.refunds || []).flatMap((refund) => (refund.refundLineItems || []).map((item) => {
|
|
745
|
-
var _a, _b;
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
745
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
746
|
+
// A stored RefundLineItem is { lineItem, quantityRefund,
|
|
747
|
+
// quantityCancel, subtotalRefund(Presentment), subtotalCanceled(
|
|
748
|
+
// Presentment) } — the title/amount live on `lineItem`, not flat on
|
|
749
|
+
// the item. Returned units = refunded + canceled (a cancellation of
|
|
750
|
+
// unfulfilled units still returns money). The subtotals are net of
|
|
751
|
+
// tax (originalUnitPrice basis), so gross them up for the receipt.
|
|
752
|
+
const lineItem = item.lineItem || {};
|
|
753
|
+
const quantity = Number(item.quantityRefund || 0) + Number(item.quantityCancel || 0);
|
|
754
|
+
const net = Number((_d = (_b = (_a = item.subtotalRefundPresentment) === null || _a === void 0 ? void 0 : _a.amount) !== null && _b !== void 0 ? _b : (_c = item.subtotalRefund) === null || _c === void 0 ? void 0 : _c.amount) !== null && _d !== void 0 ? _d : 0) +
|
|
755
|
+
Number((_h = (_f = (_e = item.subtotalCanceledPresentment) === null || _e === void 0 ? void 0 : _e.amount) !== null && _f !== void 0 ? _f : (_g = item.subtotalCanceled) === null || _g === void 0 ? void 0 : _g.amount) !== null && _h !== void 0 ? _h : 0);
|
|
756
|
+
const taxRate = Number(lineItem.taxRate || 0);
|
|
757
|
+
const gross = lineItem.isTaxable && taxRate ? net * (1 + taxRate) : net;
|
|
758
|
+
return {
|
|
759
|
+
title: (0, MarketplaceLineDisplayHelpers_1.formatMarketplaceLineDisplayTitle)({ lineItem }, { includeSellerPrefix: includeMarketplaceSellerPrefix }) ||
|
|
760
|
+
lineItem.title ||
|
|
761
|
+
'',
|
|
762
|
+
quantity,
|
|
749
763
|
price: (0, Utilities_1.formatPrice)({
|
|
750
764
|
currencyCode,
|
|
751
|
-
amount: -
|
|
765
|
+
amount: -Math.abs(gross),
|
|
752
766
|
fractionDigits: 2,
|
|
753
767
|
}),
|
|
754
|
-
}
|
|
768
|
+
};
|
|
755
769
|
})),
|
|
756
770
|
}));
|
|
757
771
|
}
|
|
@@ -1,6 +1,16 @@
|
|
|
1
|
+
export type ReceiptPreviewLine = {
|
|
2
|
+
align: 'left' | 'center' | 'right';
|
|
3
|
+
bold: boolean;
|
|
4
|
+
size: number;
|
|
5
|
+
text: string;
|
|
6
|
+
cut?: boolean;
|
|
7
|
+
};
|
|
1
8
|
export default class ReceiptXmlHelpers {
|
|
2
9
|
static escapeXML(text: any): string;
|
|
3
10
|
private static variantLabelForReceipt;
|
|
4
11
|
static formatLineItemXML(lineItem: any): string;
|
|
5
12
|
static buildReceiptContentXML(receiptData: any): string;
|
|
13
|
+
private static decodeXML;
|
|
14
|
+
private static parseAttrs;
|
|
15
|
+
static parseReceiptXml(xml: string): ReceiptPreviewLine[];
|
|
6
16
|
}
|
|
@@ -231,5 +231,89 @@ class ReceiptXmlHelpers {
|
|
|
231
231
|
receipt += '</epos-print>';
|
|
232
232
|
return receipt;
|
|
233
233
|
}
|
|
234
|
+
// Decode the 5 XML entities escapeXML produces, back to their characters.
|
|
235
|
+
// `&` is decoded last so `&lt;` round-trips to `<`, not `<`.
|
|
236
|
+
static decodeXML(text) {
|
|
237
|
+
return String(text)
|
|
238
|
+
.replace(/</g, '<')
|
|
239
|
+
.replace(/>/g, '>')
|
|
240
|
+
.replace(/"/g, '"')
|
|
241
|
+
.replace(/'/g, "'")
|
|
242
|
+
.replace(/&/g, '&');
|
|
243
|
+
}
|
|
244
|
+
// Parse `attr="value"` pairs out of a tag's attribute string.
|
|
245
|
+
static parseAttrs(raw) {
|
|
246
|
+
const attrs = {};
|
|
247
|
+
const re = /(\w+)="([^"]*)"/g;
|
|
248
|
+
let m = re.exec(raw);
|
|
249
|
+
while (m) {
|
|
250
|
+
attrs[m[1]] = m[2];
|
|
251
|
+
m = re.exec(raw);
|
|
252
|
+
}
|
|
253
|
+
return attrs;
|
|
254
|
+
}
|
|
255
|
+
// Inverse of buildReceiptContentXML for PREVIEW rendering: turn the exact
|
|
256
|
+
// ePOS-Print XML the printer receives into an ordered list of styled lines, so
|
|
257
|
+
// a simulator can render byte-for-byte what will print without re-deriving the
|
|
258
|
+
// layout from raw receipt fields (which silently drifts when a field is added).
|
|
259
|
+
//
|
|
260
|
+
// ePOS-Print printer state (align, double width/height, emphasis) is sticky —
|
|
261
|
+
// it persists across <text> elements until changed — so we carry it forward.
|
|
262
|
+
// <feed/> ends a line; <cut/> is emitted as a cut marker. Spaces are preserved
|
|
263
|
+
// verbatim (line items pad to a fixed column width), so render with a
|
|
264
|
+
// fixed-width font and white-space: pre to reproduce the columns.
|
|
265
|
+
//
|
|
266
|
+
// Returns styled lines ({ align, bold, size (1|2), text, cut? }) in print order.
|
|
267
|
+
static parseReceiptXml(xml) {
|
|
268
|
+
const lines = [];
|
|
269
|
+
if (!xml)
|
|
270
|
+
return lines;
|
|
271
|
+
// Sticky printer state.
|
|
272
|
+
let align = 'left';
|
|
273
|
+
let bold = false;
|
|
274
|
+
let size = 1;
|
|
275
|
+
// Current line buffer (reflects the state at the time text was appended).
|
|
276
|
+
let buf = '';
|
|
277
|
+
let hasText = false;
|
|
278
|
+
const flush = () => {
|
|
279
|
+
lines.push({ align, bold, size, text: buf });
|
|
280
|
+
buf = '';
|
|
281
|
+
hasText = false;
|
|
282
|
+
};
|
|
283
|
+
const tokenRe = /<text\b([^>]*?)\/>|<text\b([^>]*)>([\s\S]*?)<\/text>|<feed\s*\/>|<cut\b[^>]*?\/>/g;
|
|
284
|
+
let t = tokenRe.exec(xml);
|
|
285
|
+
while (t) {
|
|
286
|
+
const whole = t[0];
|
|
287
|
+
if (whole.indexOf('<feed') === 0) {
|
|
288
|
+
flush();
|
|
289
|
+
}
|
|
290
|
+
else if (whole.indexOf('<cut') === 0) {
|
|
291
|
+
if (hasText || buf)
|
|
292
|
+
flush();
|
|
293
|
+
lines.push({ align: 'center', bold: false, size: 1, text: '', cut: true });
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
// A <text> element: self-closing (state only) or with content.
|
|
297
|
+
const selfClosing = t[1] !== undefined;
|
|
298
|
+
const attrs = this.parseAttrs(selfClosing ? t[1] : t[2]);
|
|
299
|
+
if (attrs.align === 'left' || attrs.align === 'center' || attrs.align === 'right') {
|
|
300
|
+
align = attrs.align;
|
|
301
|
+
}
|
|
302
|
+
if (attrs.width)
|
|
303
|
+
size = parseInt(attrs.width, 10) >= 2 ? 2 : 1;
|
|
304
|
+
if (attrs.em !== undefined)
|
|
305
|
+
bold = attrs.em === 'true';
|
|
306
|
+
if (!selfClosing && t[3]) {
|
|
307
|
+
buf += this.decodeXML(t[3]);
|
|
308
|
+
hasText = true;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
t = tokenRe.exec(xml);
|
|
312
|
+
}
|
|
313
|
+
// Trailing content with no closing <feed/>.
|
|
314
|
+
if (hasText || buf)
|
|
315
|
+
flush();
|
|
316
|
+
return lines;
|
|
317
|
+
}
|
|
234
318
|
}
|
|
235
319
|
exports.default = ReceiptXmlHelpers;
|