Practical Guide to the Query Transfer Order Strategy: From Source System Pull to Qeasy Scheduling
What This Strategy Solves
In a multi-warehouse transfer scenario for a retail enterprise, transfer orders between stores, and between stores and the central warehouse, need to be visible to downstream finance and supply chain systems as soon as they land in the source system (Hupun/Wanliniu). Relying on manual export and import is not only slow, but the order statuses often drift out of sync.
The "Query Transfer Order" strategy we are dissecting has a clear purpose: pull transfer orders from the source system within a time window, serving as the entry point of the entire transfer synchronization chain. It does not write directly to the target system. Instead, it pushes data into the staging layer of the Qeasy data integration platform, where subsequent strategies take over.
In other words, this strategy addresses the question of "where do transfer orders come from, and at what cadence are they fetched?"
Data Flow and Field Mapping
The entire chain is a unidirectional pull: Hupun → Qeasy staging layer (awaiting downstream strategy consumption).
The source system is called via the POST endpoint /erp/allocation/changebill/query, with pagination parameter page starting from 1 and limit capped at 200. The key filter fields are:
| Field | Meaning | Required | Value Note |
|---|---|---|---|
| bill_code | Order Code | No | Used for precise order filtering; left empty in this strategy |
| create_time | Creation Start Time | No | Uses variable {{LAST_SYNC_TIME}} |
| create_end_time | Creation End Time | No | Uses variable {{CURRENT_TIME}} |
| page | Current Page | Yes | Starts from 1 |
| limit | Page Size | Yes | Recommended 200 |
| bill_status | Order Status | No | Filter as needed |
The staging target on the Qeasy side is a "Write No-Op" execution node (type=WebAPI, effect=EXECUTE). It does not write to any business system itself; it merely persists the paginated data for downstream strategies to consume. This "source → staging" separation is a common pattern among Qeasy customers: decoupling pull from write to prevent either end's instability from impacting the whole chain.
At the field level, the source-side bill_code serves as both the "order number" and the "unique ID". This is especially critical for idempotency checks downstream.
How to Configure in Qeasy
There are several switches in the strategy metadata that need immediate attention:
- idCheck = true: Enables idempotency check, using
bill_codeas the deduplication key. Repeated pulls within the same window will not produce duplicate orders. - buildModel = false: Does not auto-build the target model based on this response, meaning field mapping must be maintained manually rather than auto-inferred by the platform.
- autoFillResponse = false: Response fields are not back-filled into the source request template, ensuring the query conditions for each pull remain clean.
- Both
numberandidpoint tobill_code: The order number and the unique ID share the same field, which can be used directly as the join key in downstream strategies.
In the request body, create_time uses {{LAST_SYNC_TIME|datetime}} and create_end_time uses {{CURRENT_TIME|datetime}}. This is a typical "sliding window" pattern in Qeasy, where the platform automatically fills in the last successful sync timestamp before each scheduled run.
Implementation Steps
We recommend a three-step approach, which is also the common rhythm Qeasy customers follow when implementing such query strategies:
Step 1: Confirm the incremental starting point. Find a historical transfer order in the source system and record its creation time as the initial value for LAST_SYNC_TIME. Qeasy supports manually backfilling a historical timestamp once to backfill past data before switching to normal operation.
Step 2: Trigger a one-time full backfill. Temporarily change the crontab to a one-time run (e.g., manual trigger), and observe whether pagination completes properly and whether there are timeouts or errors. This step only checks "can it run through"; the data volume is not the focus.
Step 3: Switch to daily scheduling. The strategy's crontab is */5 8-23 * * *, meaning it runs every 5 minutes from 8 AM to 11 PM daily. This frequency covers the transfer rhythm during store operating hours. Nighttime runs are paused because the source system performs settlement during the early hours, when the API is least stable.
For scheduling strategy, we use the "dual-track of incremental and full" approach: daily sliding-window pulls for increments, and a separate retrospective pull for issue recovery or data backfill. The two tracks do not interfere with each other.
Pitfall Retrospective
1. Don't just look at the "last 3 months" window. The source-side API explicitly states for the create_time field: "Can only query the last 3 months." In an actual project, a colleague mistakenly filled LAST_SYNC_TIME with a value from one year ago, causing the API to error and the schedule to fail repeatedly. The safe approach is: add a pre-check in Qeasy that automatically truncates and raises an alert if the window exceeds 90 days.
2. Always cap pagination at 200. The maximum limit is 200. If exceeded, the source side truncates and silently drops data without throwing an error. We encountered a case on the customer site where "it looked finished, but one page was actually missing" — it took half a day to realize the pagination parameter had been reduced.
3. Don't disable idCheck. This strategy's idCheck defaults to true, with idempotency backed by bill_code. Once manually disabled, the same transfer order may be pulled twice due to pagination boundaries, causing duplicate rows in downstream writes — extremely painful to troubleshoot.
4. "Write No-Op" is not a misconfiguration. Seeing api field labeled "Write No-Op", novice engineers often assume the configuration is incomplete. In fact, this is an intentional design: the query strategy is only responsible for pulling, and actual target system writes are handled by downstream strategies. The pitfall here is the temptation to "configure the target system all at once", which breaks the clean boundaries of the chain.
Applicable and Non-Applicable Scenarios
Applicable: The source system has a clear time-window paginated query API; the downstream needs incremental sync based on order status or time range; the overall chain requires decoupling of pull and write for inventory transfer scenarios.
Not applicable: Scenarios where the source does not support time-window filtering and requires full re-pull to obtain data; and scenarios where order write requires strong real-time performance (second-level) and is not suitable for 5-minute scheduling.