# Phase 7: DKV Fleet Module - Context **Gathered:** 2026-06-26 **Status:** Ready for planning ## Phase Boundary Build 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 Decisions ### Email 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 `mail` module (`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 with `xlsx` (SheetJS) - **D-12:** Filename: `DKV_YYYY-MM_.xlsx` — example: `DKV_2026-04_26-651566449-001.xlsx` - **D-13:** Exactly 5 columns in this order: 1. **Lieferdatum** — format `TT.MM.JJJJ` (e.g., `13.12.2020`) 2. **Fahrzeug** — format `{Marke}/{Modell}/{Kennzeichen}` (e.g., `Mercedes/GLC 300 de 4MATIC/GP-JL 728E`) — format string configurable in module 3. **Fahrer** — format `Vorname Nachname` (resolved from vehicle master data via Kennzeichen) 4. **Ort** — Servicestation Ort from PDF 5. **Kilometerstand** — numeric, no unit - **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/schedule` ScheduleModule) - EWS reuse from existing `ews-javascript-api` (already installed for calendar) - IMAP library choice (`imapflow` recommended — modern, Promise-based) - PDF parsing robustness (handle multi-page, multi-vehicle DKV format) - Frontend component patterns (reuse existing admin table / settings patterns) ## 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 passwords - `apps/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 development - `user-files/fahrzeuge_bereinigt.xlsx` — cleaned vehicle master data — use to understand CSV import schema - `user-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 in `apps/api/package.json`) - `nodemailer@^9.0.1` — SMTP send (already in `apps/api/package.json`) ### New dependencies needed - `imapflow` — IMAP client (modern, Promise-based) - `pdf-parse` — PDF text extraction - `xlsx` (SheetJS) — Excel file generation ## Existing Code Insights ### Reusable Assets - `apps/api/src/calendar/crypto.service.ts` — inject directly for encrypting inbox + SMTP credentials - `apps/api/src/mail/mail.service.ts` — extend (not replace) for DB-driven SMTP config - `apps/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/schedule` for 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 here - `apps/api/src/prisma/` — add new tables: `dkv_module_config`, `dkv_vehicle_master`, `dkv_invoice_history` - `apps/web/src/app/(portal)/` — new module page follows existing portal route pattern - `user-files/` directory — already exists, used for file storage ## Specific Ideas - DKV PDF structure: each vehicle section starts with `VEHICLE: {Kennzeichen} CARD NO.: {CardNumber}`, followed by transaction rows; ends with `TOTAL:` 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. ## Deferred Ideas None — discussion stayed within phase scope. --- *Phase: 7-DKV Fleet Module* *Context gathered: 2026-06-26*