Syncing Receiving (Assembly) to Other Receipts: A Single-Strategy Deep Dive into Cross-System Inventory Documents
What This Strategy Solves
A retail client runs a cross-border WMS that generates a steady stream of assembly-receiving documents every day. These documents must land in the financial ERP as "Other Receipts" to drive on-book inventory, costing, and reporting. It looks like "write one document in two places," but mismatched codes, missing organization mapping, or wrong stock direction will freeze month-end reconciliation cold. This strategy's job is to deliver assembly receiving documents into the ERP in a stable, traceable way.
Data Flow and Field Mapping
The overall flow is: Cross-border WMS (source) → Qeasy Integration Platform (middle layer) → Financial ERP (target). The middle layer handles cleansing, mapping, ID linkage, and replay; the source and target never talk directly.
Key field mapping (only the error-prone essentials):
| Business meaning | Source field | Target field | Note |
|---|---|---|---|
| Receiving number | receiving_code | FBillNo | Keep the source number for easier reconciliation |
| Document type | (derived) | FBillTypeID | Fixed value QTRKD06_SYS, assembly-specific |
| Inventory org | warehouse_id | FStockOrgId | Must be looked up via warehouse archive, never raw ID |
| Stock direction | (derived) | FStockDirect | Assembly receiving is typically 0, set by strategy |
| Receiving date | complete_time | FDate | Strongly prefer completion time over creation time |
Note the target FStockOrgId value: _findCollection find warehouseCode from <archive_id> where warehouseId={{warehouse_id}}. This is Qeasy's typical "cross-strategy archive lookup" usage.
Configuring on Qeasy
Configuration has three blocks: source fetch, transformation, target write.
Source side: API getReceiving, POST query, primary key receiving_id, business number receiving_code. Enable idCheck so the platform dedupes by primary key. Common filters include receiving number, customer reference, tracking number, PO number, and warehouse ID. For initial onboarding, lock one document by receiving_code first.
Middle transformation: This is the most overlooked yet most valuable stage. Centralize the following rules:
- Code mapping: warehouses, customers, SKUs, and items live in dedicated archive strategies; business strategies only read, never write. This is the "centralized code mapping" pattern we see across Qeasy customers — change once, propagate everywhere.
- Header and body in phases: stabilize the header first (number, type, org, date, supplier), then add the body (lines, batches, quantities). If something breaks on go-live, at least no dirty data hits the ERP.
- Idempotency and write-back: use
receiving_codeas the idempotency key, write back status after the target saves, and reruns will not create duplicates.
Target side: API batchSave, POST execute. Document type is pinned to QTRKD06_SYS for the assembly scenario; stock direction, inventory org, and date follow the mapping table above.
Implementation Steps
Go live in a "stable first, fast later" rhythm with three phases:
- Historical full backfill. Pause the schedule, manually trigger a full sync covering the past N days of completed assembly receiving. Verify the target documents look clean and the inventory org is correct. The manual-trigger button on Qeasy handles this; no extra script needed.
- Set the incremental anchor. Use the moment the full sync finishes as the anchor; record the largest
complete_time. All subsequent increments start there. - Turn on the schedule. The source crontab is
49 3 * * *(fetch early morning), the target is23 2 * * *(execute early morning) — staggered to avoid collision. This "incremental + full dual-track" rhythm has become standard in Qeasy customer projects: incremental runs daily, full sync is one click away when something goes wrong.
Lessons from the Trenches
- Using warehouse ID directly as inventory org ID. Classic mistake: skipping the archive lookup. Result: stock direction correct, organization wrong, every document needs to be reversed. The safe move is
_findCollectionagainst the archive — never shortcut it. - Using creation time as the receiving date. WMS creation time and completion time can differ by days; using the wrong one skews the inventory ledger. Insist on
complete_time. - Going live with header and body together. When header and lines push in the same run, root-causing a failure is brutally expensive. Push header first, body second — a "header/body phased" pattern we have validated repeatedly on Qeasy projects.
- Ignoring idempotency. Receiving volumes are large; a network blip can trigger a resend, and
batchSavewithout an idempotency key produces duplicates.receiving_codemust serve as the unique key. - Cross-timezone date strings. If the source time string carries a timezone or is truncated, the ERP rejects it or shifts it. Format it explicitly in the middle layer; never forward raw strings.
When This Applies — and When It Doesn't
Applies: cross-border WMS → financial ERP flows for assembly, adjustment, and initialization "other receipts," where data volume is steady and reconciliation matters. Doesn't apply: hard real-time stock queries (sub-second), multi-org networks that switch organizations frequently, or scenarios needing high-frequency reverse adjustments — those are better served by event streams or a dedicated inventory service.