Learn
10 · Invoice intake
10: Build-Along - Invoice Intake Validation + Approval Routing
Goal: automate AP intake routing with clear, auditable decision criteria.
You will implement one practical workflow:
- query invoice intake rows,
- apply routing rules (
auto_approve,finance_review,needs_po), - send an approval-routing digest email.
Why This Matters
Accounts-payable intake is repetitive and error-prone when routed manually.
This workflow makes the policy explicit and reviewable.
Final Workflow File
examples/realworld/invoice-intake-approval-digest.gr
Business Rules
Current example rules:
amount_usd > 5000->finance_review- missing PO number ->
needs_po - otherwise ->
auto_approve
Digest includes:
- per-invoice line with route decision
- summary counts per route class
Run It
CLI path:
GRAPHEME_ALLOWED_SQL_CONNECTIONS=sqlite::memory: \
GRAPHEME_ALLOWED_SMTP_DOMAINS=example.com \
grapheme run examples/realworld/invoice-intake-approval-digest.gr --json
Workspace path:
GRAPHEME_ALLOWED_SQL_CONNECTIONS=sqlite::memory: \
GRAPHEME_ALLOWED_SMTP_DOMAINS=example.com \
cargo run -- run examples/realworld/invoice-intake-approval-digest.gr --json
Expected Output Signals
Look for:
"outcome": "succeeded"- SMTP accepted state
- digest body with
SUMMARY | total=...line
Required Failure Drills
- Remove SQL allow-list env var.
- Observe policy/connectivity failure behavior.
- Remove SMTP allow-list env var.
- Observe mail send failure behavior.
- Raise or lower finance threshold in SQL.
- Confirm
finance_reviewcount changes in summary.
- Populate missing PO value for one invoice.
- Confirm
needs_pocount drops.
Production Adaptation
- Replace inline CTE with real AP intake table/view.
- Externalize thresholds and routing policy.
- Add approver metadata in output lines.
- Add branch for paging finance-oncall when review queue spikes.
This pattern turns finance routing policy into executable, testable workflow logic.