Kelvin Perez
Back

Invoice and receipt processor

I built a TypeScript document workflow that validates extracted fields, holds uncertain receipts for review and reconciles accounting writes before replay.

Invoice and receipt processor, original project capture
Invoice & Receipt Processor Demonstration · 4:31

Invoice & Receipt Processor Demonstration

English scene descriptions available in the player. Open the recording

Untrimmed browser QA with a real receipt and synthetic recovery control. Silent footage; includes a reload during a button fix.

Read visual walkthrough description

This demonstration has no spoken narration. The text below describes the recorded visuals.

Untrimmed browser QA with a real receipt and synthetic recovery control. Silent footage; includes a reload during a button fix.

00:00:00.000 Actual recorded browser QA: a real receipt is submitted to the development task and held for review.

00:00:40.000 A declared synthetic control is submitted through Trigger.dev. This is controlled QA, not production bookkeeping.

00:01:30.000 The synthetic control requires currency confirmation. Missing fields must not be guessed.

00:02:15.000 A test-contract correction supplies USD for the synthetic control. Approval and export are verified in this recording.

00:03:00.000 The accepted synthetic control and review interface are inspected. The untrimmed footage includes a reload during a button fix.

00:03:45.000 Accepted synthetic output is available for local QA CSV export. Incomplete real receipts remain held.

Download timed captions

Try the interactive workflow

01

The problem

Repeated entry of vendor names, amounts and due dates creates an accounting task that needs both speed and a reliable way to handle uncertainty.

02

My role

Independent controlled portfolio project. I designed and implemented the intake, receipt parser, validation rules, private review interface, accounting adapter and recovery tests.

03

The approach

Hosted Trigger.dev schedules a single macOS development worker. The worker reads private PDF snapshots, extracts draft fields with source evidence and validates them in TypeScript. A durable private store routes uncertain records to review and accepted revisions to a controlled CSV.

  • Keep extraction separate from permission to export. Missing identity and currency stay unknown, even when the amount is recovered.
  • Normalize international separator patterns with strict grouping and preserve the original evidence. Receipts may omit due dates; invoices may not.
  • Configure three retries explicitly after the initial attempt, then stop permanent and ambiguous-write failures.
  • Use a single persistent filesystem for the controlled worker. A public visitor gateway and deployed extraction/state backend remain separate work.

From document to decision

Read the receipt. Validate before writing.

Hosted Trigger.dev schedules the private macOS worker and records its attempts. The worker keeps extraction, validation and permission to export separate.

Try it: make the review decision.

Interactive browser practice. Uses retained extraction and the processor’s validation rules. No upload, Trigger.dev run or external accounting write.

Selected source: CORD receipt 002

Selected: CORD receipt 002

Real receipt with unresolved vendor and currency. The retained OCR draft is available to inspect.

NAVER CLOVA, CORD v2 test split, CC BY 4.0. Original JPEG retained; resized thumbnail. Dataset source

Inspect the full document
  1. source
  2. extracted
  3. review
  4. accepted
  5. reconcile
  6. exported

CORD receipt 002

State: source

Real receipt with unresolved vendor and currency. The retained OCR draft is available to inspect.

Choose a sample and inspect its draft.

Demonstration accounting rows (0)

No accepted output yet.

