Purchase Requisition Sync in Practice: A Field-Level Passthrough from WMS to SQL Server Staging Tables
What This Strategy Solves (Scenario and Value)
The purchase requisition is one of the source documents in a supply chain. In one real project, a retailer used the WMS flagship edition as the procurement entry point, and all internal BI plus custom ERP modules relied on SQL Server staging tables for joins and aggregations. The pain points were obvious: scattered API calls, inconsistent field naming, and line items that often lost their link back to the header. We used the Qeasy Data Integration Platform to take over this link, pushing WMS purchase requisitions to two SQL Server staging tables every five minutes on an incremental basis, so downstream consumers could just read from the tables instead of each calling the API independently.
Data Flow and Field Mapping
The flow is one-way: WMS Flagship Edition → SQL Server. The source side is a QUERY-type API, purchase.PurchaseApply.search. The target side is an EXECUTE-type insert that writes the header and line tables in a 1:1 fashion.
Key field mapping for the header table (t_mid_purchase_apply):
| Source Field | Target Field | Mapping Type | Notes |
|---|---|---|---|
| purchase_apply_no | purchase_apply_no | DIRECT passthrough | Primary key, unique document ID |
| warehouse_name / warehouse_no | warehouse_name / warehouse_no | DIRECT passthrough | Warehouse name / code |
| created / modified | created / modified | DIRECT passthrough | Created / modified time |
| remark | remark | DIRECT passthrough | Remark |
| expected_time | expected_time | DIRECT passthrough | Expected arrival time |
| apply_name | apply_name | DIRECT passthrough | Applicant |
| status | status | DIRECT passthrough | Status enum: 5 cancelled / 10 editing / 20 pending confirm / 23 pending reference / 25 partially referenced / 30 fully referenced |
Key field mapping for the line table (t_mid_purchase_applyEntry):
| Source Field | Target Field | Mapping Type | Notes |
|---|---|---|---|
| detail_list.rec_id | rec_id | DIRECT passthrough | Line unique identifier |
| detail_list.spec_no / goods_no / goods_name | spec_no / goods_no / goods_name | DIRECT passthrough | SKU / product dimensions |
| detail_list.spec_name / brand_name | spec_name / brand_name | DIRECT passthrough | Spec / brand |
| detail_list.remark | remark2 | DIRECT passthrough | Only the column name differs, semantics are the same |
| detail_list.num / ref_num / stockin_num | num / ref_num / stockin_num | DIRECT passthrough | Applied / referenced / received quantities |
The header purchase_apply_no is propagated to the line table as the header-line foreign key. Aggregated fields on the source header such as num, ref_num, and provider_no are intentionally not written to the target header — that is a deliberate design boundary.
How to Configure It on Qeasy
On the Qeasy Data Integration Platform, this strategy is intentionally lightweight:
- Source platform: Connect to the WMS Flagship Edition, pick the
purchase.PurchaseApply.searchAPI. Use{{DAYS_AGO_3|datetime}}asstart_time, defaultend_timeto2025-12-31 23:59:59,page_size=100, and let the paginator drivepage_no. - Target platform: Connect to SQL Server. The main statement is
insert into t_mid_purchase_apply(...), the 1:1 extension statement isinsert into t_mid_purchase_applyEntry(...), andextend_params_1is set todetail_list. - Field mapping: All DIRECT. Just drag fields to their targets. The only naming caveat is
remark → remark2. - Scheduling: Source uses
*/5 * * * *, target uses2-59/5 * * * *. The two-minute offset avoids read/write contention — a common "staggered scheduling" pattern among Qeasy customers. - No encoding mapping: Because this lands into staging tables rather than a business system, there is no need for shop/customer/material crosswalk tables.
- No scripts: No
_findCollection, no_mongoQuery, no custom functions. Everything relies on field passthrough plus header-line linkage.
Implementation Steps
We usually break the rollout into four phases:
- Schema and permissions: Create
t_mid_purchase_applyandt_mid_purchase_applyEntryin SQL Server first. The header primary key ispurchase_apply_no; the line primary key is the composite(purchase_apply_no, rec_id). Build an index onpurchase_apply_no+created. - Incremental anchor configuration: Use
DAYS_AGO_3forstart_timeinstead of a fixed historical date, to avoid a one-off backfill of ancient data. Pointend_timeto a far-future timestamp so the platform naturally converges on the current time. - One-shot full trigger: At first go-live, temporarily set
end_timeto the day before cutover and run a deliberate full backfill. Verify that the line-to-header ratio and the line count match the sourcedetail_listlength, then switch back to the regular schedule. - Frequency and monitoring: Pull from the source every five minutes, write to the target offset by two minutes. In Qeasy, attach alerts to three metrics: source-side pulled rows, target-side written rows, and the line-per-header ratio. Investigate immediately if any of them goes abnormal.
Lessons Learned
- Line rows are easy to lose:
extend_params_1must bedetail_list, and the:purchase_apply_nobind in the 1:1 extension statement must come from the header. If you treat the line as a plain array and forget the foreign key, you will end up with "orphan lines". - The
remarkname collision: Both the header and the lines have aremarkon the source side. To disambiguate, the target side renames the line column toremark2. During mapping, double-check whether you are wiring the headerremarkor the lineremark. A typical mistake is to skip it or wire it twice. - Do not translate status codes in the staging table:
statusis an integer enum on the source side (5/10/20/23/25/30). The safe approach is to store it as-is and let the consumer layer translate it to a label via CASE. Translating it early loses semantics and makes future downstream integrations painful. - Do not hard-code time windows: Writing
end_timeas2025-12-31looks harmless, but in 2026 the pipeline will silently stop pulling. Using a variable or a far-future timestamp lets the platform converge naturally on the current time — a small but critical piece of any incremental-plus-full dual-track strategy. - Staggered scheduling is not decoration: When both source and target use
*/5 * * * *, you get contention where a new header round arrives just as the previous header is still being written. Setting the target to2-59/5 * * * *gives the source a window to breathe and noticeably improves chain stability.
When This Applies and When It Does Not
Applies: WMS is the procurement entry point, and downstream BI, reporting, or in-house systems need stable, traceable purchase requisition data with no semantic rework.
Does not apply: scenarios where WMS purchase requisitions must be converted directly into ERP purchase orders — state machines, approval flows, and document conversion rules belong in a separate strategy. It also does not apply when SKU or vendor cross-system encoding mapping is required; the staging tables should not carry that burden.