← All manuals IM2

Background Job — QuickBooks Item Master Refresh

(background process — no screen)
Technical Spec Ver 1 Updated 2026-09-06 Matches the live screen

Background Job — QuickBooks Item Master Refresh

Mirrors QuickBooks-owned item fields into the IM2 items table. QuickBooks is the book of record; this job never writes QuickBooks.

Code: skills/im2_app/scripts/qb_refresh.py (runs in the Viktor sandbox, not on the droplet — it uses the Viktor QuickBooks connector sdk.tools.mcp_quickbooks.quickbooks_run_custom_query).

Trigger / schedule

Inputs

Tables written (all in im2)

TableWhat is written
itemsUpsert on sku of the QB-owned fields: qb_item_id, item_name, description_po, description_so, qty_on_hand, purchase_cost, qb_active, expense_gl, income_gl, primary_vendor, plus qb_last_updated = now(). New SKUs are inserted with blank warehouse fields (they land on the "needs a bin" queue).
items (status)qb_status flipped to 'in_qb' for rows found in either pull (adoption of items created in IM2); archived_at = now() where qb_active = false AND qb_status='in_qb' AND archived_at IS NULL; archived_at = NULL (un-archive) only for SKUs present in tonight's active pull.
sync_runsOne row per applied run: finished_at, items_read, items_created, items_archived, exceptions, and a JSON detail with the first 50 new SKUs, first 50 orphans (in IM2, not in QB), duplicate QB SKUs and the count of QB items with no SKU.

Inactive QB items never create IM2 rows — they only update/archive rows IM2 already has.

External calls

QuickBooks Online (via the Viktor QB connector) — read only, two paged queries. Full read takes ~4 minutes; run long invocations under nohup with a log file.

Failure behaviour / idempotency

Logs to look at

Known limits / gaps