Inspect this practice session’s events
    Document image
    Fit

    Zoom to inspect details. Scroll to move around the document. Press Escape to close.

    1. 01

      Private PDF

      Bound the file, calculate its content hash and preserve an immutable snapshot.

    2. 02

      Extract with evidence

      Read text or run local OCR. Keep the original source line beside each proposed field.

    3. 03

      Validate in code

      Check required fields, exact amounts and due-date rules before allowing output.

    If uncertain

    Hold for human review

    Show the source and blocking reasons. Record a correction, then validate the revised document again.

    If accepted

    Write the controlled record once

    Persist intent, append and sync the accounting row, then save its destination receipt. Reconcile uncertain writes before replay.

    Actual controlled architecture. The portfolio presents retained evidence; it does not submit a new task.

    04

    The solution

    The private browser shows each source beside its fields and validation reasons. Corrections preserve a reason, actor, timestamp and version, then pass through validation again. A stable business marker and complete-row readback protect the accounting boundary after a lost acknowledgement.

    Original CORD test receipt 002 showing TOTAL SALES 28,000
    NAVER CLOVA CORD v2, test row 2. Original image, CC BY 4.0. Publisher dataset .

    One real receipt, two different conclusions

    The total was recovered. The record was still incomplete.

    Original evidence
    TOTAL SALES 28,000
    Normalized draft
    28000.00
    Vendor / currency
    Not established by the source
    Disposition
    Human review. No accounting row.

    A comma can mark grouping or a decimal separator. Strict parsing preserves the source and asks for confirmation when notation is ambiguous. Currency stays unknown instead of being inferred from the country.

    Receipts can omit a due date. Invoices require a valid date and invoice number. A plausible amount alone never grants permission to export.

    The review decision stays beside the document.

    Actual private review screen with the source receipt, draft fields and reasons blocking approval
    Actual retained review screen. Missing vendor and currency keep this receipt unresolved. A correction must include its source and reason, preserve a versioned decision and pass validation again.

    A separate synthetic control proves accepted output.

    Actual private review screen after a synthetic invoice correction and controlled export
    The synthetic invoice's declared test contract supplies the missing currency. Its accepted revision was exported through Trigger.dev. None of the five real receipts was filled with invented identity data.

    05

    Results & impact

    All five CORD development receipt totals matched reference annotations. All five remained in review and produced zero exports because required fields were unresolved. Three separate synthetic controls produced three accounting rows with unique markers.

    06

    Lessons & takeaways

    Preserve ownership and human review across the connected workflow. Measure each outcome separately and retain the limits of the controlled evidence.

    07

    Explore the evidence

    The failure path is part of the design

    Retry a transient fault. Reconcile an uncertain write.

    Retained Trigger.dev history shows a transient control recovering on attempt two and a separate control exhausting all four attempts. Three retries after the first attempt are explicitly configured, with 1, 2 and 4 second backoff.

    1. Save the write intent

      Persist a stable business marker before appending the accounting row.

    2. Stop on an unknown outcome

      A timeout after append aborts automatic retry. A lost acknowledgement does not establish a failed write.

    3. Read back before replay

      One exact marker and complete-row match confirms the existing effect. Missing, changed or multiple rows require operator reconciliation.

    5 of 5 development receipt totals matched reference annotations. All five stayed in review.

    3 unique markers for three synthetic accounting rows. A new run ID is not a new transaction.

    Inspect the retained measurements .

    A review decision you can inspect

    The central example is receipt 002, where the original total line uses a comma. The parser proposes 28000.00 while preserving the original evidence. Missing vendor and currency fields keep the receipt in review. The separate synthetic controls show approval and export without inventing fields for a real receipt.

    The recovery decision

    A timeout after an accounting append does not establish that the write failed. The processor saves intent first and then compares a stable destination marker and the complete expected row before replay. Missing, changed or multiple rows stop for operator reconciliation.

    Prepare a walkthrough

    Open the visual presentation, read the detailed architecture explanation. Presentation controls navigate retained evidence; they do not submit new Trigger.dev tasks.

    Validation and scope

    The regression suite passes 55 checks and TypeScript validation. Actual Trigger.dev runs demonstrate retry recovery, four-attempt exhaustion, review routing and timeout-after-write reconciliation. Renamed duplicates and complete destination-row matching are covered.

    • Five development receipts were evaluated.
    • The verified extraction worker runs locally on macOS. Public visitor execution is not deployed. The visual walkthrough presents retained execution evidence.
    • The output is a private controlled CSV, not QuickBooks, payments or production bookkeeping.
    • The polished narrated recording is not yet recorded. The existing untrimmed QA capture is a separate artifact.

    Next steps

    • Record the prepared narration with the visual presentation and actual private workflow.
    • Deploy and verify a session-isolated public execution gateway before offering a live visitor processing action.

    Let's build what comes next.

    Talk with me about your team and the systems you need.

    Contact options

    Project image

    100%