punchout-simulator 0.3.1 → 0.5.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 +46 -7
- package/dist/server/cli.js +482 -90
- package/dist/web/assets/{cssMode-uoWbxmRA.js → cssMode-BbEnQNgt.js} +1 -1
- package/dist/web/assets/{freemarker2-DNR9Witk.js → freemarker2-B66AqaBn.js} +1 -1
- package/dist/web/assets/{handlebars-Cz4BZbpY.js → handlebars-VHNJA3L3.js} +1 -1
- package/dist/web/assets/{html-B08afy-k.js → html-DKhtq5mU.js} +1 -1
- package/dist/web/assets/{htmlMode-DwllrnDj.js → htmlMode-DTvp4_of.js} +1 -1
- package/dist/web/assets/{index-BzgSetIt.js → index-DRD_fRQi.js} +195 -193
- package/dist/web/assets/{index-DLIyRG88.css → index-WgWCySdd.css} +1 -1
- package/dist/web/assets/{javascript-CSO3Lh8M.js → javascript-C7niBpqn.js} +1 -1
- package/dist/web/assets/{jsonMode-BQc0D6l3.js → jsonMode-mhDIEB_U.js} +1 -1
- package/dist/web/assets/{liquid-D_Cq8kS0.js → liquid-v92UUGTF.js} +1 -1
- package/dist/web/assets/{mdx-9UNHMbIw.js → mdx-upBohKLC.js} +1 -1
- package/dist/web/assets/{python-BziTtpp-.js → python-BptHZKfu.js} +1 -1
- package/dist/web/assets/{razor-CqSSZBI0.js → razor-D3-LbWWb.js} +1 -1
- package/dist/web/assets/{tsMode-BXILR9lc.js → tsMode-0LcFoT79.js} +1 -1
- package/dist/web/assets/{typescript-lG76zlZP.js → typescript-ClLaLjem.js} +1 -1
- package/dist/web/assets/{xml-D1mrwtCd.js → xml-BIefLbdX.js} +1 -1
- package/dist/web/assets/{yaml-DWKj4dJQ.js → yaml-D3udJL_a.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -99,8 +99,8 @@ Document-specific:
|
|
|
99
99
|
| Document | Checks |
|
|
100
100
|
|---|---|
|
|
101
101
|
| **PunchOutSetupResponse** | `Status` present & `200`; valid `StartPage/URL` |
|
|
102
|
-
| **PunchOutOrderMessage** (punchback) | `BuyerCookie` matches the session; header `Total`/`Money`+currency; each `ItemIn` has quantity, `SupplierPartID`, `UnitPrice`+currency, `Description`, `UnitOfMeasure`, `Classification`@domain; **Total consistency** (sum of line totals) |
|
|
103
|
-
| **OrderRequest** | `orderID`/`orderDate`/`Total`; `ShipTo`/`BillTo`; each `ItemOut`; **attachment `cid:` resolution** (see below) |
|
|
102
|
+
| **PunchOutOrderMessage** (punchback) | `BuyerCookie` matches the session; header `Total`/`Money`+currency; each `ItemIn` has quantity, `SupplierPartID`, `UnitPrice`+currency, `Description`, `UnitOfMeasure`, `Classification`@domain; **single currency** (mixed-currency is an error unless the supplier allows it); **Total consistency** (sum of line totals) |
|
|
103
|
+
| **OrderRequest** | `orderID`/`orderDate`/`Total`; `ShipTo`/`BillTo` present **and complete** (an `addressID` or a postal Street/City — an empty block is flagged); `Contact@role`; each `ItemOut`; **single currency** (as above); **attachment `cid:` resolution** (see below) |
|
|
104
104
|
| **OrderResponse** | `Status` code present / not an error |
|
|
105
105
|
|
|
106
106
|
> Note: full cXML DTD validation would require a native validating XML parser,
|
|
@@ -167,7 +167,7 @@ backend, so there is no CORS between them).
|
|
|
167
167
|
| XML parsing | `fast-xml-parser` |
|
|
168
168
|
| cXML building | template literals (full control over shape/ordering/`xml:lang`) |
|
|
169
169
|
| multipart/related | hand-assembled (`Buffer` + boundary) |
|
|
170
|
-
| Storage | `lowdb` (`config.json`) for buyers/suppliers/connections/profiles · append-only JSONL per session for logs · separate files for attachments |
|
|
170
|
+
| Storage | `lowdb` (`config.json`) for buyers/suppliers/connections/product-lists/profiles · append-only JSONL per session for logs · separate files for attachments |
|
|
171
171
|
|
|
172
172
|
```
|
|
173
173
|
src/
|
|
@@ -178,15 +178,51 @@ src/
|
|
|
178
178
|
|
|
179
179
|
### Data model
|
|
180
180
|
|
|
181
|
-
The config is normalized into
|
|
181
|
+
The config is normalized into five entities:
|
|
182
182
|
|
|
183
|
-
- **Buyer** — a reusable party holding its own cXML identity (the `From` credential)
|
|
184
|
-
- **Supplier** — a reusable party holding its cXML identity (`To`) plus its **endpoints** (PunchOut URL, Order URL) and
|
|
185
|
-
- **Connection** — the edge pairing one Buyer with one Supplier. It holds only what is specific to that pair: which side the tool simulates (`mode`), the `sharedSecret`, an optional per-pair Sender identity override (defaults to the buyer's identity), `
|
|
183
|
+
- **Buyer** — a reusable party holding its own cXML identity (the `From` credential), an optional **platform profile** reference (see below), and optional default **ShipTo / BillTo addresses** and an end-user **Contact** (see below).
|
|
184
|
+
- **Supplier** — a reusable party holding its cXML identity (`To`) plus its **endpoints** (PunchOut URL, Order URL) and the **product lists** it serves as its Mode-B catalog. Endpoints are intrinsic to the supplier — defined once, not per relationship. An optional `allowMixedCurrency` flag relaxes the multi-currency check for this supplier (see below).
|
|
185
|
+
- **Connection** — the edge pairing one Buyer with one Supplier. It holds only what is specific to that pair: which side the tool simulates (`mode`), the `sharedSecret`, an optional per-pair Sender identity override (defaults to the buyer's identity), `deploymentMode`, and `attachmentEncoding`.
|
|
186
|
+
- **Product List** — a reusable, named set of catalog products. Assigned to one or more Suppliers; each supplier serves the **union** of its lists as its mock catalog. See below.
|
|
186
187
|
- **Profile** — a reusable **procurement-platform profile** (Ariba/Coupa/Jaggaer/…) referenced by a Buyer. See below.
|
|
187
188
|
|
|
188
189
|
At send time: `From` = buyer identity, `To` = supplier identity, `Sender` = the connection's override (or the buyer), and the request targets the supplier's endpoints. The mock-supplier endpoints are keyed by supplier id (`/sim/<supplierId>/…`).
|
|
189
190
|
|
|
191
|
+
### Product lists (Mode-B catalogs)
|
|
192
|
+
|
|
193
|
+
A **Product List** is a named set of catalog items, edited on its own and assigned to one or
|
|
194
|
+
more Suppliers from the **Products** tab. In Mode B a supplier serves the union of its assigned
|
|
195
|
+
lists; a supplier with no lists falls back to a small built-in demo catalog. A built-in
|
|
196
|
+
**Sample assortment** (~20 office/industrial items) ships out of the box and can be **loaded
|
|
197
|
+
into the editor** as a starting point. You can also **import a CSV** (a header row, any column
|
|
198
|
+
order; `SupplierPartID` required) to bulk-load a real catalog — a template is downloadable from
|
|
199
|
+
the editor. Recognized columns: `SupplierPartID`, `SupplierPartAuxiliaryID`, `Description`,
|
|
200
|
+
`UnitPrice`, `Currency`, `UoM`, `UNSPSC` (or a `Classifications` column as
|
|
201
|
+
`UNSPSC:31161500;eCl@ss:27-06`), `ManufacturerPartID`, `ManufacturerName`, `AllowFractional`.
|
|
202
|
+
|
|
203
|
+
Each product carries a `SupplierPartID`, an optional `SupplierPartAuxiliaryID`, description, unit
|
|
204
|
+
price + currency, unit of measure, manufacturer info, and **one or more `Classification`** entries
|
|
205
|
+
(each with its own `domain`, e.g. `UNSPSC` plus a supplier scheme like `eCl@ss`). A product may opt
|
|
206
|
+
into **fractional order quantities** (e.g. `1.5` m of cable) via its `allowFractional` flag — the
|
|
207
|
+
Mode-B catalog then accepts decimals for that item; all other items stay whole-number. These fields
|
|
208
|
+
flow through to the punchback (`ItemIn`) and the resulting OrderRequest (`ItemOut`).
|
|
209
|
+
|
|
210
|
+
**Currency.** A cXML `Total` is a single `Money`, so a document is expected to be single-currency.
|
|
211
|
+
If a cart/order spans more than one currency the mock supplier emits `Total` `0` (rather than a
|
|
212
|
+
meaningless cross-currency sum) and validation raises a `mixed-currency` **error**. A supplier that
|
|
213
|
+
genuinely handles multi-currency orders can set **`allowMixedCurrency`**, which downgrades that to a
|
|
214
|
+
non-blocking **warning** (the per-line `Money` currencies are always preserved either way).
|
|
215
|
+
|
|
216
|
+
### Addresses & contact
|
|
217
|
+
|
|
218
|
+
A **Buyer** holds default **ShipTo** / **BillTo** addresses and an end-user **Contact** (name, email,
|
|
219
|
+
phone). They pre-fill the OrderRequest (which stays fully editable as cXML before sending) and, when the
|
|
220
|
+
buyer's profile enables it, are also carried in the **PunchOutSetupRequest** (Ariba-style). Each address
|
|
221
|
+
supports a postal block and/or an `addressID` (+ `addressIDDomain`) reference; the **profile's
|
|
222
|
+
`addressMode`** decides which is emitted (`full` / `id-only` / `both`) — matching how platforms differ
|
|
223
|
+
(Jaggaer/Workday send full postal, SAP is plant-code/`addressID`-centric, Ariba sends both and includes
|
|
224
|
+
ShipTo in setup). An emitted `ShipTo`/`BillTo` with neither an `addressID` nor a Street/City is flagged.
|
|
225
|
+
|
|
190
226
|
### Simulating different procurement platforms (Buyer profiles)
|
|
191
227
|
|
|
192
228
|
Real procurement systems emit cXML differently. A **Profile** captures a platform's
|
|
@@ -201,6 +237,8 @@ Ariba, Coupa, Jaggaer, Oracle, SAP, or Workday:
|
|
|
201
237
|
| `attachmentEncoding` | Default `Content-Transfer-Encoding` for OrderRequest attachments (`binary`/`base64`). |
|
|
202
238
|
| `cartReturnTransport` | How the punchback is returned in Mode B: `cxml-urlencoded`, `cxml-base64`, or `raw`. |
|
|
203
239
|
| `extrinsics` | `<Extrinsic>` templates injected into the setup/order documents (values may use `${buyerCookie}` / `${orderId}`). |
|
|
240
|
+
| `addressMode` | How `ShipTo`/`BillTo`/`Contact` are emitted: `full` (PostalAddress), `id-only` (just `addressID`), or `both`. |
|
|
241
|
+
| `shipToInSetup` / `contactInSetup` | Carry the buyer's `ShipTo` / `Contact` already in the **PunchOutSetupRequest** (Ariba-style), so the supplier can price/personalize per ship-to. |
|
|
204
242
|
|
|
205
243
|
Built-in presets (Ariba, Coupa, Jaggaer, Oracle, SAP, Workday, Generic) ship out of the box
|
|
206
244
|
and can be **loaded into the editor** as a starting point, then customized. A Profile holds
|
|
@@ -218,6 +256,7 @@ cxml-urlencoded) — i.e. the tool's original behavior.
|
|
|
218
256
|
|
|
219
257
|
- `*/api/buyers`, `*/api/suppliers` — CRUD for the reusable parties
|
|
220
258
|
- `*/api/profiles` — CRUD for procurement-platform profiles · `GET /api/profile-presets` — the built-in preset library
|
|
259
|
+
- `*/api/product-lists` — CRUD for product lists · `GET /api/product-list-presets` — the built-in sample library
|
|
221
260
|
- `*/api/connections` — CRUD for connection edges (reference a buyer + supplier)
|
|
222
261
|
- `GET /api/connections/:id/setup/preview` · `POST …/setup` — preview / send the SetupRequest
|
|
223
262
|
- `POST /api/connections/:id/order/preview` · `POST …/order` — preview / send the OrderRequest (multipart if attachments)
|