feat: Maintenance Receipt Upload with OCR Auto-populate (#16) #161

Merged
egullickson merged 11 commits from issue-16-maintenance-receipt-upload-ocr into main 2026-02-13 22:19:45 +00:00

11 Commits

Author SHA1 Message Date
Eric Gullickson
1bf550ae9b feat: add pending vehicle association resolution UI (refs #160)
All checks were successful
Deploy to Staging / Build Images (pull_request) Successful in 8m40s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 52s
Deploy to Staging / Verify Staging (pull_request) Successful in 8s
Deploy to Staging / Notify Staging Ready (pull_request) Successful in 7s
Deploy to Staging / Notify Staging Failure (pull_request) Has been skipped
Backend: Add authenticated endpoints for pending association CRUD
(GET/POST/DELETE /api/email-ingestion/pending). Service methods for
resolving (creates fuel/maintenance record) and dismissing associations.

Frontend: New email-ingestion feature with types, API client, hooks,
PendingAssociationBanner (dashboard), PendingAssociationList, and
ResolveAssociationDialog. Mobile-first responsive with 44px touch
targets and full-screen dialogs on small screens.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 09:39:03 -06:00
Eric Gullickson
8bcac80818 feat: add email ingestion notification handler with logging (refs #159)
- Extract all notification logic from EmailIngestionService into
  dedicated EmailIngestionNotificationHandler class
- Add notification_logs entries for every email sent (success/failure)
- Add in-app user_notifications for all error scenarios (no vehicles,
  no attachments, OCR failure, processing failure)
- Update email templates with enhanced variables: merchantName,
  totalAmount, date, guidance
- Update pending vehicle notification title to 'Vehicle Selection Required'
- Add sample variables for receipt templates in test email flow

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 09:27:37 -06:00
Eric Gullickson
fce60759cf feat: add vehicle association and record creation (refs #158)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 08:53:08 -06:00
Eric Gullickson
d9a40f7d37 feat: add receipt classifier and OCR integration (refs #157)
- New ReceiptClassifier module with keyword-based classification for
  fuel vs maintenance receipts from email text and OCR raw text
- Classifier-first pipeline: classify from email subject/body keywords
  before falling back to OCR-based classification
- Fuel keywords: gas, fuel, gallons, octane, pump, diesel, unleaded,
  shell, chevron, exxon, bp
- Maintenance keywords: oil change, brake, alignment, tire, rotation,
  inspection, labor, parts, service, repair, transmission, coolant
- Confident classification (>= 2 keyword matches) routes to specific
  OCR endpoint; unclassified falls back to both endpoints + rawText
  classification + field-count heuristic

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 08:44:03 -06:00
Eric Gullickson
e7f3728771 feat: add email ingestion processing service and repository (refs #156)
- EmailIngestionRepository: queue CRUD (insert, update status, get,
  find by email ID), pending vehicle association management, mapRow
  pattern for snake_case -> camelCase conversion
- EmailIngestionService: full processing pipeline with sender validation,
  attachment filtering (PDF/PNG/JPG/JPEG/HEIC, <10MB), dual OCR
  classification (fuel vs maintenance), vehicle association logic
  (single-vehicle auto-associate, multi-vehicle pending), retry handling
  (max 3 attempts), and templated email replies (confirmation, failure,
  pending vehicle)
- Updated controller to delegate async processing to service
- Added receipt_processed/receipt_failed/receipt_pending_vehicle to
  TemplateKey union type

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 08:32:10 -06:00
Eric Gullickson
2462fff34d feat: add Resend inbound webhook endpoint and client (refs #155)
- ResendInboundClient: webhook signature verification via Svix, email
  fetch/download/parse with mailparser
- POST /api/webhooks/resend/inbound endpoint with rawBody, signature
  verification, idempotency check, queue insertion, async processing
- Config: resend_webhook_secret (optional) in secrets schema
- Route registration in app.ts following Stripe webhook pattern

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 08:22:25 -06:00
Eric Gullickson
877f844be6 feat: add email ingestion database schema and types (refs #154)
- Create email_ingestion_queue table with UNIQUE email_id constraint
- Create pending_vehicle_associations table with documents FK
- Seed 3 email templates: receipt_processed, receipt_failed, receipt_pending_vehicle
- Add TypeScript types for queue records, associations, and Resend webhook payloads
- Register email-ingestion in migration runner order

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 22:01:17 -06:00
Eric Gullickson
06ff8101dc feat: add form integration, tier gating, and receipt display (refs #153)
- Add tier-gated "Scan Receipt" button to MaintenanceRecordForm
- Wire useMaintenanceReceiptOcr hook with CameraCapture and ReviewModal
- Auto-populate form fields from accepted OCR results via setValue
- Upload receipt as document and pass receiptDocumentId on record create
- Show receipt thumbnail + "View Receipt" button in edit dialog
- Add receipt indicator chip on records list rows
- Add receiptDocumentId and receiptDocument to frontend types

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 21:40:27 -06:00
Eric Gullickson
91166b021c feat: add maintenance receipt OCR hook and review modal (refs #152)
Add useMaintenanceReceiptOcr hook mirroring fuel receipt OCR pattern,
MaintenanceReceiptReviewModal with confidence indicators and inline editing,
and maintenance-receipt.types.ts for extraction field types. Includes
category/subtype suggestion via keyword matching from service descriptions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 21:31:48 -06:00
Eric Gullickson
88d23d2745 feat: add backend migration and API for maintenance receipt linking (refs #151)
Add receipt_document_id FK on maintenance_records, update types/repo/service
to support receipt linking on create and return document metadata on GET.
Add OCR proxy endpoint POST /api/ocr/extract/maintenance-receipt with
tier gating (maintenance.receiptScan) through full chain: routes -> controller
-> service -> client.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 21:24:24 -06:00
Eric Gullickson
90401dc1ba feat: add maintenance receipt extraction pipeline with Gemini + regex (refs #150)
- New MaintenanceReceiptExtractor: Gemini-primary extraction with regex
  cross-validation for dates, amounts, and odometer readings
- New maintenance_receipt_validation.py: cross-validation patterns for
  structured field confidence adjustment
- New POST /extract/maintenance-receipt endpoint reusing
  ReceiptExtractionResponse model
- Per-field confidence scores (0.0-1.0) with Gemini base 0.85,
  boosted/reduced by regex agreement

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 21:14:13 -06:00