2026-07-13 03:34:35 +02:00
{
"project" : "erp-nutzfahrzeuge" ,
"version" : "1.0" ,
"created" : "2026-07-12" ,
"status" : "approved_for_implementation" ,
"total_tasks" : 8 ,
"tasks" : [
{
"id" : "T01" ,
"title" : "Auth + User Management + RBAC + Base Frontend Layout + i18n Setup" ,
"category" : "foundation" ,
"description" : "Komplettes Auth-System: JWT login/refresh, User CRUD (admin only), RBAC Middleware (admin/verkaeufer/buchhaltung). Backend: User Model, auth_service, auth router, users router, JWT utils, RBAC dependency. Frontend: Root layout, Login page, Auth context/hooks, i18n setup (next-intl oder react-i18next), de.json + en.json Basistranslationen, API client (fetch wrapper mit Auth-Header), Base UI components (Button, Input, Card, Table, Modal, Toast). Health endpoint /api/health. Config via Pydantic BaseSettings (DB URL, Redis URL, JWT Secret, OpenRouter Key, mobile.de credentials)." ,
"assigned_subagent" : "implementation_engineer" ,
"dependencies" : [ ] ,
"requirement_ids" : [ "M6-F1" , "M6-F2" , "AUTH-1" , "AUTH-2" , "AUTH-3" , "AUTH-4" , "I18N-1" , "I18N-2" ] ,
"estimated_effort" : "L" ,
"estimated_lines" : 600 ,
"acceptance_criteria" : [
"POST /api/auth/login mit valid credentials → 200 + JWT access_token + refresh_token" ,
"POST /api/auth/login mit invalid credentials → 401" ,
"POST /api/auth/refresh mit valid refresh_token → 200 + new access_token" ,
"GET /api/auth/me mit valid JWT → 200 + user object (email, full_name, role)" ,
"GET /api/users ohne admin role → 403" ,
"GET /api/users mit admin role → 200 + paginated user list" ,
"POST /api/users mit valid data → 201 + user object" ,
"DELETE /api/users/:id → 200 + user.is_active=false" ,
"GET /api/health → 200 + {status: 'ok'}" ,
"Frontend Login page rendert und sendet POST /api/auth/login" ,
"Frontend zeigt Toast bei login error" ,
"i18n: de.json und en.json existieren mit mindestens 20 keys" ,
"Sprachumschaltung DE/EN wechselt UI-Texte live" ,
"RBAC: /api/users blocked für verkaeufer role → 403" ,
"pytest coverage >= 80% für auth module"
] ,
"test_spec" : {
"commands" : [
"cd backend && python -m pytest tests/test_auth.py tests/test_users.py --cov=app/services/auth_service --cov=app/routers/auth --cov=app/routers/users --cov-report=term-missing -v" ,
"cd backend && python -m pytest tests/test_health.py -v" ,
"cd frontend && npx vitest run tests/auth.test.tsx tests/i18n.test.tsx --coverage"
] ,
"expected_results" : "All auth tests pass (login, refresh, RBAC, user CRUD). Health endpoint returns 200. Frontend login form renders and submits. i18n loads DE/EN translations. Coverage >= 80% backend auth, >= 70% frontend auth." ,
"test_files" : [
"backend/tests/test_auth.py" ,
"backend/tests/test_users.py" ,
"backend/tests/test_health.py" ,
"backend/tests/conftest.py" ,
"frontend/tests/auth.test.tsx" ,
"frontend/tests/i18n.test.tsx"
] ,
"coverage_target" : 80
} ,
"files_to_create" : [
"backend/app/main.py" ,
"backend/app/config.py" ,
"backend/app/database.py" ,
"backend/app/dependencies.py" ,
"backend/app/models/user.py" ,
"backend/app/schemas/user.py" ,
"backend/app/routers/auth.py" ,
"backend/app/routers/users.py" ,
"backend/app/services/auth_service.py" ,
"backend/app/utils/jwt.py" ,
"backend/app/utils/i18n.py" ,
"backend/tests/test_auth.py" ,
"backend/tests/test_users.py" ,
"backend/tests/test_health.py" ,
"backend/tests/conftest.py" ,
"frontend/app/layout.tsx" ,
"frontend/app/(auth)/login/page.tsx" ,
"frontend/lib/api.ts" ,
"frontend/lib/auth.ts" ,
"frontend/lib/i18n.ts" ,
"frontend/messages/de.json" ,
"frontend/messages/en.json" ,
"frontend/components/ui/Button.tsx" ,
"frontend/components/ui/Input.tsx" ,
"frontend/components/ui/Card.tsx" ,
"frontend/components/ui/Table.tsx" ,
"frontend/components/ui/Modal.tsx" ,
"frontend/components/ui/Toast.tsx" ,
"frontend/tests/auth.test.tsx" ,
"frontend/tests/i18n.test.tsx"
]
} ,
{
"id" : "T02" ,
"title" : "Vehicle Management + mobile.de Push + Vehicle UI" ,
"category" : "vehicle" ,
"description" : "Komplettes Fahrzeug-Modul: Vehicle Model (LKW, Baumaschine, PKW, Stapler, Transporter), vehicle_service mit CRUD + filter/sort/paginate, vehicles router mit allen Endpoints. mobile.de Seller API Integration (Push only): mobilede_service, mobilede_push background task, Ad-Format Mapping, Retry-Queue via Redis. Frontend: Vehicle List page mit Filter (type, status, brand) + Pagination + Sort, Vehicle Detail page, Vehicle Create/Edit form, mobile.de Push Button + Status indicator. Soft-Delete Implementierung (status='deleted')." ,
"assigned_subagent" : "implementation_engineer" ,
"dependencies" : [ "T01" ] ,
"requirement_ids" : [ "M1-F1" , "M1-F2" , "M1-F3" , "M1-F4" , "M1-F5" , "M1-F6" , "M1-F7" ] ,
"estimated_effort" : "L" ,
"estimated_lines" : 700 ,
"acceptance_criteria" : [
"GET /api/vehicles → 200 + paginated list (page, per_page, total)" ,
"GET /api/vehicles?type=lkw&status=in_stock → 200 + filtered list" ,
"GET /api/vehicles?sort=-created_at → 200 + sorted list" ,
"GET /api/vehicles/:id → 200 + vehicle detail object" ,
"GET /api/vehicles/:nonexistent → 404" ,
"POST /api/vehicles mit valid data → 201 + vehicle object" ,
"POST /api/vehicles mit missing brand → 422 validation error" ,
"PUT /api/vehicles/:id → 200 + updated vehicle" ,
"DELETE /api/vehicles/:id → 200 + status='deleted' (soft delete)" ,
"POST /api/vehicles/:id/mobilede-push → 202 (async push queued)" ,
"GET /api/vehicles/:id/mobilede-status → 200 + {synced: bool, ad_id, synced_at}" ,
"mobile.de Push sendet korrektes Ad-Format an Seller API" ,
"mobile.de Push Fehler → Retry-Queue (Redis), max 3 retries" ,
"Frontend Vehicle List zeigt Tabelle mit Filter + Pagination" ,
"Frontend Vehicle Detail zeigt alle Felder + mobile.de Status" ,
"Frontend Vehicle Create Form validiert Pflichtfelder" ,
"Frontend mobile.de Push Button → zeigt Sync-Status" ,
"pytest coverage >= 80% für vehicle module"
] ,
"test_spec" : {
"commands" : [
"cd backend && python -m pytest tests/test_vehicles.py tests/test_mobilede.py --cov=app/services/vehicle_service --cov=app/services/mobilede_service --cov=app/routers/vehicles --cov-report=term-missing -v" ,
"cd frontend && npx vitest run tests/vehicles.test.tsx --coverage"
] ,
"expected_results" : "All vehicle CRUD tests pass. Filter, sort, pagination work. mobile.de push queues async task. Soft delete sets status=deleted. Frontend list renders with filters. Coverage >= 80% backend, >= 70% frontend." ,
"test_files" : [
"backend/tests/test_vehicles.py" ,
"backend/tests/test_mobilede.py" ,
"frontend/tests/vehicles.test.tsx"
] ,
"coverage_target" : 80
} ,
"files_to_create" : [
"backend/app/models/vehicle.py" ,
"backend/app/schemas/vehicle.py" ,
"backend/app/routers/vehicles.py" ,
"backend/app/services/vehicle_service.py" ,
"backend/app/services/mobilede_service.py" ,
"backend/app/tasks/mobilede_push.py" ,
"backend/app/utils/mobilede_mapping.py" ,
"backend/tests/test_vehicles.py" ,
"backend/tests/test_mobilede.py" ,
"frontend/app/vehicles/page.tsx" ,
"frontend/app/vehicles/[id]/page.tsx" ,
"frontend/app/vehicles/new/page.tsx" ,
"frontend/components/vehicles/VehicleList.tsx" ,
"frontend/components/vehicles/VehicleForm.tsx" ,
"frontend/components/vehicles/VehicleDetail.tsx" ,
"frontend/components/vehicles/MobileDeStatus.tsx" ,
"frontend/tests/vehicles.test.tsx"
]
} ,
{
"id" : "T03" ,
"title" : "OCR-Erfassung (ZB I/II) via OpenRouter Vision + OCR UI" ,
"category" : "ocr" ,
2026-07-17 00:45:14 +02:00
"status" : "completed" ,
2026-07-13 03:34:35 +02:00
"description" : "Komplettes OCR-Modul: OCRResult Model, ocr_service mit OpenRouter Qwen2.5-VL Integration, OCR router (upload, get results, apply to vehicle). Async OCR processing via Redis Queue. Prompt-Engineering für ZB I/II: structured JSON output (brand, model, vin, first_registration, mileage, power_kw, fuel_type). Confidence-Score Berechnung. Manual Review bei confidence < 0.7. Response-Caching für identische Scans. Frontend: OCR Upload page (drag-and-drop), OCR Results view mit side-by-side Original Scan + Extracted Data, Apply-to-Vehicle Button." ,
"assigned_subagent" : "implementation_engineer" ,
"dependencies" : [ "T01" , "T02" ] ,
"requirement_ids" : [ "M2-F1" , "M2-F2" , "M2-F3" , "M2-F4" , "M2-F5" ] ,
"estimated_effort" : "L" ,
"estimated_lines" : 600 ,
"acceptance_criteria" : [
"POST /api/ocr/upload mit image file → 202 + ocr_result_id (async processing)" ,
"POST /api/ocr/upload ohne file → 422" ,
"POST /api/ocr/upload mit invalid MIME type → 422" ,
"GET /api/ocr/results/:id → 200 + {status, raw_text, structured_data, confidence_score}" ,
"GET /api/ocr/results?vehicle_id=X → 200 + list of OCR results for vehicle" ,
"POST /api/ocr/results/:id/apply → 200 + vehicle updated with OCR data" ,
"OCR processing mit mocked OpenRouter → structured_data enthält brand, model, vin" ,
"Confidence score < 0.7 → status='pending' (manual review needed)" ,
"Confidence score >= 0.7 → status='completed'" ,
"OCR Fehler (OpenRouter unavailable) → status='failed' + error message" ,
"Frontend OCR Upload akzeptiert Drag-and-Drop" ,
"Frontend OCR Results zeigt Original + Extracted Data side-by-side" ,
"Frontend Apply Button → sendet POST /api/ocr/results/:id/apply" ,
"pytest coverage >= 80% für ocr module"
] ,
"test_spec" : {
"commands" : [
"cd backend && python -m pytest tests/test_ocr.py --cov=app/services/ocr_service --cov=app/routers/ocr --cov=app/utils/openrouter --cov-report=term-missing -v" ,
"cd frontend && npx vitest run tests/ocr.test.tsx --coverage"
] ,
"expected_results" : "All OCR tests pass with mocked OpenRouter. Upload queues async task. Results retrievable. Apply updates vehicle. Confidence threshold works. Frontend upload + results render. Coverage >= 80% backend, >= 70% frontend." ,
"test_files" : [
"backend/tests/test_ocr.py" ,
"frontend/tests/ocr.test.tsx"
] ,
"coverage_target" : 80
} ,
"files_to_create" : [
"backend/app/models/ocr_result.py" ,
"backend/app/schemas/ocr.py" ,
"backend/app/routers/ocr.py" ,
"backend/app/services/ocr_service.py" ,
"backend/app/tasks/ocr_processing.py" ,
"backend/app/utils/openrouter.py" ,
"backend/tests/test_ocr.py" ,
"frontend/app/ocr/page.tsx" ,
"frontend/components/ocr/OCRUpload.tsx" ,
"frontend/components/ocr/OCRResults.tsx" ,
"frontend/components/ocr/OCRDetail.tsx" ,
"frontend/tests/ocr.test.tsx"
]
} ,
{
"id" : "T04" ,
"title" : "Kontakt-/Kundenverwaltung + Contact UI" ,
"category" : "contact" ,
"description" : "Komplettes Kontakt-Modul: Contact Model (Kunde/Lieferant/Beide, EU/Inland, USt-IdNr.), contact_service mit CRUD + search + filter (type, eu/inland), contacts router. USt-IdNr.-Feld mit Format-Validierung (DE + EU Formate). Contact-Search (name, company, city, email). Frontend: Contact List mit Search + Filter, Contact Detail page, Contact Create/Edit form. EU/Inland Toggle. USt-IdNr. input mit Format-Validierung frontend-seitig." ,
"assigned_subagent" : "implementation_engineer" ,
"dependencies" : [ "T01" ] ,
"requirement_ids" : [ "M3-F1" , "M3-F2" , "M3-F3" , "M3-F4" , "M3-F5" , "M3-F6" ] ,
"estimated_effort" : "M" ,
"estimated_lines" : 500 ,
"acceptance_criteria" : [
"GET /api/contacts → 200 + paginated list" ,
"GET /api/contacts?type=kunde → 200 + filtered list" ,
"GET /api/contacts?is_eu=true → 200 + EU contacts only" ,
"GET /api/contacts?search=mueller → 200 + matching contacts" ,
"GET /api/contacts/:id → 200 + contact detail" ,
"GET /api/contacts/:nonexistent → 404" ,
"POST /api/contacts mit valid data → 201 + contact object" ,
"POST /api/contacts mit invalid ust_id_nr format → 422" ,
"PUT /api/contacts/:id → 200 + updated contact" ,
"DELETE /api/contacts/:id → 200 (or 404 if not found)" ,
"Contact mit contact_type='beide' erscheint in kunde und lieferant filter" ,
"Frontend Contact List zeigt Tabelle mit Search + Filter" ,
"Frontend Contact Form validiert USt-IdNr. Format" ,
"Frontend EU/Inland Toggle ändert Pflichtfelder" ,
"pytest coverage >= 80% für contact module"
] ,
"test_spec" : {
"commands" : [
"cd backend && python -m pytest tests/test_contacts.py --cov=app/services/contact_service --cov=app/routers/contacts --cov-report=term-missing -v" ,
"cd frontend && npx vitest run tests/contacts.test.tsx --coverage"
] ,
"expected_results" : "All contact CRUD tests pass. Search, filter, pagination work. USt-IdNr. validation rejects invalid formats. Frontend list renders with search/filter. Coverage >= 80% backend, >= 70% frontend." ,
"test_files" : [
"backend/tests/test_contacts.py" ,
"frontend/tests/contacts.test.tsx"
] ,
"coverage_target" : 80
} ,
"files_to_create" : [
"backend/app/models/contact.py" ,
"backend/app/schemas/contact.py" ,
"backend/app/routers/contacts.py" ,
"backend/app/services/contact_service.py" ,
"backend/app/utils/ust_validation.py" ,
"backend/tests/test_contacts.py" ,
"frontend/app/contacts/page.tsx" ,
"frontend/app/contacts/[id]/page.tsx" ,
"frontend/app/contacts/new/page.tsx" ,
"frontend/components/contacts/ContactList.tsx" ,
"frontend/components/contacts/ContactForm.tsx" ,
"frontend/components/contacts/ContactDetail.tsx" ,
"frontend/tests/contacts.test.tsx"
]
} ,
{
"id" : "T05" ,
"title" : "Dateiablage pro Fahrzeug + File UI" ,
"category" : "file" ,
"description" : "Komplettes Dateiablage-Modul: File Model, file_service mit Upload/Download/Delete, files router. MIME-Type-Validierung (images: jpg/png/webp, documents: pdf/doc/docx, scans: jpg/png). Max 20MB pro Datei. Dateien gespeichert im uploads_data Volume. Thumbnail-Generierung für Images. Frontend: File Upload Component (Drag-and-Drop, multi-file), File List mit Thumbnails, File Download, File Delete mit Confirm. Gallery view für Fahrzeug-Bilder." ,
"assigned_subagent" : "implementation_engineer" ,
"dependencies" : [ "T01" , "T02" ] ,
"requirement_ids" : [ "M4-F1" , "M4-F2" , "M4-F3" , "M4-F4" , "M4-F5" ] ,
"estimated_effort" : "M" ,
"estimated_lines" : 500 ,
"acceptance_criteria" : [
"GET /api/vehicles/:id/files → 200 + list of files" ,
"POST /api/vehicles/:id/files mit multipart image → 201 + file object" ,
"POST /api/vehicles/:id/files mit >20MB file → 413" ,
"POST /api/vehicles/:id/files mit invalid MIME type → 422" ,
"GET /api/vehicles/:id/files/:fileId → 200 + file content (download)" ,
"DELETE /api/vehicles/:id/files/:fileId → 200 + file deleted" ,
"File gespeichert in uploads_data volume, path in DB gespeichert" ,
"Image files → Thumbnail generiert (200x200)" ,
"Frontend File Upload akzeptiert Drag-and-Drop multi-file" ,
"Frontend File List zeigt Thumbnails für images" ,
"Frontend File Delete zeigt Confirm Dialog" ,
"Frontend Gallery view für Fahrzeug-Bilder" ,
"pytest coverage >= 80% für file module"
] ,
"test_spec" : {
"commands" : [
"cd backend && python -m pytest tests/test_files.py --cov=app/services/file_service --cov=app/routers/files --cov-report=term-missing -v" ,
"cd frontend && npx vitest run tests/files.test.tsx --coverage"
] ,
"expected_results" : "All file CRUD tests pass. MIME validation rejects invalid types. Size limit enforced. Download returns file content. Thumbnails generated for images. Frontend upload + list + gallery render. Coverage >= 80% backend, >= 70% frontend." ,
"test_files" : [
"backend/tests/test_files.py" ,
"frontend/tests/files.test.tsx"
] ,
"coverage_target" : 80
} ,
"files_to_create" : [
"backend/app/models/file.py" ,
"backend/app/schemas/file.py" ,
"backend/app/routers/files.py" ,
"backend/app/services/file_service.py" ,
"backend/app/utils/thumbnails.py" ,
"backend/tests/test_files.py" ,
"frontend/components/files/FileUpload.tsx" ,
"frontend/components/files/FileList.tsx" ,
"frontend/components/files/FileGallery.tsx" ,
"frontend/components/files/FilePreview.tsx" ,
"frontend/tests/files.test.tsx"
]
} ,
{
"id" : "T06" ,
"title" : "Verkaufsmodul + Rechtsdokumente + DATEV-Export + Sales UI" ,
"category" : "sales" ,
"description" : "Komplettes Verkaufsmodul: Sale Model, sale_service mit CRUD, sales router. Contract PDF Generierung (Verkaufvertrag mit Vehicle + Contact Daten, GwG-Klausel, USt-IdNr. Feld). DATEV-Export: datev_service, DATEV CSV Format (Buchungsstapel: Datum, Konto, Gegenkonto, Betrag, Belegfeld, Buchungstext). GwG-Logik: Sofortabzug bei <= 800EUR (§6 Abs. 2 EStG). USt-IdNr.-Prüfung: BZSt API endpoint (Feature-Flag bzst_api_enabled, aktuell disabled → manual review). DATEVExport Model + router. Frontend: Sales List, Sale Detail mit Contract Preview, Sale Create form (Vehicle select, Contact select, Price, GwG toggle), DATEV Export page (Zeitraum wählen, Download CSV)." ,
"assigned_subagent" : "implementation_engineer" ,
"dependencies" : [ "T02" , "T04" ] ,
"requirement_ids" : [ "M5-F1" , "M5-F2" , "M5-F3" , "M5-F4" , "M5-F5" , "M5-F6" , "M5-F7" , "M5-F8" , "M5-F9" ] ,
"estimated_effort" : "XL" ,
"estimated_lines" : 800 ,
"acceptance_criteria" : [
"GET /api/sales → 200 + paginated list with filter (date range, status)" ,
"GET /api/sales/:id → 200 + sale detail with vehicle + contact nested" ,
"POST /api/sales mit valid data → 201 + sale object + contract_pdf_path" ,
"POST /api/sales ohne vehicle_id → 422" ,
"POST /api/sales ohne buyer_contact_id → 422" ,
"PUT /api/sales/:id → 200 + updated sale" ,
"DELETE /api/sales/:id → 200 (sale cancelled, vehicle status back to in_stock)" ,
"POST /api/sales/:id/contract → 200 + regenerated contract PDF path" ,
"GET /api/sales/:id/contract → 200 + PDF content (application/pdf)" ,
"Sale mit is_gwg=true und sale_price <= 800 → GwG-Klausel in contract" ,
"POST /api/sales/:id/verify-ust-id → 200 + {verified: false, message: 'BZSt API not available'} (feature flag disabled)" ,
"POST /api/datev/export mit date range → 201 + DATEVExport object" ,
"POST /api/datev/export mit invalid date range → 422" ,
"GET /api/datev/exports → 200 + list of exports" ,
"GET /api/datev/exports/:id/download → 200 + CSV content (text/csv)" ,
"DATEV CSV enthält korrekte Felder: Datum, Konto, Gegenkonto, Betrag, Belegfeld, Buchungstext" ,
"Sale creation → Vehicle status='sold'" ,
"Sale deletion → Vehicle status='in_stock'" ,
"Frontend Sales List zeigt Tabelle mit Date Filter" ,
"Frontend Sale Detail zeigt Contract Preview (PDF embed)" ,
"Frontend Sale Create Form mit Vehicle + Contact Selectors" ,
"Frontend DATEV Export page mit Date Range Picker + Download" ,
"pytest coverage >= 80% für sales + datev module"
] ,
"test_spec" : {
"commands" : [
"cd backend && python -m pytest tests/test_sales.py tests/test_datev.py --cov=app/services/sale_service --cov=app/services/datev_service --cov=app/routers/sales --cov=app/routers/datev --cov-report=term-missing -v" ,
"cd frontend && npx vitest run tests/sales.test.tsx tests/datev.test.tsx --coverage"
] ,
"expected_results" : "All sales CRUD tests pass. Contract PDF generated. DATEV CSV export with correct format. GwG logic applied. Vehicle status changes on sale create/delete. USt-IdNr. endpoint returns feature-flag message. Frontend list + detail + form + DATEV export render. Coverage >= 80% backend, >= 70% frontend." ,
"test_files" : [
"backend/tests/test_sales.py" ,
"backend/tests/test_datev.py" ,
"frontend/tests/sales.test.tsx" ,
"frontend/tests/datev.test.tsx"
] ,
"coverage_target" : 80
} ,
"files_to_create" : [
"backend/app/models/sale.py" ,
"backend/app/models/datev_export.py" ,
"backend/app/schemas/sale.py" ,
"backend/app/schemas/datev.py" ,
"backend/app/routers/sales.py" ,
"backend/app/routers/datev.py" ,
"backend/app/services/sale_service.py" ,
"backend/app/services/datev_service.py" ,
"backend/app/utils/contract_pdf.py" ,
"backend/app/utils/datev.py" ,
"backend/tests/test_sales.py" ,
"backend/tests/test_datev.py" ,
"frontend/app/sales/page.tsx" ,
"frontend/app/sales/[id]/page.tsx" ,
"frontend/app/sales/new/page.tsx" ,
"frontend/components/sales/SaleList.tsx" ,
"frontend/components/sales/SaleForm.tsx" ,
"frontend/components/sales/ContractPreview.tsx" ,
"frontend/components/sales/DatevExport.tsx" ,
"frontend/tests/sales.test.tsx" ,
"frontend/tests/datev.test.tsx"
]
} ,
{
"id" : "T07" ,
"title" : "KI-Copilot (Text + Sprache) + Systemsteuerung + Copilot UI" ,
"category" : "copilot" ,
"description" : "Komplettes KI-Copilot-Modul: Copilot chat_service mit OpenRouter (Claude/GPT-4), copilot router (chat, voice, history, action). System-Prompt mit ERP-Kontext (verfügbare Aktionen: vehicle search/create, contact search, sale overview). Action-System: Copilot kann strukturierte Actions ausführen (GET /api/vehicles, POST /api/contacts, etc.) via function-calling. Voice Input: STT via Browser Web Speech API → text → chat. Chat History (paginated, pro User). Frontend: Copilot Chat Interface (message list, input, send), Voice Input Button (microphone), Action Preview (zeigt was Copilot tun will vor Ausführung), Chat History sidebar." ,
"assigned_subagent" : "implementation_engineer" ,
"dependencies" : [ "T01" , "T02" ] ,
"requirement_ids" : [ "M7-F1" , "M7-F2" , "M7-F3" , "M7-F4" , "M7-F5" , "M7-F6" , "M7-F7" ] ,
"estimated_effort" : "L" ,
"estimated_lines" : 700 ,
"acceptance_criteria" : [
"POST /api/copilot/chat mit {message: 'Zeige alle LKWs'} → 200 + {response: '...', actions: [{type: 'search_vehicles', params: {type: 'lkw'}}]}" ,
"POST /api/copilot/chat mit empty message → 422" ,
"POST /api/copilot/action mit {action: 'search_vehicles', params: {type: 'lkw'}} → 200 + {result: [...vehicles...]}" ,
"POST /api/copilot/action mit invalid action → 400" ,
"GET /api/copilot/history → 200 + paginated chat history for current user" ,
"POST /api/copilot/voice → 200 (accepts audio, transcribes, returns chat response)" ,
"Copilot System-Prompt enthält ERP-Kontext und verfügbare Actions" ,
"Copilot kann vehicle search action auslösen (mocked OpenRouter)" ,
"Copilot kann contact search action auslösen (mocked OpenRouter)" ,
"Copilot response enthält action proposal (nicht direkt ausgeführt, User bestätigt)" ,
"Frontend Copilot Chat rendert message list + input" ,
"Frontend Voice Button startet Web Speech API" ,
"Frontend Action Preview zeigt geplante Aktion vor Bestätigung" ,
"Frontend Chat History sidebar zeigt vergangene Konversationen" ,
"pytest coverage >= 80% für copilot module (mit mocked OpenRouter)"
] ,
"test_spec" : {
"commands" : [
"cd backend && python -m pytest tests/test_copilot.py --cov=app/services/copilot_service --cov=app/routers/copilot --cov-report=term-missing -v" ,
"cd frontend && npx vitest run tests/copilot.test.tsx --coverage"
] ,
"expected_results" : "All copilot tests pass with mocked OpenRouter. Chat returns response + action proposals. Action endpoint executes approved actions. History paginated. Voice endpoint accepts audio. Frontend chat + voice + action preview render. Coverage >= 80% backend, >= 70% frontend." ,
"test_files" : [
"backend/tests/test_copilot.py" ,
"frontend/tests/copilot.test.tsx"
] ,
"coverage_target" : 80
} ,
"files_to_create" : [
"backend/app/models/copilot.py" ,
"backend/app/schemas/copilot.py" ,
"backend/app/routers/copilot.py" ,
"backend/app/services/copilot_service.py" ,
"backend/app/utils/copilot_actions.py" ,
"backend/app/utils/copilot_prompt.py" ,
"backend/tests/test_copilot.py" ,
"frontend/app/copilot/page.tsx" ,
"frontend/components/copilot/ChatInterface.tsx" ,
"frontend/components/copilot/MessageList.tsx" ,
"frontend/components/copilot/ChatInput.tsx" ,
"frontend/components/copilot/VoiceInput.tsx" ,
"frontend/components/copilot/ActionPreview.tsx" ,
"frontend/components/copilot/ChatHistory.tsx" ,
"frontend/tests/copilot.test.tsx"
]
} ,
{
"id" : "T08" ,
"title" : "Bildretusche + Preisvergleich (Flux.1-Pro + mobile.de) + Retouch UI" ,
"category" : "retouch" ,
"description" : "Komplettes Bildretusche-Modul: Retouch service mit OpenRouter Flux.1-Pro, retouch router (process, get result, price-compare). Bild-Verarbeitung: Upload → Flux.1-Pro Retusche (Hintergrund entfernen/verbessern, Spiegelungen, Farbkorrektur) → retouched image gespeichert. Preisvergleich: mobile.de Listings Scraper/API → comparable vehicles (brand, model, year, price) → Durchschnittspreis berechnet. Frontend: Retouch Upload page (Bild wählen, Retusche starten), Before/After Vergleich (slider), Preisvergleich view (Tabelle mit comparable listings + Durchschnittspreis)." ,
"assigned_subagent" : "implementation_engineer" ,
"dependencies" : [ "T01" , "T02" , "T05" ] ,
"requirement_ids" : [ "M8-F1" , "M8-F2" , "M8-F3" , "M8-F4" , "M8-F5" ] ,
"estimated_effort" : "L" ,
"estimated_lines" : 600 ,
"acceptance_criteria" : [
"POST /api/retouch/process mit image file → 202 + {retouch_id} (async processing)" ,
"POST /api/retouch/process ohne image → 422" ,
"POST /api/retouch/process mit invalid MIME → 422" ,
"GET /api/retouch/results/:id → 200 + {status, original_url, retouched_url}" ,
"GET /api/retouch/results/:id vor completion → 200 + {status: 'processing'}" ,
"Retouch Fehler (OpenRouter unavailable) → 200 + {status: 'failed', error: '...'}" ,
"POST /api/retouch/price-compare mit {vehicle_id} → 200 + {comparable_listings: [...], average_price: X}" ,
"POST /api/retouch/price-compare ohne vehicle_id → 422" ,
"Price-compare mit no comparable listings → 200 + {comparable_listings: [], average_price: null}" ,
"Frontend Retouch Upload → Bild auswählen + Retusche starten" ,
"Frontend Before/After Slider → vergleicht Original vs Retuschiert" ,
"Frontend Preisvergleich Tabelle → zeigt comparable listings + Durchschnittspreis" ,
"pytest coverage >= 80% für retouch module (mit mocked OpenRouter)"
] ,
"test_spec" : {
"commands" : [
"cd backend && python -m pytest tests/test_retouch.py --cov=app/services/retouch_service --cov=app/routers/image_retouch --cov-report=term-missing -v" ,
"cd frontend && npx vitest run tests/retouch.test.tsx --coverage"
] ,
"expected_results" : "All retouch tests pass with mocked OpenRouter. Process queues async task. Results retrievable with status. Price-compare returns listings + average. Frontend upload + before/after + price comparison render. Coverage >= 80% backend, >= 70% frontend." ,
"test_files" : [
"backend/tests/test_retouch.py" ,
"frontend/tests/retouch.test.tsx"
] ,
"coverage_target" : 80
} ,
"files_to_create" : [
"backend/app/models/retouch.py" ,
"backend/app/schemas/retouch.py" ,
"backend/app/routers/image_retouch.py" ,
"backend/app/services/retouch_service.py" ,
"backend/app/services/price_compare_service.py" ,
"backend/app/tasks/retouch_processing.py" ,
"backend/tests/test_retouch.py" ,
"frontend/app/retouch/page.tsx" ,
"frontend/components/retouch/RetouchUpload.tsx" ,
"frontend/components/retouch/BeforeAfterSlider.tsx" ,
"frontend/components/retouch/PriceComparison.tsx" ,
"frontend/tests/retouch.test.tsx"
]
}
] ,
"dependency_graph" : {
"T01" : [ ] ,
"T02" : [ "T01" ] ,
"T03" : [ "T01" , "T02" ] ,
"T04" : [ "T01" ] ,
"T05" : [ "T01" , "T02" ] ,
"T06" : [ "T02" , "T04" ] ,
"T07" : [ "T01" , "T02" ] ,
"T08" : [ "T01" , "T02" , "T05" ]
} ,
"execution_order" : [ "T01" , "T02" , "T04" , "T03" , "T05" , "T06" , "T07" , "T08" ] ,
"summary" : {
"total_tasks" : 8 ,
"tasks_with_test_spec" : 8 ,
"tasks_with_acceptance_criteria" : 8 ,
"tasks_with_dependencies" : 8 ,
"total_requirement_ids" : 45 ,
"total_acceptance_criteria" : 115 ,
"total_files_to_create" : 120 ,
"estimated_total_lines" : 5000
}
}