One-to-One Sync from Jushuitan Sale-Out Orders to Chanjet T+ Sale Delivery
What this strategy solves
Retail merchants often run their online stores on Jushuitan while keeping finance and inventory on Chanjet T+. Every confirmed sale-out order must land as a T+ sale delivery voucher so reconciliation, stock accounting and invoicing can proceed. In one customer engagement we incrementally pulled sale-out orders for a specific retail shop and wrote them one-to-one into T+ — no merging — so each voucher stays traceable back to its source order.
Data flow and field mapping
Flow: Jushuitan Qimen → Qeasy Data Integration Platform → Chanjet T+.
The platform's data hub does two jobs in the middle: it persists the source payload, and it powers the _findCollection lookup that resolves shop_name → short_name before writing the T+ voucher.
Key field mapping (header)
| Target field (T+) | Source / rule | Mapping type | Notes |
|---|---|---|---|
| Code | io_id | DIRECT | Voucher code, taken from the out-order number |
| VoucherDate | io_date_new | DIRECT | Voucher date; falls back to io_date if empty |
| ExternalCode | io_id + "+1" | TRANSFORM | External code; concatenation guarantees uniqueness |
| BusinessType | 15 | CONSTANT | Fixed retail business type |
| Customer | _findCollection find short_name ... where shop_name={{shop_name}} | COLLECTION | Cross-strategy lookup of customer short name |
| Memo | remark | DIRECT | Seller remark |
| InvoiceType | 02 | CONSTANT | Fixed invoice type |
| Warehouse | 1 | CONSTANT | Default warehouse |
| IsAutoGenerateSaleOut | false | CONSTANT | Do not auto-generate sale-out |
| SaleDeliveryDetails | items | DIRECT | Line array; sub-mapping required per T+ spec |
The source request itself carries two filters: status=Confirmed (only out-confirmed orders) and shop_id=16288585 (only the retail shop), which keeps the pipeline free of irrelevant records.
How to configure on Qeasy
- Source QUERY node: pick
jushuitan.saleout.list.query, POST. Use{{LAST_SYNC_TIME|datetime}}forstart_time,{{CURRENT_TIME|datetime}}forend_time,date_type=2(out time), and pinshop_idto the retail shop. - Target EXECUTE node: pick
/tplus/api/v2/saleDelivery/Create, POST,dataKey=dto. - Field mapping: configure per the table above.
Customeruses_findCollectionagainst the Jushuitan Shop Query strategy, keyed byshop_name, returningshort_name. - Line mapping:
SaleDeliveryDetailstakesitemsdirectly. Drill into the sub-structure and map inventory code, quantity, unit price, etc. per T+'s detail spec. - Write mode: enable "do-not-merge write" so each source order produces exactly one target voucher.
- Dependencies and scheduling: the Shop Query strategy must run first. Schedule the source at 03:49 daily and the target at 04:23 daily to leave a buffer.
Implementation steps
- Incremental start point: on first go-live, rewind
start_timeto a fixed date (e.g., the day before cutover) to backfill the confirmed orders, then switch to{{LAST_SYNC_TIME}}and roll forward daily. - Run dependencies first: the Shop Query strategy must complete before this one; otherwise
_findCollectionfinds noshort_nameand the customer field ends up blank. - Frequency: once per day. Chain source (03:49) → target (04:23) so the shop data is ready.
- ExternalCode dedup: concatenating
io_id + "+1"keeps the code unique and avoids clashing with T+ internal codes. - Monitoring and retries: Qeasy uses
io_idas the idempotency key; failed vouchers can be retried by ExternalCode without double-posting.
Pitfalls and lessons
- The window between
start_timeandend_timemust not exceed 7 days. Jushuitan's API caps the range. The safe approach is to keep the window to one day and let the scheduler advance it. - Don't blindly fall back to
io_datewhenio_date_newis empty. Detect the empty case first and only then apply the conversion, or the voucher date will drift. +1is string concatenation, not addition. Verify the platform treats it as text; otherwise the ExternalCode loses characters and T+ rejects the payload.- Don't reverse the dependency order. If Shop Query hasn't finished,
_findCollectionreturns null and the customer field goes blank, failing the batch. Put the dependency on the schedule chain so Qeasy triggers them in order. - Don't confuse
ConfirmedwithCancelled. Cancelled orders also carryio_idand will either post as negatives or be rejected. Filter them at the source.
When to use and when not to
Use when: one shop per retail customer, moderate order volume, strict 1:1 traceability, and reconciliation requires vouchers to mirror source orders one-to-one. Don't use when: multiple out-orders must be merged into one invoice, aggregation by customer/day is required, or the business needs warehouse splits or other T+ voucher types — those call for a separate aggregation strategy.