For SAP implementation partners
One number per package.
Fully traced to your SAP.
PackCost AI is a read-only layer over SAP that turns BOM, vendor, price and transactional data into a deterministic cost for every empty bottle or package — and shows the exact path it took through the ERP to get there.
Every figure is reproducible from stored inputs, business rules, source references and timestamps. Nothing is estimated. Where landed-cost or conversion data is missing, the result is marked partial and the gap is listed — never filled with a zero.
Architecture
Four layers. The ERP sits behind one interface.
The separation is what lets the same product serve S/4HANA, ECC and non-SAP ERPs without touching the costing engine or the user experience.
Where your team plugs in
Implement one interface. Nothing above it changes.
The mock connector implements every operation today, against a deterministic seed. On a REST/OData ERP your work is the mapping pack — the connector itself, the canonical model, the cost engine, the API and the web UI are all shared and untouched.
The connector interface ERPConnector
- resolve_part
- get_fx_rates
- get_plants
- get_purchase_history
- get_material
- get_receipts
- get_bom
- get_invoices
- get_vendors
- get_landed_costs
- get_vendor_materials
- get_production_orders
- get_prices
- get_consumption
- get_qualifications
- get_conversion_cost
Each returns canonical DTOs plus source metadata — never raw SAP objects.
The mapping pack config/{sap,rest}/<customer>.yaml
# connection picks the dialect; bindings map the fields connection: route: rest dialect: odata_v2 get_bom: object: API_BILL_OF_MATERIAL_SRV/MaterialBOM status: partial field_map: version: BillOfMaterialVariantUsage valid_from: BOMHeaderValidityStartDate # TODO: component scrap % field
Your deliverable: turn
python -m packcost.connectors.sap check green.
One connector, many ERPs
Config picks the dialect. The interface never changes.
The live connector is config-driven. A dialect handles how one family of HTTP + JSON ERPs shapes a query — the URL, where the filter goes, the response envelope, pagination — and the customer’s YAML mapping pack does the field-by-field mapping. SAP S/4HANA is one dialect among several; adding Dynamics or Oracle is configuration, not new connector code.
SAP S/4HANA odata_v2
Released OData APIs & CDS views; Integration Suite. Material Ledger for actual cost where activated.
- API_BILL_OF_MATERIAL_SRV
- API_PRODUCT_SRV
- API_PURCHASINGINFORECORD_PROCESS_SRV
- API_SUPPLIERINVOICE_PROCESS_SRV
- API_EXCHANGE_RATE_SRV
Oracle NetSuite suiteql
One joined SELECT per operation against the whole data model — the concept, not the tables. Flat component rows are grouped back into BOM headers.
- bomassignment → bomrevision
- bomrevisioncomponent
- item / itemvendor
- vendor / currencyrate
- transaction / transactionline
SAP ECC 6.0 rfc / bapi
A separate RFC / BAPI adapter behind the same interface (needs the NW RFC SDK). Actual cost reconstructed from PO / GR / IR / freight history.
- CS_BOM_EXPL_MAT_V2
- BAPI_MATERIAL_GET_DETAIL
- EINA / EINE / KONP / A017
- RBKP / RSEG
- TCURR
-- NetSuite get_bom: "BOM components with quantities and scrap" as one query SELECT br.name, brc.item, brc.quantity, (100 - COALESCE(brc.componentyield, 100)) AS scrap_pct FROM bomassignment ba JOIN bomrevision br ON br.billofmaterials = ba.billofmaterials JOIN bomrevisioncomponent brc ON brc.bomrevision = br.id WHERE ba.item = … AND ba.location = …
No API in the POC? file / staging_db
Same interface, same mapping pack — rows come from CSV / Parquet / JSON extracts in a directory, or a read-only staging schema the customer replicates a few tables into. Unblocks the engagement while API access is still in approvals; the extract can be swapped for a live dialect later with no change above the connector.
Shipped feature
Every figure shows its retrieval path.
For any BOM or cost, PackCost renders the exact sequence of ERP reads — object, filter, fields, rows returned. On SAP the steps name the real objects, so a client’s auditors can point at where each number came from.
- Retrieve the BOM version(s) for the package & plant, valid on the date. SAP API_BILL_OF_MATERIAL_SRV/MaterialBOM $filter=Material eq 'BOT-500' and Plant eq 'LKO' → selected B2 (valid 2025-07-01…)
- For each component — the purchasing price valid on the date, per supplier. SAP API_PURCHASINGINFORECORD_PROCESS_SRV/A_PurInfoRecdPrcgCndn material='PRE-22' → V-PRE-B 1.40 INR
- Foreign-currency component → the exchange rate to the reporting currency. SAP API_EXCHANGE_RATE_SRV/A_ExchangeRate USD→INR → 83.00
Status
Everything above the connector is built and tested.
- Canonical schema — 28 ERP-neutral tables, migrated
- Deterministic cost engine & calculation evidence
- Snapshot cache + cost history / trend
- Vendor comparison on total applicable cost
- Scenario engine — vendor switch, price, weight, freight, FX
- Natural-language query — 20 canonical questions
- Web UI — ask box, cost explorer, retrieval path
- Config-driven connector — 5 REST/OData dialects + offline file / staging-DB route
- S/4HANA, Dynamics 365, NetSuite, Oracle Fusion & file drop — verified end to end
The engagement
What a partner delivers.
- Confirm the environment — ERP profile and release, the approved integration route and dialect, and a read-only least-privilege service account.
- Complete the mapping pack — with the customer’s ERP team, fill the field
maps for each operation until
python -m packcost.connectors.sap checkreports the cost path ready. - Wire it up and reconcile — for a REST/OData ERP, select the dialect and
resolve secrets through the secret manager; for ECC, complete the RFC client behind
EccRfcConnector. Then reconcile PackCost’s output against an existing ERP cost report.