Success: Create user_notification with type='email_ingestion', title='Receipt Processed', message with details, referenceType='fuel_log' or 'maintenance_record', referenceId=created record ID, vehicleId
Pending vehicle: Create notification with type='email_ingestion', title='Vehicle Selection Required', referenceType='pending_vehicle_association', referenceId=pending association ID
Error: Create notification with type='email_ingestion', title='Receipt Processing Failed', message with error details
Error Reply Emails
Unregistered sender: Send error email explaining the email must come from registered address
No vehicle: Send error email explaining user must add a vehicle first
OCR failure (after 3 retries): Send error email with details
receipt_failed: Replaced emailSubject with guidance variable, updated HTML to show guidance section
receipt_pending_vehicle: Added merchantName, totalAmount, date variables
Updated: notifications.service.ts
Added sample variables for receipt_processed, receipt_failed, receipt_pending_vehicle in test email flow
Acceptance Criteria
Success email sent and in-app notification created
Pending vehicle notification created for multi-vehicle users
Error emails sent for each failure scenario (unregistered sender, no vehicles, no attachments, OCR failure, processing failure)
All emails logged to notification_logs
Validation
TypeScript: 0 errors
Lint: 0 errors (656 pre-existing warnings)
Verdict: PASS | Next: Quality review
## Milestone: Implementation Complete
**Phase**: Execution | **Agent**: Developer | **Status**: PASS
### Changes Made
**New file: `notification-handler.ts`**
- `EmailIngestionNotificationHandler` class encapsulating all notification logic
- Methods: `notifyReceiptProcessed`, `notifyPendingVehicleSelection`, `notifyUnregisteredSender`, `notifyNoVehicles`, `notifyNoValidAttachments`, `notifyOcrFailure`, `notifyProcessingFailure`
- Every email sent is logged to `notification_logs` via `insertNotificationLog` (both success and failure)
- In-app `user_notification` created for all scenarios (success, pending vehicle, all error types)
- Error scenarios without userId (unregistered sender) gracefully skip in-app notification and logging
**Updated: `email-ingestion.service.ts`**
- Replaced 6 inline notification methods (~130 lines) with delegation to `EmailIngestionNotificationHandler`
- Error handlers now pass `userId`/`userName` to notification handler for in-app notifications
- Vehicle name built from `nickname || year make model` (no `name` field on Vehicle type)
- Removed `sendConfirmationEmail`, `sendFailureEmail`, `sendNoVehiclesEmail`, `sendPendingVehicleEmail`
**Updated: `002_create_email_templates.sql`**
- `receipt_processed`: Added `merchantName`, renamed `receiptDate`->`date`, `amount`->`totalAmount`
- `receipt_failed`: Replaced `emailSubject` with `guidance` variable, updated HTML to show guidance section
- `receipt_pending_vehicle`: Added `merchantName`, `totalAmount`, `date` variables
**Updated: `notifications.service.ts`**
- Added sample variables for `receipt_processed`, `receipt_failed`, `receipt_pending_vehicle` in test email flow
### Acceptance Criteria
- [x] Success email sent and in-app notification created
- [x] Pending vehicle notification created for multi-vehicle users
- [x] Error emails sent for each failure scenario (unregistered sender, no vehicles, no attachments, OCR failure, processing failure)
- [x] All emails logged to notification_logs
### Validation
- TypeScript: 0 errors
- Lint: 0 errors (656 pre-existing warnings)
*Verdict*: PASS | *Next*: Quality review
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Relates to #149
Scope
Implement all notification paths for the email ingestion flow.
Email Templates (content)
Define template content for the 3 templates created in migration sub-issue:
In-App Notifications
user_notificationwith type='email_ingestion', title='Receipt Processed', message with details, referenceType='fuel_log' or 'maintenance_record', referenceId=created record ID, vehicleIdError Reply Emails
Notification Logging
notification_logswith reference_type='email_ingestion'Files
backend/src/features/email-ingestion/domain/notification-handler.tsAcceptance Criteria
Milestone: Implementation Complete
Phase: Execution | Agent: Developer | Status: PASS
Changes Made
New file:
notification-handler.tsEmailIngestionNotificationHandlerclass encapsulating all notification logicnotifyReceiptProcessed,notifyPendingVehicleSelection,notifyUnregisteredSender,notifyNoVehicles,notifyNoValidAttachments,notifyOcrFailure,notifyProcessingFailurenotification_logsviainsertNotificationLog(both success and failure)user_notificationcreated for all scenarios (success, pending vehicle, all error types)Updated:
email-ingestion.service.tsEmailIngestionNotificationHandleruserId/userNameto notification handler for in-app notificationsnickname || year make model(nonamefield on Vehicle type)sendConfirmationEmail,sendFailureEmail,sendNoVehiclesEmail,sendPendingVehicleEmailUpdated:
002_create_email_templates.sqlreceipt_processed: AddedmerchantName, renamedreceiptDate->date,amount->totalAmountreceipt_failed: ReplacedemailSubjectwithguidancevariable, updated HTML to show guidance sectionreceipt_pending_vehicle: AddedmerchantName,totalAmount,datevariablesUpdated:
notifications.service.tsreceipt_processed,receipt_failed,receipt_pending_vehiclein test email flowAcceptance Criteria
Validation
Verdict: PASS | Next: Quality review