7.1 KiB
7.1 KiB
Phase 7: DKV Fleet Module - Context
Gathered: 2026-06-26 Status: Ready for planning
## Phase BoundaryBuild a Tessera module that monitors an email inbox for DKV fuel card invoices, parses the PDF attachments, maps license plates to drivers via a configurable vehicle master list, exports a 5-column Excel file, and delivers it via SMTP. Includes processing history and file storage for the last 10 exports.
## Implementation DecisionsEmail Inbox Monitoring
- D-01: Support both IMAP and Exchange (EWS) as inbox protocols — selectable per module config
- D-02: Polling via configurable cron job (interval in minutes, set in module config) + manual "Jetzt prüfen" button in the UI
- D-03: Inbox config fields: Protocol (IMAP/Exchange), Host, Port, Username (optional), Password (optional), Encryption (None/STARTTLS/SSL-TLS), Folder, Sender filter (email address to watch for DKV invoices)
- D-04: Credentials stored encrypted (AES-256-GCM via existing
crypto.service.ts)
SMTP / Email Send
- D-05: SMTP settings live in general settings (shared, not per-module): Host, Port, Username (optional), Password (optional), Encryption (None/STARTTLS/SSL-TLS), Sender address
- D-06: Existing
mailmodule (apps/api/src/mail/) must be extended to read SMTP config from DB instead of hardcoded env vars - D-07: Export recipient address configured per module (not in general settings)
PDF Parsing
- D-08: Parse DKV E-Rechnung PDF using
pdf-parse(text extraction + regex) — DKV PDF structure is consistent across invoices - D-09: Parsed data per vehicle block: Kennzeichen (from
VEHICLE: ...header), per-transaction rows with Lieferdatum, Servicestation Ort, Kilometerstand, Produkt, Menge, Einheit - D-10: On parse failure: 3 retries, then mark as failed in processing history with error message
Export Format
- D-11: Output format:
.xlsx(Excel), generated withxlsx(SheetJS) - D-12: Filename:
DKV_YYYY-MM_<Rechnungsnummer>.xlsx— example:DKV_2026-04_26-651566449-001.xlsx - D-13: Exactly 5 columns in this order:
- Lieferdatum — format
TT.MM.JJJJ(e.g.,13.12.2020) - Fahrzeug — format
{Marke}/{Modell}/{Kennzeichen}(e.g.,Mercedes/GLC 300 de 4MATIC/GP-JL 728E) — format string configurable in module - Fahrer — format
Vorname Nachname(resolved from vehicle master data via Kennzeichen) - Ort — Servicestation Ort from PDF
- Kilometerstand — numeric, no unit
- Lieferdatum — format
- D-14: One Excel file per processed invoice (not cumulative)
- D-15: Last 10 export files stored in
user-files/directory, downloadable from module UI
SMTP Send (on export ready)
- D-16: On SMTP failure: 3 retries with exponential backoff, then mark as "Versand fehlgeschlagen" in history; export file remains locally available for manual download
Vehicle Master Data
- D-17: Vehicle master data stored in DB per tenant; fields: Kennzeichen, Marke, Modell, Fahrer (Vorname Nachname)
- D-18: Importable as CSV (bulk replace or merge); also manually editable in module UI (CRUD table)
- D-19: Fahrzeug column format string is configurable (default:
{Marke}/{Modell}/{Kennzeichen})
Processing History
- D-20: Processing history table in module UI: Datum/Zeit, Rechnungsnummer, Anzahl Fahrzeuge, Anzahl Transaktionen, Status (Verarbeitet / Fehler / Versand fehlgeschlagen), Export-Dateiname
- D-21: History stored in DB; entries kept indefinitely (no auto-purge in v1)
Claude's Discretion
- DB schema design (vehicle_master, dkv_invoice_history, dkv_module_config tables)
- Cron job implementation (NestJS
@nestjs/scheduleScheduleModule) - EWS reuse from existing
ews-javascript-api(already installed for calendar) - IMAP library choice (
imapflowrecommended — modern, Promise-based) - PDF parsing robustness (handle multi-page, multi-vehicle DKV format)
- Frontend component patterns (reuse existing admin table / settings patterns)
<canonical_refs>
Canonical References
Downstream agents MUST read these before planning or implementing.
Existing modules to extend/reuse
apps/api/src/mail/mail.service.ts— existing mail service (uses @nestjs-modules/mailer, env-based — must be extended for DB SMTP config)apps/api/src/calendar/crypto.service.ts— AES-256-GCM credential encryption, use for inbox + SMTP passwordsapps/api/src/calendar/calendar.service.ts— reference pattern for provider abstraction (IMAP vs Exchange mirrors CalDAV vs EWS)apps/api/src/calendar/providers/— EWS provider pattern to follow for Exchange inbox monitoring
Reference data (user-provided)
user-files/invoice.pdf— real DKV E-Rechnung (April 2026, 4 pages, 27 vehicles) — use as parse target for regex developmentuser-files/fahrzeuge_bereinigt.xlsx— cleaned vehicle master data — use to understand CSV import schemauser-files/Bildschirmfoto 2026-06-24 um 13.27.56.png— reference UI for the module view
Installed dependencies (no new install needed)
ews-javascript-api@0.15.3— Exchange inbox access (already inapps/api/package.json)nodemailer@^9.0.1— SMTP send (already inapps/api/package.json)
New dependencies needed
imapflow— IMAP client (modern, Promise-based)pdf-parse— PDF text extractionxlsx(SheetJS) — Excel file generation
</canonical_refs>
<code_context>
Existing Code Insights
Reusable Assets
apps/api/src/calendar/crypto.service.ts— inject directly for encrypting inbox + SMTP credentialsapps/api/src/mail/mail.service.ts— extend (not replace) for DB-driven SMTP configapps/api/src/calendar/providers/— provider abstraction pattern for IMAP vs Exchange
Established Patterns
- NestJS module structure:
*.module.ts,*.service.ts,*.controller.ts,dto/— follow same layout - Prisma migrations for new tables
@nestjs/schedulefor cron (already in NestJS ecosystem)- Tenant isolation via existing RLS / tenant context
Integration Points
apps/api/src/mail/mail.module.ts— add DB-SMTP config support hereapps/api/src/prisma/— add new tables:dkv_module_config,dkv_vehicle_master,dkv_invoice_historyapps/web/src/app/(portal)/— new module page follows existing portal route patternuser-files/directory — already exists, used for file storage
</code_context>
## Specific Ideas- DKV PDF structure: each vehicle section starts with
VEHICLE: {Kennzeichen} CARD NO.: {CardNumber}, followed by transaction rows; ends withTOTAL:row per vehicle. Regex anchors on these markers. - The Fahrzeug column format
{Marke}/{Modell}/{Kennzeichen}should use a configurable template string so admins can change it (e.g.,{Kennzeichen} - {Fahrer}alternative). - Screenshot reference shows card-style rows with vehicle thumbnail, driver avatar, km reading, amount — the actual Excel export is a flat table, the UI shows the same data in card style.
None — discussion stayed within phase scope.
Phase: 7-DKV Fleet Module Context gathered: 2026-06-26