Audience: engineers and power users who want to know how an emailed invoice becomes a posted NetSuite Vendor Bill — the “magic” explained.
An invoice flows through a chain of small, independently-testable stages:
Email → Triage (classify) → Draft + vendor resolve → OCR (Textract) → Structure (Claude) → PO match → Item match → Vendor coding → Project coding → Validate → Review → Post (SuiteTalk)
Every stage writes its result onto one VendorBillDraft.draft JSON blob (header + lines + totals), so any stage is inspectable and re-runnable.
Gmail::PollInboxJob).EmailTriage::Classifier, forced tool use) into invoice / spam / other with a confidence + recommended action → stored as a TriageDecision.SHADOW_MODE defaults on).NetsuiteBills::DraftInitiator:
NsVendor mirror, biased toward high-bill-count vendors so a junk/duplicate record doesn't out-score the real one.VendorBillDraft (ocr_running) → enqueues OCR.NetsuiteBills::OcrJob runs Textract (async start-then-poll), storing raw text + tables + blocks in BillOcrResult. Status → ocr_done → structuring.
NetsuiteBills::BillStructurer is the heart:
record_vendor_bill) whose schema is the code-owned contract.