Order Processing Workflow
Complete workflow from document receipt to ERP submission, showing all intake paths, the shared validation pipeline, and every feature-flag decision point.
Workflow Diagram
Section titled βWorkflow Diagramβflowchart TD %% ββ Styles ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ classDef active fill:#d4edda,stroke:#28a745,color:#000 classDef inactive fill:#fff,stroke:#dc3545,color:#999,stroke-dasharray:5 5 classDef flag fill:#fff3cd,stroke:#ffc107,color:#000 classDef process fill:#e2e3e5,stroke:#6c757d,color:#000 classDef convergence fill:#cce5ff,stroke:#007bff,color:#000
%% ββ Email Intake Paths ββββββββββββββββββββββββββββββββββββββββββββββββββ subgraph EMAIL["Email Intake"] E2["Cloudflare Email Worker\n(POST /api/webhook/inbound-email)"]:::active E3["Gmail Poll\n(ScheduledEmailPullDispatcher)"]:::active end
%% Cloudflare path E2 -->|"HMAC verify β insert emailEvent\nβ link pdfDocuments"| CF_EXTRACT CF_EXTRACT["Start PDFExtractionWorkflow\nper attachment"]:::active
%% Per-connection poll path E3 -->|"poll_gmail_for_connection β\nfan-out per message"| EPW
%% ββ Email Processing Workflow βββββββββββββββββββββββββββββββββββββββββββ EPW["EmailProcessingWorkflow\n(Temporal)"]:::active EPW -->|"1. fetch_gmail_message\n2. lookup_alias\n3. triage_email"| TRIAGE
TRIAGE{"Triage\nDecision"}:::process TRIAGE -->|"skip / rfq"| DONE_EMAIL["Email Complete\n(skipped or saved as RFQ)"]:::process TRIAGE -->|"order"| EMAIL_EXTRACT["4. extract_from_email\n5. match_customer\n6. batch_match_items\n7. save_email_order"]:::active
EMAIL_EXTRACT --> AV_CHILD
%% ββ PDF Upload Path βββββββββββββββββββββββββββββββββββββββββββββββββββββ subgraph UPLOAD["PDF / Document Upload"] U1["Manual Upload\n(POST /api/pdf-documents)"]:::active end
U1 -->|"Upload to R2 β insert pdfDocument\n+ workItem β startDocumentProcessing"| PDFWF
CF_EXTRACT --> PDFWF
%% ββ PDF Extraction Workflow βββββββββββββββββββββββββββββββββββββββββββββ PDFWF["PDFExtractionWorkflow\n(Temporal)"]:::active PDFWF -->|"0. pre_extract_document\n1. extract_text_with_gemini_multiformat\n2. match_customer\n3. batch_match_items\n3.5. enrich_order_with_inventory_routing\n3.6. resolve_org_discounts\n4. save_extracted_order"| AV_CHILD
%% ββ Convergence: Agentic Validation βββββββββββββββββββββββββββββββββββββ AV_CHILD["Start child:\nAgenticValidationWorkflow"]:::convergence
AV_CHILD --> FLAG_AV
FLAG_AV{{"agentic_validation_enabled\n(default: false)"}}:::flag FLAG_AV -->|"false"| AV_DISABLED["Persist 'disabled' status\nβ advance work_item\nto manual review"]:::active FLAG_AV -->|"true"| AV_RUN
AV_RUN["1. Fetch ERP capabilities\n2. LLM Validation (Gemini)\n3. persistAutoPricedMatches\n4. ERP item validity check\n5. Merge results & compute confidence"]:::active
AV_RUN --> FLAG_THRESHOLD
FLAG_THRESHOLD{{"agentic_confidence_threshold\n(default: 0.95)"}}:::flag FLAG_THRESHOLD -->|"confidence β₯ threshold\n& all_valid"| AUTO_SUBMIT_DECISION FLAG_THRESHOLD -->|"confidence < threshold\nor issues found"| ESCALATED["Escalated\nβ Manual Review Queue"]:::active
AUTO_SUBMIT_DECISION{{"agentic_auto_submit_enabled\n(default: false)\nAND\nerp_write_enabled\n(default: false)"}}:::flag AUTO_SUBMIT_DECISION -.->|"both true\n(INACTIVE)"| AUTO_SUBMIT["submit_order_to_erp\nβ auto_submitted"]:::inactive AUTO_SUBMIT_DECISION -->|"either false\n(current default)"| DRY_RUN["Dry Run\nβ log decision only"]:::active
%% ββ Manual Submit Path (Active) βββββββββββββββββββββββββββββββββββββββββ ESCALATED --> MANUAL_REVIEW AV_DISABLED --> MANUAL_REVIEW DRY_RUN --> MANUAL_REVIEW
MANUAL_REVIEW["Operator Reviews Order\nin Webapp UI"]:::active
MANUAL_REVIEW -->|"Generate Quote\n(POST /api/erp/orders/generate-quote)"| TEMPORAL_QUOTE MANUAL_REVIEW -->|"Submit Order\n(POST /api/erp/orders/[id]/submit)"| SUBMIT_ORDER
TEMPORAL_QUOTE["ERPQuoteGenerationWorkflow\n(Temporal, async 202)"]:::active
SUBMIT_ORDER["Manual Submit\n(POST /api/erp/orders/[id]/submit)"]:::active SUBMIT_ORDER --> TEMPORAL_SUBMIT["ERPOrderSubmissionWorkflow\n(Temporal, async 202)"]:::active
TEMPORAL_QUOTE --> ERP_DONE TEMPORAL_SUBMIT --> ERP_DONE
ERP_DONE["Order in ERP β"]:::active| Style | Meaning |
|---|---|
| Green solid border | Active path β currently in use with default flag values |
| Red dashed border | Inactive path β requires feature flags to be enabled |
| Yellow diamond/hexagon | Feature flag decision point |
| Blue box | Convergence point where multiple paths merge |
| Grey box | Intermediate processing step or terminal state |
Intake Path Summary
Section titled βIntake Path Summaryβ| Path | Trigger | Entry Point | Temporal Workflow |
|---|---|---|---|
| Cloudflare Email Worker | Cloudflare Worker parses inbound email, uploads attachments to R2, posts webhook | POST /api/webhook/inbound-email | PDFExtractionWorkflow (per attachment) |
| Gmail Poll | Temporal schedule (per-connection mailbox poll every N minutes) | ScheduledEmailPullDispatcher | EmailProcessingWorkflow (per message) |
| PDF Upload | User uploads PDF/Excel via webapp UI | POST /api/pdf-documents | PDFExtractionWorkflow |
All paths converge on AgenticValidationWorkflow, which runs as a child workflow
of either EmailProcessingWorkflow or PDFExtractionWorkflow.
Feature Flag Reference
Section titled βFeature Flag Referenceβ| Flag | Type | Default | Effect |
|---|---|---|---|
agentic_validation_enabled | boolean | false | Gates the entire AgenticValidationWorkflow. When off, orders skip validation and go directly to the manual review queue with a disabled status. |
agentic_auto_submit_enabled | boolean | false | Allows automatic ERP submission after successful agentic validation. Requires agentic_validation_enabled. When off, passing validation results in a dry_run (decision logged but not submitted). |
agentic_confidence_threshold | multivariate | 0.95 | Minimum confidence score for auto-submit. Orders below this threshold are escalated to manual review regardless of other flags. |
erp_write_enabled | boolean | false | Global safety switch allowing the agentic workflow to write to ERP systems. Must be true alongside agentic_auto_submit_enabled for actual submission. When off, auto-submit decisions become dry runs. |
email_enabled | boolean | false | Master switch for email functionality (inbox, aliases, email-to-order). |
Retired (2026-06):
use_temporal_for_erp_writes,use_temporal_for_quote_writes, anduse_temporal_for_order_writesare no longer used. All manual ERP write paths (quote generation, order creation, order sync) now route through Temporal unconditionally; the synchronous P21 fallback and these flags have been removed.
Current Default Behavior (all flags at defaults)
Section titled βCurrent Default Behavior (all flags at defaults)β- Email/PDF intake paths are always active (email processing requires
email_enabledper-org). - Agentic validation is disabled β orders go straight to the manual review queue.
- Manual submit uses a Temporal workflow (
ERPOrderSubmissionWorkflow) for thePOST /api/erp/orders/[id]/submitpath. - Quote generation uses a Temporal workflow (
ERPQuoteGenerationWorkflow) for thePOST /api/erp/orders/generate-quotepath β unconditional, same as order creation and sync. - Auto-submit is completely inactive β even if validation were enabled and passed,
agentic_auto_submit_enabledanderp_write_enabledboth default to off.