punchout-simulator 0.6.1 → 0.7.1
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 +6 -0
- package/dist/server/cli.js +184 -73
- 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
|
@@ -167,6 +167,12 @@ SetupRequest → catalog → cart → OrderRequest → OrderResponse. The **Sess
|
|
|
167
167
|
- **inspect** — view a previously ordered item read-only (`operation="inspect"`),
|
|
168
168
|
carrying that item (or the whole source cart) as `ItemOut`.
|
|
169
169
|
|
|
170
|
+
The built-in **mock supplier honours these on the receiving side too**: an
|
|
171
|
+
`edit` pre-fills the catalog quantities from the carried `ItemOut` (items it
|
|
172
|
+
doesn't list appear as extra "from cart" rows), and an `inspect` shows the
|
|
173
|
+
item(s) read-only and returns them unchanged — so the full round-trip is
|
|
174
|
+
exercisable end-to-end against the built-in mock.
|
|
175
|
+
|
|
170
176
|
Connections/Buyers/Suppliers/Products/Profiles remain under **Configure** — you set
|
|
171
177
|
them up there, then run them from **Sessions**.
|
|
172
178
|
|
package/dist/server/cli.js
CHANGED
|
@@ -94,13 +94,34 @@ var PROFILE_PRESETS = [
|
|
|
94
94
|
shipToInSetup: false,
|
|
95
95
|
contactInSetup: false
|
|
96
96
|
},
|
|
97
|
+
// Jaggaer (formerly SciQuest) is observed sending TWO different UserAgent
|
|
98
|
+
// strings in the wild — the modern "JAGGAER" and the legacy "SciQuest" — so we
|
|
99
|
+
// ship both presets. They are identical except for name + userAgent, letting
|
|
100
|
+
// you faithfully reproduce whichever tenant you're testing against. DTD 1.2.011
|
|
101
|
+
// is confirmed on real OrderRequests for both; setup requests are assumed to
|
|
102
|
+
// use the same version (set as `default`, easily overridden per document type).
|
|
97
103
|
{
|
|
98
104
|
id: "jaggaer",
|
|
99
|
-
name: "
|
|
105
|
+
name: "Jaggaer",
|
|
100
106
|
platform: "Jaggaer",
|
|
101
107
|
builtin: true,
|
|
102
|
-
dtdVersions: { default: "1.2.
|
|
103
|
-
userAgent: "JAGGAER
|
|
108
|
+
dtdVersions: { default: "1.2.011" },
|
|
109
|
+
userAgent: "JAGGAER",
|
|
110
|
+
setupOperation: "create",
|
|
111
|
+
attachmentEncoding: "binary",
|
|
112
|
+
cartReturnTransport: "cxml-urlencoded",
|
|
113
|
+
extrinsics: [],
|
|
114
|
+
addressMode: "full",
|
|
115
|
+
shipToInSetup: false,
|
|
116
|
+
contactInSetup: false
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
id: "jaggaer-sciquest",
|
|
120
|
+
name: "Jaggaer (SciQuest)",
|
|
121
|
+
platform: "Jaggaer",
|
|
122
|
+
builtin: true,
|
|
123
|
+
dtdVersions: { default: "1.2.011" },
|
|
124
|
+
userAgent: "SciQuest",
|
|
104
125
|
setupOperation: "create",
|
|
105
126
|
attachmentEncoding: "binary",
|
|
106
127
|
cartReturnTransport: "cxml-urlencoded",
|
|
@@ -553,6 +574,12 @@ function migrateProfiles(data) {
|
|
|
553
574
|
p.shipToInSetup ??= preset?.shipToInSetup ?? false;
|
|
554
575
|
p.contactInSetup ??= preset?.contactInSetup ?? false;
|
|
555
576
|
}
|
|
577
|
+
const jaggaer = data.profiles.find((p) => p.id === "jaggaer" && p.builtin);
|
|
578
|
+
if (jaggaer && jaggaer.name === "JAGGAER" && jaggaer.userAgent === "JAGGAER Procurement") {
|
|
579
|
+
jaggaer.name = "Jaggaer";
|
|
580
|
+
jaggaer.userAgent = "JAGGAER";
|
|
581
|
+
if (jaggaer.dtdVersions?.default === "1.2.021") jaggaer.dtdVersions.default = "1.2.011";
|
|
582
|
+
}
|
|
556
583
|
}
|
|
557
584
|
function migrateClassifications(data) {
|
|
558
585
|
for (const list of data.productLists) {
|
|
@@ -1620,31 +1647,39 @@ function collectCidReferences(doc) {
|
|
|
1620
1647
|
});
|
|
1621
1648
|
return refs;
|
|
1622
1649
|
}
|
|
1650
|
+
function itemFromNode(it) {
|
|
1651
|
+
const detail = it?.ItemDetail;
|
|
1652
|
+
const up = money(detail?.UnitPrice);
|
|
1653
|
+
const classifications = asArray(detail?.Classification).filter((c) => c != null).map((c) => ({ domain: attr(c, "domain") ?? "", value: text(c) ?? "" }));
|
|
1654
|
+
const classFirst = classifications[0];
|
|
1655
|
+
return {
|
|
1656
|
+
quantity: Number(attr(it, "quantity") ?? "1") || 1,
|
|
1657
|
+
supplierPartId: text(it?.ItemID?.SupplierPartID),
|
|
1658
|
+
supplierPartAuxiliaryId: text(it?.ItemID?.SupplierPartAuxiliaryID),
|
|
1659
|
+
description: text(detail?.Description),
|
|
1660
|
+
uom: text(detail?.UnitOfMeasure),
|
|
1661
|
+
unitPriceAmount: up.amount,
|
|
1662
|
+
currency: up.currency,
|
|
1663
|
+
classifications: classifications.length > 0 ? classifications : void 0,
|
|
1664
|
+
classificationDomain: classFirst?.domain,
|
|
1665
|
+
classification: classFirst?.value,
|
|
1666
|
+
manufacturerPartId: text(detail?.ManufacturerPartID),
|
|
1667
|
+
manufacturerName: text(detail?.ManufacturerName)
|
|
1668
|
+
};
|
|
1669
|
+
}
|
|
1670
|
+
function parseSetupItems(doc) {
|
|
1671
|
+
const sr = root(doc)?.Request?.PunchOutSetupRequest;
|
|
1672
|
+
return {
|
|
1673
|
+
operation: attr(sr, "operation") ?? "create",
|
|
1674
|
+
items: asArray(sr?.ItemOut).map(itemFromNode)
|
|
1675
|
+
};
|
|
1676
|
+
}
|
|
1623
1677
|
function parseCart(doc) {
|
|
1624
1678
|
const pom = root(doc)?.Message?.PunchOutOrderMessage;
|
|
1625
1679
|
const sessionId = text(pom?.BuyerCookie) ?? "";
|
|
1626
1680
|
const headerNode = pom?.PunchOutOrderMessageHeader;
|
|
1627
1681
|
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
|
-
});
|
|
1682
|
+
const items = asArray(pom?.ItemIn).map(itemFromNode);
|
|
1648
1683
|
return {
|
|
1649
1684
|
sessionId,
|
|
1650
1685
|
operationAllowed: attr(headerNode, "operationAllowed"),
|
|
@@ -2522,6 +2557,20 @@ var catalogOf = (s) => {
|
|
|
2522
2557
|
const items = catalogForSupplier(s);
|
|
2523
2558
|
return items.length > 0 ? items : DEMO_CATALOG;
|
|
2524
2559
|
};
|
|
2560
|
+
function setupContextFor(cookie) {
|
|
2561
|
+
if (!cookie) return { operation: "create", items: [] };
|
|
2562
|
+
const records = readSession(cookie);
|
|
2563
|
+
for (let i = records.length - 1; i >= 0; i--) {
|
|
2564
|
+
const r = records[i];
|
|
2565
|
+
if (r.direction === "in" && r.docType === "SetupRequest") {
|
|
2566
|
+
return parseSetupItems(parseXml(r.body));
|
|
2567
|
+
}
|
|
2568
|
+
}
|
|
2569
|
+
return { operation: "create", items: [] };
|
|
2570
|
+
}
|
|
2571
|
+
function sameProduct(a, b) {
|
|
2572
|
+
return !!a.supplierPartId && a.supplierPartId === b.supplierPartId && (a.supplierPartAuxiliaryId ?? "") === (b.supplierPartAuxiliaryId ?? "");
|
|
2573
|
+
}
|
|
2525
2574
|
function safeHttpUrl(u) {
|
|
2526
2575
|
if (!u) return "";
|
|
2527
2576
|
try {
|
|
@@ -2590,26 +2639,46 @@ simRoute.post("/:id/punchout", async (c) => {
|
|
|
2590
2639
|
c.header("Content-Type", "text/xml; charset=UTF-8");
|
|
2591
2640
|
return c.body(respXml);
|
|
2592
2641
|
});
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2642
|
+
var catalogView = (it) => ({
|
|
2643
|
+
description: it.description,
|
|
2644
|
+
supplierPartId: it.supplierPartId,
|
|
2645
|
+
supplierPartAuxiliaryId: it.supplierPartAuxiliaryId,
|
|
2646
|
+
uom: it.uom,
|
|
2647
|
+
currency: it.currency,
|
|
2648
|
+
price: it.unitPrice,
|
|
2649
|
+
classifications: it.classifications
|
|
2650
|
+
});
|
|
2651
|
+
var cartView = (it) => ({
|
|
2652
|
+
description: it.description,
|
|
2653
|
+
supplierPartId: it.supplierPartId,
|
|
2654
|
+
supplierPartAuxiliaryId: it.supplierPartAuxiliaryId,
|
|
2655
|
+
uom: it.uom,
|
|
2656
|
+
currency: it.currency,
|
|
2657
|
+
price: it.unitPriceAmount,
|
|
2658
|
+
classifications: it.classifications
|
|
2659
|
+
});
|
|
2660
|
+
function rowLabelCells(v) {
|
|
2661
|
+
const partId = escapeXml(v.supplierPartId ?? "") + (v.supplierPartAuxiliaryId ? ` / ${escapeXml(v.supplierPartAuxiliaryId)}` : "");
|
|
2662
|
+
const cls = (v.classifications ?? []).map((c) => `${escapeXml(c.domain)} ${escapeXml(c.value)}`).join(" \xB7 ");
|
|
2663
|
+
return `<td><strong>${escapeXml(v.description ?? "")}</strong><br><small>${partId} \xB7 ${escapeXml(v.uom ?? "")}${cls ? ` \xB7 ${cls}` : ""}</small></td>
|
|
2664
|
+
<td class="price">${escapeXml(v.currency ?? "")} ${(v.price ?? 0).toFixed(2)}</td>`;
|
|
2665
|
+
}
|
|
2666
|
+
function qtyRow(v, name, value, fractional, tag) {
|
|
2667
|
+
return `<tr>
|
|
2668
|
+
${rowLabelCells(v)}
|
|
2669
|
+
<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
2670
|
</tr>`;
|
|
2609
|
-
|
|
2610
|
-
|
|
2671
|
+
}
|
|
2672
|
+
function readonlyRow(v, qty) {
|
|
2673
|
+
return `<tr>
|
|
2674
|
+
${rowLabelCells(v)}
|
|
2675
|
+
<td class="ro">${escapeXml(qty)}</td>
|
|
2676
|
+
</tr>`;
|
|
2677
|
+
}
|
|
2678
|
+
function catalogPage(o) {
|
|
2679
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8">
|
|
2611
2680
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
2612
|
-
<title>${escapeXml(supplier.name)} \u2014 mock catalog</title>
|
|
2681
|
+
<title>${escapeXml(o.supplier.name)} \u2014 mock catalog</title>
|
|
2613
2682
|
<script>
|
|
2614
2683
|
// Match the main app's theme. The app appends ?theme= to the catalog link
|
|
2615
2684
|
// (works even when the SPA is on a different origin, e.g. the Vite dev server);
|
|
@@ -2627,31 +2696,61 @@ simRoute.get("/:id/catalog", (c) => {
|
|
|
2627
2696
|
})();
|
|
2628
2697
|
</script>
|
|
2629
2698
|
<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}
|
|
2699
|
+
:root{--bg:#0f172a;--text:#e2e8f0;--muted:#94a3b8;--panel:#1e293b;--th:#0b1220;--border:#334155;--field:#0b1220;--price:#fbbf24;--accent:#6366f1;--accent-hover:#4f46e5;--banner:#1e293b}
|
|
2700
|
+
: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
2701
|
body{font-family:system-ui,sans-serif;background:var(--bg);color:var(--text);margin:0;padding:2rem}
|
|
2633
2702
|
.wrap{max-width:720px;margin:0 auto}
|
|
2634
2703
|
h1{font-size:1.4rem}.sub{color:var(--muted);margin-bottom:1.5rem}
|
|
2704
|
+
.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}
|
|
2705
|
+
.banner.inspect{border-left-color:var(--price)}
|
|
2635
2706
|
table{width:100%;border-collapse:collapse;background:var(--panel);border-radius:12px;overflow:hidden}
|
|
2636
2707
|
th,td{padding:.75rem 1rem;text-align:left;border-bottom:1px solid var(--border)}
|
|
2637
2708
|
th{background:var(--th);font-size:.8rem;text-transform:uppercase;letter-spacing:.05em;color:var(--muted)}
|
|
2638
2709
|
.price{white-space:nowrap;color:var(--price)}
|
|
2710
|
+
.ro{color:var(--muted)}
|
|
2711
|
+
.tag{font-size:.7rem;color:var(--muted);text-transform:uppercase;letter-spacing:.04em;margin-left:.4rem}
|
|
2639
2712
|
input[type=number]{width:5rem;background:var(--field);border:1px solid var(--border);color:var(--text);border-radius:6px;padding:.35rem .5rem}
|
|
2640
2713
|
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
2714
|
button:hover{background:var(--accent-hover)}
|
|
2642
2715
|
</style></head><body><div class="wrap">
|
|
2643
|
-
<h1>${escapeXml(supplier.name)} <small>(virtual supplier)</small></h1>
|
|
2716
|
+
<h1>${escapeXml(o.supplier.name)} <small>(virtual supplier)</small></h1>
|
|
2644
2717
|
<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="
|
|
2718
|
+
${o.banner}
|
|
2719
|
+
<form method="post" action="${getPublicUrl()}/sim/${o.supplier.id}/checkout">
|
|
2720
|
+
<input type="hidden" name="cookie" value="${escapeXml(o.cookie)}">
|
|
2721
|
+
<input type="hidden" name="formpost" value="${escapeXml(o.formpost)}">
|
|
2722
|
+
<input type="hidden" name="bd" value="${escapeXml(o.bd)}">
|
|
2723
|
+
<input type="hidden" name="bi" value="${escapeXml(o.bi)}">
|
|
2650
2724
|
<table><thead><tr><th>Item</th><th>Price</th><th>Qty</th></tr></thead>
|
|
2651
|
-
<tbody>${rows}</tbody></table>
|
|
2652
|
-
<button type="submit"
|
|
2725
|
+
<tbody>${o.rows}</tbody></table>
|
|
2726
|
+
<button type="submit">${escapeXml(o.submitLabel)}</button>
|
|
2653
2727
|
</form>
|
|
2654
|
-
</div></body></html
|
|
2728
|
+
</div></body></html>`;
|
|
2729
|
+
}
|
|
2730
|
+
simRoute.get("/:id/catalog", (c) => {
|
|
2731
|
+
const supplier = getSupplier(c.req.param("id"));
|
|
2732
|
+
if (!supplier) return c.text("supplier not found", 404);
|
|
2733
|
+
const cookie = c.req.query("cookie") ?? "";
|
|
2734
|
+
const formpost = safeHttpUrl(c.req.query("formpost") ?? "");
|
|
2735
|
+
const bd = c.req.query("bd") ?? "";
|
|
2736
|
+
const bi = c.req.query("bi") ?? "";
|
|
2737
|
+
const items = catalogOf(supplier);
|
|
2738
|
+
const ctx = setupContextFor(cookie);
|
|
2739
|
+
const page = (banner2, rows2, submitLabel) => c.html(catalogPage({ supplier, banner: banner2, rows: rows2, submitLabel, cookie, formpost, bd, bi }));
|
|
2740
|
+
if (ctx.operation === "inspect" && ctx.items.length > 0) {
|
|
2741
|
+
const rows2 = ctx.items.map((it) => readonlyRow(cartView(it), it.quantity)).join("\n");
|
|
2742
|
+
const banner2 = `<div class="banner inspect">Inspect \u2014 ${ctx.items.length} item(s), read-only. Returning the cart unchanged to the buyer.</div>`;
|
|
2743
|
+
return page(banner2, rows2, "Return to buyer \u2192");
|
|
2744
|
+
}
|
|
2745
|
+
const isEdit = ctx.operation === "edit";
|
|
2746
|
+
const prefill = (it) => isEdit ? ctx.items.find((p) => sameProduct(p, it))?.quantity ?? 0 : 0;
|
|
2747
|
+
const catalogRows = items.map((it, i) => qtyRow(catalogView(it), `q_${i}`, prefill(it), !!it.allowFractional)).join("\n");
|
|
2748
|
+
const extras = isEdit ? ctx.items.filter((p) => !items.some((it) => sameProduct(p, it))) : [];
|
|
2749
|
+
const extraRows = extras.map((p, j) => qtyRow(cartView(p), `qx_${j}`, p.quantity, true, "from cart")).join("\n");
|
|
2750
|
+
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>` : "";
|
|
2751
|
+
const rows = extraRows ? `${catalogRows}
|
|
2752
|
+
${extraRows}` : catalogRows;
|
|
2753
|
+
return page(banner, rows, "Return cart to buyer \u2192");
|
|
2655
2754
|
});
|
|
2656
2755
|
simRoute.post("/:id/checkout", async (c) => {
|
|
2657
2756
|
const supplier = getSupplier(c.req.param("id"));
|
|
@@ -2664,29 +2763,41 @@ simRoute.post("/:id/checkout", async (c) => {
|
|
|
2664
2763
|
const formpost = safeHttpUrl(String(form.formpost ?? ""));
|
|
2665
2764
|
const buyerCred = { domain: String(form.bd ?? ""), identity: String(form.bi ?? "") };
|
|
2666
2765
|
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
|
-
|
|
2766
|
+
const ctx = setupContextFor(cookie);
|
|
2767
|
+
let items = [];
|
|
2768
|
+
if (ctx.operation === "inspect" && ctx.items.length > 0) {
|
|
2769
|
+
items = ctx.items;
|
|
2770
|
+
} else {
|
|
2771
|
+
catalog.forEach((it, i) => {
|
|
2772
|
+
let qty = Number(form[`q_${i}`] ?? 0);
|
|
2773
|
+
if (!it.allowFractional) qty = Math.floor(qty);
|
|
2774
|
+
if (qty > 0) {
|
|
2775
|
+
items.push({
|
|
2776
|
+
quantity: qty,
|
|
2777
|
+
supplierPartId: it.supplierPartId,
|
|
2778
|
+
supplierPartAuxiliaryId: it.supplierPartAuxiliaryId,
|
|
2779
|
+
description: it.description,
|
|
2780
|
+
uom: it.uom,
|
|
2781
|
+
unitPriceAmount: it.unitPrice,
|
|
2782
|
+
currency: it.currency,
|
|
2783
|
+
classifications: it.classifications,
|
|
2784
|
+
// Keep the legacy single fields populated from the first classification
|
|
2785
|
+
// for back-compat display (CartView) and any single-domain consumer.
|
|
2786
|
+
classificationDomain: it.classifications[0]?.domain,
|
|
2787
|
+
classification: it.classifications[0]?.value,
|
|
2788
|
+
manufacturerPartId: it.manufacturerPartId,
|
|
2789
|
+
manufacturerName: it.manufacturerName
|
|
2790
|
+
});
|
|
2791
|
+
}
|
|
2792
|
+
});
|
|
2793
|
+
if (ctx.operation === "edit") {
|
|
2794
|
+
const extras = ctx.items.filter((p) => !catalog.some((it) => sameProduct(p, it)));
|
|
2795
|
+
extras.forEach((p, j) => {
|
|
2796
|
+
const qty = Number(form[`qx_${j}`] ?? p.quantity);
|
|
2797
|
+
if (qty > 0) items.push({ ...p, quantity: qty });
|
|
2687
2798
|
});
|
|
2688
2799
|
}
|
|
2689
|
-
}
|
|
2800
|
+
}
|
|
2690
2801
|
const currency = items[0]?.currency ?? "USD";
|
|
2691
2802
|
const eff = effFor(supplier.id, buyerCred);
|
|
2692
2803
|
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
|