punchout-simulator 0.6.0 → 0.7.0
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/README.md +12 -9
- package/dist/server/cli.js +154 -70
- package/dist/web/assets/{cssMode-DipgJtey.js → cssMode-CML7oWhl.js} +1 -1
- package/dist/web/assets/{freemarker2-Broesno_.js → freemarker2-DpUbnEBX.js} +1 -1
- package/dist/web/assets/{handlebars-CjP6B5LA.js → handlebars-DtiE3_zM.js} +1 -1
- package/dist/web/assets/{html-DRw6NWlS.js → html-D9vzMDGU.js} +1 -1
- package/dist/web/assets/{htmlMode-CRd2lx43.js → htmlMode-DiAxG3yO.js} +1 -1
- package/dist/web/assets/{index-ByIxIbJu.js → index-Dr4reAcK.js} +93 -93
- package/dist/web/assets/{javascript-C_i2lhIv.js → javascript-CG27Sy2X.js} +1 -1
- package/dist/web/assets/{jsonMode-BgryI0EY.js → jsonMode-CM1NhC2e.js} +1 -1
- package/dist/web/assets/{liquid-7FQOG1B6.js → liquid-DhTmMwdB.js} +1 -1
- package/dist/web/assets/{mdx-qBzkPJqp.js → mdx-Bko-2_2F.js} +1 -1
- package/dist/web/assets/{python-B4DngJbm.js → python-CoX_iu2v.js} +1 -1
- package/dist/web/assets/{razor-C_lSlak7.js → razor-DUp-cZOM.js} +1 -1
- package/dist/web/assets/{tsMode-Xnz0Jk77.js → tsMode-ChruN2wc.js} +1 -1
- package/dist/web/assets/{typescript-d2XcegVU.js → typescript-C86bzGdJ.js} +1 -1
- package/dist/web/assets/{xml-D_x-LgOL.js → xml-BgJr7ceZ.js} +1 -1
- package/dist/web/assets/{yaml-gU-APWSC.js → yaml-BEM-5dxl.js} +1 -1
- package/dist/web/index.html +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,10 +18,12 @@ It is role-neutral and runs in two modes (mirror images of each other):
|
|
|
18
18
|
|
|
19
19
|
Protocol scope: **cXML only**.
|
|
20
20
|
|
|
21
|
-
> **New to PunchOut, or want the full picture?**
|
|
22
|
-
> [
|
|
23
|
-
> the [
|
|
24
|
-
> [
|
|
21
|
+
> **New to PunchOut, or want the full picture?** Read the in-depth reports at
|
|
22
|
+
> [**slawomir-szostak.github.io/punchout-simulator**](https://slawomir-szostak.github.io/punchout-simulator/):
|
|
23
|
+
> the [PunchOut business primer](https://slawomir-szostak.github.io/punchout-simulator/punchout-business-primer_en.html),
|
|
24
|
+
> the [Architecture reference](https://slawomir-szostak.github.io/punchout-simulator/architecture_en.html),
|
|
25
|
+
> and the [Operations & usage guide](https://slawomir-szostak.github.io/punchout-simulator/operations-guide_en.html).
|
|
26
|
+
> (Markdown sources live in [`docs/`](docs/).)
|
|
25
27
|
|
|
26
28
|
---
|
|
27
29
|
|
|
@@ -206,12 +208,13 @@ src/
|
|
|
206
208
|
|
|
207
209
|
For a deeper treatment — component breakdown, the full data model, and Mode A /
|
|
208
210
|
Mode B sequence diagrams — see the
|
|
209
|
-
[**Architecture reference**](
|
|
210
|
-
|
|
211
|
+
[**Architecture reference**](https://slawomir-szostak.github.io/punchout-simulator/architecture_en.html).
|
|
212
|
+
Alongside it: a [**PunchOut business primer**](https://slawomir-szostak.github.io/punchout-simulator/punchout-business-primer_en.html)
|
|
211
213
|
(the business process and where this tool fits) and an
|
|
212
|
-
[**Operations & usage guide**](
|
|
213
|
-
operations, profiles, product lists, validation).
|
|
214
|
-
|
|
214
|
+
[**Operations & usage guide**](https://slawomir-szostak.github.io/punchout-simulator/operations-guide_en.html)
|
|
215
|
+
(sessions, operations, profiles, product lists, validation). These render at
|
|
216
|
+
[slawomir-szostak.github.io/punchout-simulator](https://slawomir-szostak.github.io/punchout-simulator/);
|
|
217
|
+
their canonical Markdown sources live in [`docs/`](docs/).
|
|
215
218
|
|
|
216
219
|
### Data model
|
|
217
220
|
|
package/dist/server/cli.js
CHANGED
|
@@ -1620,31 +1620,39 @@ function collectCidReferences(doc) {
|
|
|
1620
1620
|
});
|
|
1621
1621
|
return refs;
|
|
1622
1622
|
}
|
|
1623
|
+
function itemFromNode(it) {
|
|
1624
|
+
const detail = it?.ItemDetail;
|
|
1625
|
+
const up = money(detail?.UnitPrice);
|
|
1626
|
+
const classifications = asArray(detail?.Classification).filter((c) => c != null).map((c) => ({ domain: attr(c, "domain") ?? "", value: text(c) ?? "" }));
|
|
1627
|
+
const classFirst = classifications[0];
|
|
1628
|
+
return {
|
|
1629
|
+
quantity: Number(attr(it, "quantity") ?? "1") || 1,
|
|
1630
|
+
supplierPartId: text(it?.ItemID?.SupplierPartID),
|
|
1631
|
+
supplierPartAuxiliaryId: text(it?.ItemID?.SupplierPartAuxiliaryID),
|
|
1632
|
+
description: text(detail?.Description),
|
|
1633
|
+
uom: text(detail?.UnitOfMeasure),
|
|
1634
|
+
unitPriceAmount: up.amount,
|
|
1635
|
+
currency: up.currency,
|
|
1636
|
+
classifications: classifications.length > 0 ? classifications : void 0,
|
|
1637
|
+
classificationDomain: classFirst?.domain,
|
|
1638
|
+
classification: classFirst?.value,
|
|
1639
|
+
manufacturerPartId: text(detail?.ManufacturerPartID),
|
|
1640
|
+
manufacturerName: text(detail?.ManufacturerName)
|
|
1641
|
+
};
|
|
1642
|
+
}
|
|
1643
|
+
function parseSetupItems(doc) {
|
|
1644
|
+
const sr = root(doc)?.Request?.PunchOutSetupRequest;
|
|
1645
|
+
return {
|
|
1646
|
+
operation: attr(sr, "operation") ?? "create",
|
|
1647
|
+
items: asArray(sr?.ItemOut).map(itemFromNode)
|
|
1648
|
+
};
|
|
1649
|
+
}
|
|
1623
1650
|
function parseCart(doc) {
|
|
1624
1651
|
const pom = root(doc)?.Message?.PunchOutOrderMessage;
|
|
1625
1652
|
const sessionId = text(pom?.BuyerCookie) ?? "";
|
|
1626
1653
|
const headerNode = pom?.PunchOutOrderMessageHeader;
|
|
1627
1654
|
const total = money(headerNode?.Total);
|
|
1628
|
-
const items = asArray(pom?.ItemIn).map(
|
|
1629
|
-
const detail = it?.ItemDetail;
|
|
1630
|
-
const up = money(detail?.UnitPrice);
|
|
1631
|
-
const classifications = asArray(detail?.Classification).filter((c) => c != null).map((c) => ({ domain: attr(c, "domain") ?? "", value: text(c) ?? "" }));
|
|
1632
|
-
const classFirst = classifications[0];
|
|
1633
|
-
return {
|
|
1634
|
-
quantity: Number(attr(it, "quantity") ?? "1") || 1,
|
|
1635
|
-
supplierPartId: text(it?.ItemID?.SupplierPartID),
|
|
1636
|
-
supplierPartAuxiliaryId: text(it?.ItemID?.SupplierPartAuxiliaryID),
|
|
1637
|
-
description: text(detail?.Description),
|
|
1638
|
-
uom: text(detail?.UnitOfMeasure),
|
|
1639
|
-
unitPriceAmount: up.amount,
|
|
1640
|
-
currency: up.currency,
|
|
1641
|
-
classifications: classifications.length > 0 ? classifications : void 0,
|
|
1642
|
-
classificationDomain: classFirst?.domain,
|
|
1643
|
-
classification: classFirst?.value,
|
|
1644
|
-
manufacturerPartId: text(detail?.ManufacturerPartID),
|
|
1645
|
-
manufacturerName: text(detail?.ManufacturerName)
|
|
1646
|
-
};
|
|
1647
|
-
});
|
|
1655
|
+
const items = asArray(pom?.ItemIn).map(itemFromNode);
|
|
1648
1656
|
return {
|
|
1649
1657
|
sessionId,
|
|
1650
1658
|
operationAllowed: attr(headerNode, "operationAllowed"),
|
|
@@ -2522,6 +2530,20 @@ var catalogOf = (s) => {
|
|
|
2522
2530
|
const items = catalogForSupplier(s);
|
|
2523
2531
|
return items.length > 0 ? items : DEMO_CATALOG;
|
|
2524
2532
|
};
|
|
2533
|
+
function setupContextFor(cookie) {
|
|
2534
|
+
if (!cookie) return { operation: "create", items: [] };
|
|
2535
|
+
const records = readSession(cookie);
|
|
2536
|
+
for (let i = records.length - 1; i >= 0; i--) {
|
|
2537
|
+
const r = records[i];
|
|
2538
|
+
if (r.direction === "in" && r.docType === "SetupRequest") {
|
|
2539
|
+
return parseSetupItems(parseXml(r.body));
|
|
2540
|
+
}
|
|
2541
|
+
}
|
|
2542
|
+
return { operation: "create", items: [] };
|
|
2543
|
+
}
|
|
2544
|
+
function sameProduct(a, b) {
|
|
2545
|
+
return !!a.supplierPartId && a.supplierPartId === b.supplierPartId && (a.supplierPartAuxiliaryId ?? "") === (b.supplierPartAuxiliaryId ?? "");
|
|
2546
|
+
}
|
|
2525
2547
|
function safeHttpUrl(u) {
|
|
2526
2548
|
if (!u) return "";
|
|
2527
2549
|
try {
|
|
@@ -2590,26 +2612,46 @@ simRoute.post("/:id/punchout", async (c) => {
|
|
|
2590
2612
|
c.header("Content-Type", "text/xml; charset=UTF-8");
|
|
2591
2613
|
return c.body(respXml);
|
|
2592
2614
|
});
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2615
|
+
var catalogView = (it) => ({
|
|
2616
|
+
description: it.description,
|
|
2617
|
+
supplierPartId: it.supplierPartId,
|
|
2618
|
+
supplierPartAuxiliaryId: it.supplierPartAuxiliaryId,
|
|
2619
|
+
uom: it.uom,
|
|
2620
|
+
currency: it.currency,
|
|
2621
|
+
price: it.unitPrice,
|
|
2622
|
+
classifications: it.classifications
|
|
2623
|
+
});
|
|
2624
|
+
var cartView = (it) => ({
|
|
2625
|
+
description: it.description,
|
|
2626
|
+
supplierPartId: it.supplierPartId,
|
|
2627
|
+
supplierPartAuxiliaryId: it.supplierPartAuxiliaryId,
|
|
2628
|
+
uom: it.uom,
|
|
2629
|
+
currency: it.currency,
|
|
2630
|
+
price: it.unitPriceAmount,
|
|
2631
|
+
classifications: it.classifications
|
|
2632
|
+
});
|
|
2633
|
+
function rowLabelCells(v) {
|
|
2634
|
+
const partId = escapeXml(v.supplierPartId ?? "") + (v.supplierPartAuxiliaryId ? ` / ${escapeXml(v.supplierPartAuxiliaryId)}` : "");
|
|
2635
|
+
const cls = (v.classifications ?? []).map((c) => `${escapeXml(c.domain)} ${escapeXml(c.value)}`).join(" \xB7 ");
|
|
2636
|
+
return `<td><strong>${escapeXml(v.description ?? "")}</strong><br><small>${partId} \xB7 ${escapeXml(v.uom ?? "")}${cls ? ` \xB7 ${cls}` : ""}</small></td>
|
|
2637
|
+
<td class="price">${escapeXml(v.currency ?? "")} ${(v.price ?? 0).toFixed(2)}</td>`;
|
|
2638
|
+
}
|
|
2639
|
+
function qtyRow(v, name, value, fractional, tag) {
|
|
2640
|
+
return `<tr>
|
|
2641
|
+
${rowLabelCells(v)}
|
|
2642
|
+
<td><input type="number" name="${name}" value="${escapeXml(value)}" min="0" step="${fractional ? "any" : "1"}" inputmode="${fractional ? "decimal" : "numeric"}">${tag ? ` <span class="tag">${tag}</span>` : ""}</td>
|
|
2608
2643
|
</tr>`;
|
|
2609
|
-
|
|
2610
|
-
|
|
2644
|
+
}
|
|
2645
|
+
function readonlyRow(v, qty) {
|
|
2646
|
+
return `<tr>
|
|
2647
|
+
${rowLabelCells(v)}
|
|
2648
|
+
<td class="ro">${escapeXml(qty)}</td>
|
|
2649
|
+
</tr>`;
|
|
2650
|
+
}
|
|
2651
|
+
function catalogPage(o) {
|
|
2652
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8">
|
|
2611
2653
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
2612
|
-
<title>${escapeXml(supplier.name)} \u2014 mock catalog</title>
|
|
2654
|
+
<title>${escapeXml(o.supplier.name)} \u2014 mock catalog</title>
|
|
2613
2655
|
<script>
|
|
2614
2656
|
// Match the main app's theme. The app appends ?theme= to the catalog link
|
|
2615
2657
|
// (works even when the SPA is on a different origin, e.g. the Vite dev server);
|
|
@@ -2627,31 +2669,61 @@ simRoute.get("/:id/catalog", (c) => {
|
|
|
2627
2669
|
})();
|
|
2628
2670
|
</script>
|
|
2629
2671
|
<style>
|
|
2630
|
-
:root{--bg:#0f172a;--text:#e2e8f0;--muted:#94a3b8;--panel:#1e293b;--th:#0b1220;--border:#334155;--field:#0b1220;--price:#fbbf24;--accent:#6366f1;--accent-hover:#4f46e5}
|
|
2631
|
-
:root[data-theme="light"]{--bg:#f5f7fb;--text:#1e293b;--muted:#4b5a73;--panel:#ffffff;--th:#eef1f7;--border:#d4dae8;--field:#ffffff;--price:#b45309;--accent:#6366f1;--accent-hover:#4f46e5}
|
|
2672
|
+
:root{--bg:#0f172a;--text:#e2e8f0;--muted:#94a3b8;--panel:#1e293b;--th:#0b1220;--border:#334155;--field:#0b1220;--price:#fbbf24;--accent:#6366f1;--accent-hover:#4f46e5;--banner:#1e293b}
|
|
2673
|
+
:root[data-theme="light"]{--bg:#f5f7fb;--text:#1e293b;--muted:#4b5a73;--panel:#ffffff;--th:#eef1f7;--border:#d4dae8;--field:#ffffff;--price:#b45309;--accent:#6366f1;--accent-hover:#4f46e5;--banner:#eef1f7}
|
|
2632
2674
|
body{font-family:system-ui,sans-serif;background:var(--bg);color:var(--text);margin:0;padding:2rem}
|
|
2633
2675
|
.wrap{max-width:720px;margin:0 auto}
|
|
2634
2676
|
h1{font-size:1.4rem}.sub{color:var(--muted);margin-bottom:1.5rem}
|
|
2677
|
+
.banner{background:var(--banner);border:1px solid var(--border);border-left:4px solid var(--accent);border-radius:8px;padding:.7rem 1rem;margin-bottom:1.25rem;font-size:.95rem}
|
|
2678
|
+
.banner.inspect{border-left-color:var(--price)}
|
|
2635
2679
|
table{width:100%;border-collapse:collapse;background:var(--panel);border-radius:12px;overflow:hidden}
|
|
2636
2680
|
th,td{padding:.75rem 1rem;text-align:left;border-bottom:1px solid var(--border)}
|
|
2637
2681
|
th{background:var(--th);font-size:.8rem;text-transform:uppercase;letter-spacing:.05em;color:var(--muted)}
|
|
2638
2682
|
.price{white-space:nowrap;color:var(--price)}
|
|
2683
|
+
.ro{color:var(--muted)}
|
|
2684
|
+
.tag{font-size:.7rem;color:var(--muted);text-transform:uppercase;letter-spacing:.04em;margin-left:.4rem}
|
|
2639
2685
|
input[type=number]{width:5rem;background:var(--field);border:1px solid var(--border);color:var(--text);border-radius:6px;padding:.35rem .5rem}
|
|
2640
2686
|
button{margin-top:1.5rem;background:var(--accent);color:#fff;border:0;border-radius:8px;padding:.7rem 1.4rem;font-size:1rem;cursor:pointer}
|
|
2641
2687
|
button:hover{background:var(--accent-hover)}
|
|
2642
2688
|
</style></head><body><div class="wrap">
|
|
2643
|
-
<h1>${escapeXml(supplier.name)} <small>(virtual supplier)</small></h1>
|
|
2689
|
+
<h1>${escapeXml(o.supplier.name)} <small>(virtual supplier)</small></h1>
|
|
2644
2690
|
<div class="sub">Mock catalog served by punchout-simulator. Set quantities and return the cart.</div>
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
<input type="hidden" name="
|
|
2648
|
-
<input type="hidden" name="
|
|
2649
|
-
<input type="hidden" name="
|
|
2691
|
+
${o.banner}
|
|
2692
|
+
<form method="post" action="${getPublicUrl()}/sim/${o.supplier.id}/checkout">
|
|
2693
|
+
<input type="hidden" name="cookie" value="${escapeXml(o.cookie)}">
|
|
2694
|
+
<input type="hidden" name="formpost" value="${escapeXml(o.formpost)}">
|
|
2695
|
+
<input type="hidden" name="bd" value="${escapeXml(o.bd)}">
|
|
2696
|
+
<input type="hidden" name="bi" value="${escapeXml(o.bi)}">
|
|
2650
2697
|
<table><thead><tr><th>Item</th><th>Price</th><th>Qty</th></tr></thead>
|
|
2651
|
-
<tbody>${rows}</tbody></table>
|
|
2652
|
-
<button type="submit"
|
|
2698
|
+
<tbody>${o.rows}</tbody></table>
|
|
2699
|
+
<button type="submit">${escapeXml(o.submitLabel)}</button>
|
|
2653
2700
|
</form>
|
|
2654
|
-
</div></body></html
|
|
2701
|
+
</div></body></html>`;
|
|
2702
|
+
}
|
|
2703
|
+
simRoute.get("/:id/catalog", (c) => {
|
|
2704
|
+
const supplier = getSupplier(c.req.param("id"));
|
|
2705
|
+
if (!supplier) return c.text("supplier not found", 404);
|
|
2706
|
+
const cookie = c.req.query("cookie") ?? "";
|
|
2707
|
+
const formpost = safeHttpUrl(c.req.query("formpost") ?? "");
|
|
2708
|
+
const bd = c.req.query("bd") ?? "";
|
|
2709
|
+
const bi = c.req.query("bi") ?? "";
|
|
2710
|
+
const items = catalogOf(supplier);
|
|
2711
|
+
const ctx = setupContextFor(cookie);
|
|
2712
|
+
const page = (banner2, rows2, submitLabel) => c.html(catalogPage({ supplier, banner: banner2, rows: rows2, submitLabel, cookie, formpost, bd, bi }));
|
|
2713
|
+
if (ctx.operation === "inspect" && ctx.items.length > 0) {
|
|
2714
|
+
const rows2 = ctx.items.map((it) => readonlyRow(cartView(it), it.quantity)).join("\n");
|
|
2715
|
+
const banner2 = `<div class="banner inspect">Inspect \u2014 ${ctx.items.length} item(s), read-only. Returning the cart unchanged to the buyer.</div>`;
|
|
2716
|
+
return page(banner2, rows2, "Return to buyer \u2192");
|
|
2717
|
+
}
|
|
2718
|
+
const isEdit = ctx.operation === "edit";
|
|
2719
|
+
const prefill = (it) => isEdit ? ctx.items.find((p) => sameProduct(p, it))?.quantity ?? 0 : 0;
|
|
2720
|
+
const catalogRows = items.map((it, i) => qtyRow(catalogView(it), `q_${i}`, prefill(it), !!it.allowFractional)).join("\n");
|
|
2721
|
+
const extras = isEdit ? ctx.items.filter((p) => !items.some((it) => sameProduct(p, it))) : [];
|
|
2722
|
+
const extraRows = extras.map((p, j) => qtyRow(cartView(p), `qx_${j}`, p.quantity, true, "from cart")).join("\n");
|
|
2723
|
+
const banner = isEdit ? `<div class="banner edit">Edit \u2014 ${ctx.items.length} item(s) pre-loaded from the buyer's cart. Adjust quantities and return.</div>` : "";
|
|
2724
|
+
const rows = extraRows ? `${catalogRows}
|
|
2725
|
+
${extraRows}` : catalogRows;
|
|
2726
|
+
return page(banner, rows, "Return cart to buyer \u2192");
|
|
2655
2727
|
});
|
|
2656
2728
|
simRoute.post("/:id/checkout", async (c) => {
|
|
2657
2729
|
const supplier = getSupplier(c.req.param("id"));
|
|
@@ -2664,29 +2736,41 @@ simRoute.post("/:id/checkout", async (c) => {
|
|
|
2664
2736
|
const formpost = safeHttpUrl(String(form.formpost ?? ""));
|
|
2665
2737
|
const buyerCred = { domain: String(form.bd ?? ""), identity: String(form.bi ?? "") };
|
|
2666
2738
|
const catalog = catalogOf(supplier);
|
|
2667
|
-
const
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2739
|
+
const ctx = setupContextFor(cookie);
|
|
2740
|
+
let items = [];
|
|
2741
|
+
if (ctx.operation === "inspect" && ctx.items.length > 0) {
|
|
2742
|
+
items = ctx.items;
|
|
2743
|
+
} else {
|
|
2744
|
+
catalog.forEach((it, i) => {
|
|
2745
|
+
let qty = Number(form[`q_${i}`] ?? 0);
|
|
2746
|
+
if (!it.allowFractional) qty = Math.floor(qty);
|
|
2747
|
+
if (qty > 0) {
|
|
2748
|
+
items.push({
|
|
2749
|
+
quantity: qty,
|
|
2750
|
+
supplierPartId: it.supplierPartId,
|
|
2751
|
+
supplierPartAuxiliaryId: it.supplierPartAuxiliaryId,
|
|
2752
|
+
description: it.description,
|
|
2753
|
+
uom: it.uom,
|
|
2754
|
+
unitPriceAmount: it.unitPrice,
|
|
2755
|
+
currency: it.currency,
|
|
2756
|
+
classifications: it.classifications,
|
|
2757
|
+
// Keep the legacy single fields populated from the first classification
|
|
2758
|
+
// for back-compat display (CartView) and any single-domain consumer.
|
|
2759
|
+
classificationDomain: it.classifications[0]?.domain,
|
|
2760
|
+
classification: it.classifications[0]?.value,
|
|
2761
|
+
manufacturerPartId: it.manufacturerPartId,
|
|
2762
|
+
manufacturerName: it.manufacturerName
|
|
2763
|
+
});
|
|
2764
|
+
}
|
|
2765
|
+
});
|
|
2766
|
+
if (ctx.operation === "edit") {
|
|
2767
|
+
const extras = ctx.items.filter((p) => !catalog.some((it) => sameProduct(p, it)));
|
|
2768
|
+
extras.forEach((p, j) => {
|
|
2769
|
+
const qty = Number(form[`qx_${j}`] ?? p.quantity);
|
|
2770
|
+
if (qty > 0) items.push({ ...p, quantity: qty });
|
|
2687
2771
|
});
|
|
2688
2772
|
}
|
|
2689
|
-
}
|
|
2773
|
+
}
|
|
2690
2774
|
const currency = items[0]?.currency ?? "USD";
|
|
2691
2775
|
const eff = effFor(supplier.id, buyerCred);
|
|
2692
2776
|
const xml = buildPunchOutOrderMessage({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{m as et}from"./index-
|
|
1
|
+
import{m as et}from"./index-Dr4reAcK.js";/*!-----------------------------------------------------------------------------
|
|
2
2
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
3
|
* Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
|
|
4
4
|
* Released under the MIT license
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{m as f}from"./index-
|
|
1
|
+
import{m as f}from"./index-Dr4reAcK.js";/*!-----------------------------------------------------------------------------
|
|
2
2
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
3
|
* Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
|
|
4
4
|
* Released under the MIT license
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{m as l}from"./index-
|
|
1
|
+
import{m as l}from"./index-Dr4reAcK.js";/*!-----------------------------------------------------------------------------
|
|
2
2
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
3
|
* Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
|
|
4
4
|
* Released under the MIT license
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{m as s}from"./index-
|
|
1
|
+
import{m as s}from"./index-Dr4reAcK.js";/*!-----------------------------------------------------------------------------
|
|
2
2
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
3
|
* Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
|
|
4
4
|
* Released under the MIT license
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{m as lt}from"./index-
|
|
1
|
+
import{m as lt}from"./index-Dr4reAcK.js";/*!-----------------------------------------------------------------------------
|
|
2
2
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
3
|
* Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
|
|
4
4
|
* Released under the MIT license
|