@aglyn/plugins-commerce 1.0.0-beta.261 → 1.0.0-beta.263
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +13 -13
- package/src/lib/components/console/order-detail-dialog.component.js +17 -45
- package/src/lib/components/console/order-detail-dialog.component.js.map +1 -1
- package/src/lib/components/console/order-fulfillment-panel.component.js +12 -25
- package/src/lib/components/console/order-fulfillment-panel.component.js.map +1 -1
- package/src/lib/components/console/order-invoice.component.js +2 -10
- package/src/lib/components/console/order-invoice.component.js.map +1 -1
- package/src/lib/components/console/order-shipping-actions.component.d.ts +1 -15
- package/src/lib/components/console/order-shipping-actions.component.js +3 -23
- package/src/lib/components/console/order-shipping-actions.component.js.map +1 -1
- package/src/lib/components/console/product-labels-dialog.component.d.ts +2 -5
- package/src/lib/components/console/product-labels-dialog.component.js +6 -24
- package/src/lib/components/console/product-labels-dialog.component.js.map +1 -1
- package/src/lib/components/console/products-hub-card.component.js +7 -20
- package/src/lib/components/console/products-hub-card.component.js.map +1 -1
- package/src/lib/model/commerce-shipping.d.ts +2 -0
- package/src/lib/model/commerce-shipping.js +1 -0
- package/src/lib/model/commerce-shipping.js.map +1 -1
- package/src/lib/model/order-dialog.d.ts +52 -0
- package/src/lib/model/order-dialog.js +85 -0
- package/src/lib/model/order-dialog.js.map +1 -0
- package/src/lib/model/product-write.d.ts +71 -0
- package/src/lib/model/product-write.js +28 -0
- package/src/lib/model/product-write.js.map +1 -1
- package/src/lib/printing/product-labels.d.ts +22 -0
- package/src/lib/printing/product-labels.js +39 -2
- package/src/lib/printing/product-labels.js.map +1 -1
- package/src/lib/server/billing-webhook.js +3 -3
- package/src/lib/server/billing-webhook.js.map +1 -1
- package/src/lib/server/order-figures.js +37 -0
- package/src/lib/server/order-figures.js.map +1 -1
- package/src/lib/server/order-print.d.ts +40 -0
- package/src/lib/server/order-print.js +113 -0
- package/src/lib/server/order-print.js.map +1 -0
- package/src/lib/server/products-write.d.ts +26 -0
- package/src/lib/server/products-write.js +184 -1
- package/src/lib/server/products-write.js.map +1 -1
- package/src/lib/server.js +8 -0
- package/src/lib/server.js.map +1 -1
- package/src/lib/transfer/shipping-presets.d.ts +16 -0
- package/src/lib/transfer/shipping-presets.js +34 -1
- package/src/lib/transfer/shipping-presets.js.map +1 -1
- package/src/lib/utils/order-invoice.d.ts +5 -0
- package/src/lib/utils/order-invoice.js +14 -0
- package/src/lib/utils/order-invoice.js.map +1 -1
- package/src/lib/utils/order-packing-slip.d.ts +31 -0
- package/src/lib/utils/order-packing-slip.js +46 -0
- package/src/lib/utils/order-packing-slip.js.map +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/utils/order-invoice.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n formatOrderNumber,\n orderCreatedAtMs,\n type HostOrder,\n type OrderAddress,\n} from '../model/commerce-orders'\nimport { escapeHtml } from './escape-html'\n\n/**\n * The printable invoice (AGL-3611), beside the packing slip: the order as a\n * bill — who sold it, to whom, each line with its unit price, the totals,\n * what was refunded and what was paid in the end.\n *\n * A string of markup, because it is written into a print popup the way the\n * packing slip is, and the browser's print dialog saves it as a PDF. Every\n * value is escaped: the addresses are typed by the shopper, and the popup\n * inherits the console's origin (AGL-2283). No `<style>` and no `style`\n * attributes, because the popup inherits the console's content security\n * policy; the layout is the table attributes HTML still honors.\n */\n\nexport interface OrderInvoiceStore {\n /** The business's name, as its emails sign. */\n name: string\n /** The store's currency, for an order that does not carry its own. */\n currency: string\n /** The receipt footer the store set, printed at the foot. */\n footer?: string | null\n /** The store's terms address, printed at the foot. */\n termsUrl?: string | null\n}\n\ntype InvoiceOrder = Pick<\n HostOrder,\n | 'number'\n | 'status'\n | 'lineItems'\n | 'totals'\n | 'refundedCents'\n | 'customerName'\n | 'customerEmail'\n | 'shippingAddress'\n | 'billingAddress'\n> & { createdAtMs?: number; currency?: string; amountCents?: number }\n\n/** Money in the order's currency, integer cents in. */\nexport function invoiceMoney(cents: number, currency: string): string {\n const amount = (Number(cents) || 0) / 100\n try {\n return new Intl.NumberFormat('en-US', { style: 'currency', currency: currency || 'USD' }).format(amount)\n } catch {\n return `${amount.toFixed(2)} ${String(currency || '').toUpperCase()}`.trim()\n }\n}\n\nfunction addressLines(address: OrderAddress | undefined | null): string[] {\n if (!address) return []\n return [\n address.name,\n address.line1,\n address.line2,\n [address.city, address.state, address.postalCode].filter(Boolean).join(' '),\n address.country,\n address.phone,\n ]\n .map((part) => String(part ?? '').trim())\n .filter(Boolean)\n}\n\n/** What the payment line says. */\nexport function invoicePaymentStatus(order: Pick<InvoiceOrder, 'status' | 'refundedCents' | 'totals' | 'amountCents'>): string {\n const total = Number(order.totals?.totalCents ?? order.amountCents ?? 0)\n const refunded = Math.max(0, Number(order.refundedCents ?? 0))\n const status = String(order.status ?? '')\n if (status === 'pending' || status === 'draft') return 'Awaiting payment'\n if (status === 'cancelled') return 'Canceled'\n if (refunded > 0 && refunded >= total) return 'Refunded'\n if (refunded > 0) return 'Paid, partially refunded'\n return 'Paid'\n}\n\n/** The invoice's markup: a full document body, every value escaped. */\nexport function buildOrderInvoiceHtml(input: {\n order: InvoiceOrder\n orderId: string\n store: OrderInvoiceStore\n}): string {\n const { order, orderId, store } = input\n const currency = String(order.currency || store.currency || 'USD').toUpperCase()\n const money = (cents: number) => escapeHtml(invoiceMoney(cents, currency))\n const number = formatOrderNumber(order, orderId)\n const createdAt = orderCreatedAtMs(order as never)\n const totals = order.totals\n const itemsCents =\n totals?.itemsCents ??\n (order.lineItems ?? []).reduce((sum, line) => sum + Number(line.unitAmountCents || 0) * Number(line.quantity || 0), 0)\n const totalCents = Number(totals?.totalCents ?? order.amountCents ?? itemsCents)\n const refundedCents = Math.max(0, Number(order.refundedCents ?? 0))\n\n const billTo = [\n ...(order.billingAddress ? addressLines(order.billingAddress) : [order.customerName ?? ''].filter(Boolean)),\n order.customerEmail ?? '',\n ].filter(Boolean)\n const shipTo = addressLines(order.shippingAddress)\n\n const rows = (order.lineItems ?? [])\n .map((line) => {\n const quantity = Number(line.quantity) || 0\n const unit = Number(line.unitAmountCents) || 0\n const detail = [line.variantLabel ? escapeHtml(line.variantLabel) : '', line.sku ? `SKU ${escapeHtml(line.sku)}` : '']\n .filter(Boolean)\n .join(' · ')\n return (\n `<tr><td>${escapeHtml(line.name)}${detail ? `<br/><small>${detail}</small>` : ''}</td>` +\n `<td align=\"right\">${escapeHtml(quantity)}</td>` +\n `<td align=\"right\">${money(unit)}</td>` +\n `<td align=\"right\">${money(unit * quantity)}</td></tr>`\n )\n })\n .join('')\n\n const summary: Array<[string, string]> = [['Subtotal', money(itemsCents)]]\n if (Number(totals?.discountCents ?? 0) > 0) summary.push(['Discount', `−${money(Number(totals?.discountCents))}`])\n if (Number(totals?.shippingCents ?? 0) > 0) summary.push(['Shipping', money(Number(totals?.shippingCents))])\n if (Number(totals?.taxCents ?? 0) > 0) summary.push(['Tax', money(Number(totals?.taxCents))])\n summary.push(['<b>Total</b>', `<b>${money(totalCents)}</b>`])\n if (Number(totals?.tipCents ?? 0) > 0) summary.push(['Tip', money(Number(totals?.tipCents))])\n if (refundedCents > 0) {\n summary.push(['Refunded', `−${money(refundedCents)}`])\n summary.push(['<b>Net paid</b>', `<b>${money(Math.max(0, totalCents - refundedCents))}</b>`])\n }\n\n const block = (title: string, lines: string[]) =>\n lines.length ? `<td valign=\"top\"><b>${title}</b><br/>${lines.map((line) => escapeHtml(line)).join('<br/>')}</td>` : ''\n\n return (\n `<title>${escapeHtml(`Invoice ${number}`)}</title>` +\n `<h2>${escapeHtml(store.name || 'Invoice')}</h2>` +\n `<h3>${escapeHtml(`Invoice ${number}`)}</h3>` +\n `<p>${createdAt ? `Date: ${escapeHtml(new Date(createdAt).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }))}<br/>` : ''}` +\n `Payment: ${escapeHtml(invoicePaymentStatus(order))}<br/>Currency: ${escapeHtml(currency)}</p>` +\n `<table width=\"100%\" cellpadding=\"6\"><tr>${block('Bill to', billTo)}${block('Ship to', shipTo)}</tr></table>` +\n `<table width=\"100%\" cellpadding=\"6\" border=\"1\" cellspacing=\"0\">` +\n `<tr><th align=\"left\">Item</th><th align=\"right\">Qty</th><th align=\"right\">Unit price</th><th align=\"right\">Amount</th></tr>` +\n rows +\n `</table>` +\n `<table width=\"100%\" cellpadding=\"4\">${summary\n .map(([label, value]) => `<tr><td align=\"right\" width=\"80%\">${label}</td><td align=\"right\">${value}</td></tr>`)\n .join('')}</table>` +\n (store.footer ? `<p>${escapeHtml(store.footer)}</p>` : '') +\n (store.termsUrl ? `<p><small>Terms: ${escapeHtml(store.termsUrl)}</small></p>` : '')\n )\n}\n"],"names":["formatOrderNumber","orderCreatedAtMs","escapeHtml","invoiceMoney","cents","currency","amount","Number","Intl","NumberFormat","style","format","toFixed","String","toUpperCase","trim","addressLines","address","name","line1","line2","city","state","postalCode","filter","Boolean","join","country","phone","map","part","invoicePaymentStatus","order","total","totals","totalCents","amountCents","refunded","Math","max","refundedCents","status","buildOrderInvoiceHtml","input","orderId","store","money","number","createdAt","itemsCents","lineItems","reduce","sum","line","unitAmountCents","quantity","billTo","billingAddress","customerName","customerEmail","shipTo","shippingAddress","rows","unit","detail","variantLabel","sku","summary","discountCents","push","shippingCents","taxCents","tipCents","block","title","lines","length","Date","toLocaleDateString","year","month","day","label","value","footer","termsUrl"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/utils/order-invoice.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n formatOrderNumber,\n orderCreatedAtMs,\n type HostOrder,\n type OrderAddress,\n} from '../model/commerce-orders'\nimport { escapeHtml } from './escape-html'\n\n/**\n * The printable invoice (AGL-3611), beside the packing slip: the order as a\n * bill — who sold it, to whom, each line with its unit price, the totals,\n * what was refunded and what was paid in the end.\n *\n * A string of markup, because it is written into a print popup the way the\n * packing slip is, and the browser's print dialog saves it as a PDF. Every\n * value is escaped: the addresses are typed by the shopper, and the popup\n * inherits the console's origin (AGL-2283). No `<style>` and no `style`\n * attributes, because the popup inherits the console's content security\n * policy; the layout is the table attributes HTML still honors.\n */\n\nexport interface OrderInvoiceStore {\n /** The business's name, as its emails sign. */\n name: string\n /** The store's currency, for an order that does not carry its own. */\n currency: string\n /** The receipt footer the store set, printed at the foot. */\n footer?: string | null\n /** The store's terms address, printed at the foot. */\n termsUrl?: string | null\n}\n\n/**\n * The invoice's store from the site's document and its store settings, as\n * the order dialog's Invoice button and `commerce/order-print` read them.\n */\nexport function invoiceStoreFrom(\n host: Record<string, unknown> | undefined | null,\n store: Record<string, unknown> | undefined | null,\n): OrderInvoiceStore {\n const hostData = host ?? {}\n const storeData = store ?? {}\n return {\n name: String(hostData['businessName'] ?? hostData['displayName'] ?? hostData['name'] ?? ''),\n currency: String(storeData['currency'] ?? 'USD'),\n footer: (storeData['receiptFooter'] as string | undefined) ?? null,\n termsUrl: (storeData['termsUrl'] as string | undefined) ?? null,\n }\n}\n\ntype InvoiceOrder = Pick<\n HostOrder,\n | 'number'\n | 'status'\n | 'lineItems'\n | 'totals'\n | 'refundedCents'\n | 'customerName'\n | 'customerEmail'\n | 'shippingAddress'\n | 'billingAddress'\n> & { createdAtMs?: number; currency?: string; amountCents?: number }\n\n/** Money in the order's currency, integer cents in. */\nexport function invoiceMoney(cents: number, currency: string): string {\n const amount = (Number(cents) || 0) / 100\n try {\n return new Intl.NumberFormat('en-US', { style: 'currency', currency: currency || 'USD' }).format(amount)\n } catch {\n return `${amount.toFixed(2)} ${String(currency || '').toUpperCase()}`.trim()\n }\n}\n\nfunction addressLines(address: OrderAddress | undefined | null): string[] {\n if (!address) return []\n return [\n address.name,\n address.line1,\n address.line2,\n [address.city, address.state, address.postalCode].filter(Boolean).join(' '),\n address.country,\n address.phone,\n ]\n .map((part) => String(part ?? '').trim())\n .filter(Boolean)\n}\n\n/** What the payment line says. */\nexport function invoicePaymentStatus(order: Pick<InvoiceOrder, 'status' | 'refundedCents' | 'totals' | 'amountCents'>): string {\n const total = Number(order.totals?.totalCents ?? order.amountCents ?? 0)\n const refunded = Math.max(0, Number(order.refundedCents ?? 0))\n const status = String(order.status ?? '')\n if (status === 'pending' || status === 'draft') return 'Awaiting payment'\n if (status === 'cancelled') return 'Canceled'\n if (refunded > 0 && refunded >= total) return 'Refunded'\n if (refunded > 0) return 'Paid, partially refunded'\n return 'Paid'\n}\n\n/** The invoice's markup: a full document body, every value escaped. */\nexport function buildOrderInvoiceHtml(input: {\n order: InvoiceOrder\n orderId: string\n store: OrderInvoiceStore\n}): string {\n const { order, orderId, store } = input\n const currency = String(order.currency || store.currency || 'USD').toUpperCase()\n const money = (cents: number) => escapeHtml(invoiceMoney(cents, currency))\n const number = formatOrderNumber(order, orderId)\n const createdAt = orderCreatedAtMs(order as never)\n const totals = order.totals\n const itemsCents =\n totals?.itemsCents ??\n (order.lineItems ?? []).reduce((sum, line) => sum + Number(line.unitAmountCents || 0) * Number(line.quantity || 0), 0)\n const totalCents = Number(totals?.totalCents ?? order.amountCents ?? itemsCents)\n const refundedCents = Math.max(0, Number(order.refundedCents ?? 0))\n\n const billTo = [\n ...(order.billingAddress ? addressLines(order.billingAddress) : [order.customerName ?? ''].filter(Boolean)),\n order.customerEmail ?? '',\n ].filter(Boolean)\n const shipTo = addressLines(order.shippingAddress)\n\n const rows = (order.lineItems ?? [])\n .map((line) => {\n const quantity = Number(line.quantity) || 0\n const unit = Number(line.unitAmountCents) || 0\n const detail = [line.variantLabel ? escapeHtml(line.variantLabel) : '', line.sku ? `SKU ${escapeHtml(line.sku)}` : '']\n .filter(Boolean)\n .join(' · ')\n return (\n `<tr><td>${escapeHtml(line.name)}${detail ? `<br/><small>${detail}</small>` : ''}</td>` +\n `<td align=\"right\">${escapeHtml(quantity)}</td>` +\n `<td align=\"right\">${money(unit)}</td>` +\n `<td align=\"right\">${money(unit * quantity)}</td></tr>`\n )\n })\n .join('')\n\n const summary: Array<[string, string]> = [['Subtotal', money(itemsCents)]]\n if (Number(totals?.discountCents ?? 0) > 0) summary.push(['Discount', `−${money(Number(totals?.discountCents))}`])\n if (Number(totals?.shippingCents ?? 0) > 0) summary.push(['Shipping', money(Number(totals?.shippingCents))])\n if (Number(totals?.taxCents ?? 0) > 0) summary.push(['Tax', money(Number(totals?.taxCents))])\n summary.push(['<b>Total</b>', `<b>${money(totalCents)}</b>`])\n if (Number(totals?.tipCents ?? 0) > 0) summary.push(['Tip', money(Number(totals?.tipCents))])\n if (refundedCents > 0) {\n summary.push(['Refunded', `−${money(refundedCents)}`])\n summary.push(['<b>Net paid</b>', `<b>${money(Math.max(0, totalCents - refundedCents))}</b>`])\n }\n\n const block = (title: string, lines: string[]) =>\n lines.length ? `<td valign=\"top\"><b>${title}</b><br/>${lines.map((line) => escapeHtml(line)).join('<br/>')}</td>` : ''\n\n return (\n `<title>${escapeHtml(`Invoice ${number}`)}</title>` +\n `<h2>${escapeHtml(store.name || 'Invoice')}</h2>` +\n `<h3>${escapeHtml(`Invoice ${number}`)}</h3>` +\n `<p>${createdAt ? `Date: ${escapeHtml(new Date(createdAt).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }))}<br/>` : ''}` +\n `Payment: ${escapeHtml(invoicePaymentStatus(order))}<br/>Currency: ${escapeHtml(currency)}</p>` +\n `<table width=\"100%\" cellpadding=\"6\"><tr>${block('Bill to', billTo)}${block('Ship to', shipTo)}</tr></table>` +\n `<table width=\"100%\" cellpadding=\"6\" border=\"1\" cellspacing=\"0\">` +\n `<tr><th align=\"left\">Item</th><th align=\"right\">Qty</th><th align=\"right\">Unit price</th><th align=\"right\">Amount</th></tr>` +\n rows +\n `</table>` +\n `<table width=\"100%\" cellpadding=\"4\">${summary\n .map(([label, value]) => `<tr><td align=\"right\" width=\"80%\">${label}</td><td align=\"right\">${value}</td></tr>`)\n .join('')}</table>` +\n (store.footer ? `<p>${escapeHtml(store.footer)}</p>` : '') +\n (store.termsUrl ? `<p><small>Terms: ${escapeHtml(store.termsUrl)}</small></p>` : '')\n )\n}\n"],"names":["formatOrderNumber","orderCreatedAtMs","escapeHtml","invoiceStoreFrom","host","store","hostData","storeData","name","String","currency","footer","termsUrl","invoiceMoney","cents","amount","Number","Intl","NumberFormat","style","format","toFixed","toUpperCase","trim","addressLines","address","line1","line2","city","state","postalCode","filter","Boolean","join","country","phone","map","part","invoicePaymentStatus","order","total","totals","totalCents","amountCents","refunded","Math","max","refundedCents","status","buildOrderInvoiceHtml","input","orderId","money","number","createdAt","itemsCents","lineItems","reduce","sum","line","unitAmountCents","quantity","billTo","billingAddress","customerName","customerEmail","shipTo","shippingAddress","rows","unit","detail","variantLabel","sku","summary","discountCents","push","shippingCents","taxCents","tipCents","block","title","lines","length","Date","toLocaleDateString","year","month","day","label","value"],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import { type HostOrder } from '../model/commerce-orders';
|
|
18
|
+
/**
|
|
19
|
+
* The packing slip (the order dialog's "Packing slip"): the order's number,
|
|
20
|
+
* where it ships and each line with its quantity and SKU, as markup for the
|
|
21
|
+
* print dialog. The console writes it into a print popup; the apps print the
|
|
22
|
+
* same markup, which `commerce/order-print` sends them.
|
|
23
|
+
*
|
|
24
|
+
* ESCAPED (AGL-2283). The console's popup is an `about:blank` document that
|
|
25
|
+
* INHERITS the console's origin, and `order.shippingAddress` is copied
|
|
26
|
+
* verbatim from Stripe's `shipping_details`, i.e. typed by the SHOPPER. A
|
|
27
|
+
* name of `<img src=x onerror=…>` ran script against the merchant's own
|
|
28
|
+
* authenticated session. Line names and SKUs are merchant-authored and lower
|
|
29
|
+
* severity, but they are the same construction and get the same treatment.
|
|
30
|
+
*/
|
|
31
|
+
export declare function buildPackingSlipHtml(order: Pick<HostOrder, 'number' | 'lineItems' | 'shippingAddress'>, orderId: string): string;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ import { formatOrderNumber } from "../model/commerce-orders.js";
|
|
17
|
+
import { escapeHtml } from "./escape-html.js";
|
|
18
|
+
/**
|
|
19
|
+
* The packing slip (the order dialog's "Packing slip"): the order's number,
|
|
20
|
+
* where it ships and each line with its quantity and SKU, as markup for the
|
|
21
|
+
* print dialog. The console writes it into a print popup; the apps print the
|
|
22
|
+
* same markup, which `commerce/order-print` sends them.
|
|
23
|
+
*
|
|
24
|
+
* ESCAPED (AGL-2283). The console's popup is an `about:blank` document that
|
|
25
|
+
* INHERITS the console's origin, and `order.shippingAddress` is copied
|
|
26
|
+
* verbatim from Stripe's `shipping_details`, i.e. typed by the SHOPPER. A
|
|
27
|
+
* name of `<img src=x onerror=…>` ran script against the merchant's own
|
|
28
|
+
* authenticated session. Line names and SKUs are merchant-authored and lower
|
|
29
|
+
* severity, but they are the same construction and get the same treatment.
|
|
30
|
+
*/ export function buildPackingSlipHtml(order, orderId) {
|
|
31
|
+
var _order_lineItems, _address_city, _address_state, _address_postalCode;
|
|
32
|
+
const rows = ((_order_lineItems = order.lineItems) != null ? _order_lineItems : []).map((line)=>{
|
|
33
|
+
var _line_sku;
|
|
34
|
+
return `<tr><td>${escapeHtml(line.quantity)}×</td><td>${escapeHtml(line.name)}${line.variantLabel ? ` — ${escapeHtml(line.variantLabel)}` : ''}</td><td>${escapeHtml((_line_sku = line.sku) != null ? _line_sku : '')}</td></tr>`;
|
|
35
|
+
}).join('');
|
|
36
|
+
const address = order.shippingAddress;
|
|
37
|
+
return `<h2>Packing slip ${escapeHtml(formatOrderNumber(order, orderId))}</h2>` + (address ? `<p>${[
|
|
38
|
+
address.name,
|
|
39
|
+
address.line1,
|
|
40
|
+
address.line2,
|
|
41
|
+
`${(_address_city = address.city) != null ? _address_city : ''} ${(_address_state = address.state) != null ? _address_state : ''} ${(_address_postalCode = address.postalCode) != null ? _address_postalCode : ''}`,
|
|
42
|
+
address.country
|
|
43
|
+
].filter(Boolean).map((part)=>escapeHtml(part)).join('<br/>')}</p>` : '') + `<table border="0" cellpadding="6">${rows}</table>`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
//# sourceMappingURL=order-packing-slip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/utils/order-packing-slip.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { formatOrderNumber, type HostOrder } from '../model/commerce-orders'\nimport { escapeHtml } from './escape-html'\n\n/**\n * The packing slip (the order dialog's \"Packing slip\"): the order's number,\n * where it ships and each line with its quantity and SKU, as markup for the\n * print dialog. The console writes it into a print popup; the apps print the\n * same markup, which `commerce/order-print` sends them.\n *\n * ESCAPED (AGL-2283). The console's popup is an `about:blank` document that\n * INHERITS the console's origin, and `order.shippingAddress` is copied\n * verbatim from Stripe's `shipping_details`, i.e. typed by the SHOPPER. A\n * name of `<img src=x onerror=…>` ran script against the merchant's own\n * authenticated session. Line names and SKUs are merchant-authored and lower\n * severity, but they are the same construction and get the same treatment.\n */\nexport function buildPackingSlipHtml(\n order: Pick<HostOrder, 'number' | 'lineItems' | 'shippingAddress'>,\n orderId: string,\n): string {\n const rows = (order.lineItems ?? [])\n .map(\n (line) =>\n `<tr><td>${escapeHtml(line.quantity)}×</td><td>${escapeHtml(line.name)}${\n line.variantLabel ? ` — ${escapeHtml(line.variantLabel)}` : ''\n }</td><td>${escapeHtml(line.sku ?? '')}</td></tr>`,\n )\n .join('')\n const address = order.shippingAddress\n return (\n `<h2>Packing slip ${escapeHtml(formatOrderNumber(order, orderId))}</h2>` +\n (address\n ? `<p>${[\n address.name,\n address.line1,\n address.line2,\n `${address.city ?? ''} ${address.state ?? ''} ${address.postalCode ?? ''}`,\n address.country,\n ]\n .filter(Boolean)\n .map((part) => escapeHtml(part))\n .join('<br/>')}</p>`\n : '') +\n `<table border=\"0\" cellpadding=\"6\">${rows}</table>`\n )\n}\n"],"names":["formatOrderNumber","escapeHtml","buildPackingSlipHtml","order","orderId","address","rows","lineItems","map","line","quantity","name","variantLabel","sku","join","shippingAddress","line1","line2","city","state","postalCode","country","filter","Boolean","part"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,SAASA,iBAAiB,QAAwB,8BAA0B;AAC5E,SAASC,UAAU,QAAQ,mBAAe;AAE1C;;;;;;;;;;;;CAYC,GACD,OAAO,SAASC,qBACdC,KAAkE,EAClEC,OAAe;QAEDD,kBAgBHE,eAAsBA,gBAAuBA;IAhBxD,MAAMC,OAAO,EAACH,mBAAAA,MAAMI,SAAS,YAAfJ,mBAAmB,EAAE,EAChCK,GAAG,CACF,CAACC;YAGwBA;eAFvB,CAAC,QAAQ,EAAER,WAAWQ,KAAKC,QAAQ,EAAE,UAAU,EAAET,WAAWQ,KAAKE,IAAI,IACnEF,KAAKG,YAAY,GAAG,CAAC,GAAG,EAAEX,WAAWQ,KAAKG,YAAY,GAAG,GAAG,GAC7D,SAAS,EAAEX,YAAWQ,YAAAA,KAAKI,GAAG,YAARJ,YAAY,IAAI,UAAU,CAAC;OAErDK,IAAI,CAAC;IACR,MAAMT,UAAUF,MAAMY,eAAe;IACrC,OACE,CAAC,iBAAiB,EAAEd,WAAWD,kBAAkBG,OAAOC,UAAU,KAAK,CAAC,GACvEC,CAAAA,UACG,CAAC,GAAG,EAAE;QACJA,QAAQM,IAAI;QACZN,QAAQW,KAAK;QACbX,QAAQY,KAAK;QACb,IAAGZ,gBAAAA,QAAQa,IAAI,YAAZb,gBAAgB,GAAG,CAAC,GAAEA,iBAAAA,QAAQc,KAAK,YAAbd,iBAAiB,GAAG,CAAC,GAAEA,sBAAAA,QAAQe,UAAU,YAAlBf,sBAAsB,IAAI;QAC1EA,QAAQgB,OAAO;KAChB,CACEC,MAAM,CAACC,SACPf,GAAG,CAAC,CAACgB,OAASvB,WAAWuB,OACzBV,IAAI,CAAC,SAAS,IAAI,CAAC,GACtB,EAAC,IACL,CAAC,kCAAkC,EAAER,KAAK,QAAQ,CAAC;AAEvD"}
|