feat(T07): KI-Copilot with OpenRouter chat, voice input, action system, chat history
This commit is contained in:
+22
-43
@@ -1,52 +1,31 @@
|
||||
# Current Status
|
||||
|
||||
## T06: Verkaufsmodul + Rechtsdokumente + DATEV-Export + Sales UI
|
||||
## T07: KI-Copilot (Text + Sprache) + Systemsteuerung + Copilot UI
|
||||
|
||||
**Status:** COMPLETED
|
||||
|
||||
### Backend
|
||||
- ✅ Sale model (app/models/sale.py) - UUID PK, vehicle_id FK, buyer_contact_id FK, seller_contact_id FK nullable, sale_price DECIMAL, sale_date, status enum, is_gwg BOOLEAN, contract_pdf_path
|
||||
- ✅ DATEVExport model (app/models/datev_export.py) - UUID PK, start_date, end_date, file_path, total_amount, created_at
|
||||
- ✅ Sale schemas (app/schemas/sale.py) - SaleCreate, SaleUpdate, SaleResponse, SaleListResponse, ContractResponse, UstIdVerifyResponse
|
||||
- ✅ DATEV schemas (app/schemas/datev.py) - DATEVExportCreate, DATEVExportResponse, DATEVExportListResponse
|
||||
- ✅ Sale service (app/services/sale_service.py) - create_sale, get_sale, list_sales, update_sale, cancel_sale, delete_sale, regenerate_contract_pdf, verify_ust_id
|
||||
- ✅ DATEV service (app/services/datev_service.py) - create_export, list_exports, get_export_csv
|
||||
- ✅ Contract PDF utils (app/utils/contract_pdf.py) - HTML template with WeasyPrint, GwG-Klausel, USt-IdNr. field, async via asyncio.to_thread
|
||||
- ✅ DATEV CSV utils (app/utils/datev.py) - Buchungsstapel format: Datum, Konto, Gegenkonto, Betrag, Belegfeld, Buchungstext
|
||||
- ✅ Sales router (app/routers/sales.py) - GET/POST/PUT/DELETE /sales, POST/GET /sales/:id/contract, POST /sales/:id/verify-ust-id
|
||||
- ✅ DATEV router (app/routers/datev.py) - POST /datev/export, GET /datev/exports, GET /datev/exports/:id/download
|
||||
- ✅ Config updated - BZST_API_ENABLED=False, WEASYPRINT_OUTPUT_DIR
|
||||
- ✅ main.py updated - sales + datev routers registered
|
||||
- ✅ requirements.txt - weasyprint>=62.0 added
|
||||
- ✅ models/__init__.py - all models imported for Base.metadata registration
|
||||
- ✅ Backend tests (tests/test_sales.py, tests/test_datev.py) - 34 tests, all passing
|
||||
- [x] models/copilot.py — CopilotSession, CopilotChat models
|
||||
- [x] schemas/copilot.py — ChatRequest, ChatResponse, ActionRequest, ActionResponse, ChatHistoryResponse, VoiceRequest, VoiceResponse
|
||||
- [x] routers/copilot.py — POST /chat, POST /action, GET /history, POST /voice
|
||||
- [x] services/copilot_service.py — chat, execute_action, get_history, get_sessions, transcribe_audio, voice_chat
|
||||
- [x] utils/copilot_actions.py — 5 actions: search_vehicles, search_contacts, get_sale_overview, create_vehicle, create_contact
|
||||
- [x] utils/copilot_prompt.py — System prompt with ERP context and action definitions
|
||||
- [x] tests/test_copilot.py — 28 endpoint+unit tests
|
||||
- [x] tests/test_copilot_coverage.py — 20 service-level coverage tests
|
||||
- [x] main.py — copilot router registered
|
||||
|
||||
### Frontend
|
||||
- ✅ Sales lib (lib/sales.ts) - listSales, getSale, createSale, updateSale, deleteSale, regenerateContract, verifyUstId
|
||||
- ✅ DATEV lib (lib/datev.ts) - createDatevExport, listDatevExports, getDatevDownloadUrl
|
||||
- ✅ SaleList component - Sales table with status + date range filters, pagination
|
||||
- ✅ SaleForm component - Sale create form with vehicle select, buyer input, price, GwG toggle
|
||||
- ✅ ContractPreview component - PDF embed preview, regenerate button, download link
|
||||
- ✅ DatevExport component - Date range picker, export list table, CSV download
|
||||
- ✅ Pages: verkauf/page.tsx, verkauf/[id]/page.tsx, verkauf/neu/page.tsx
|
||||
- ✅ Frontend tests (tests/sales.test.tsx, tests/datev.test.tsx) - 16 tests, all passing
|
||||
- [x] lib/copilot.ts — API client functions
|
||||
- [x] app/[locale]/ki-copilot/page.tsx — Copilot page
|
||||
- [x] components/copilot/ChatInterface.tsx — Main chat interface
|
||||
- [x] components/copilot/MessageList.tsx — Message list
|
||||
- [x] components/copilot/ChatInput.tsx — Text input
|
||||
- [x] components/copilot/VoiceInput.tsx — Voice input (Web Speech API)
|
||||
- [x] components/copilot/ActionPreview.tsx — Action preview before execution
|
||||
- [x] components/copilot/ChatHistory.tsx — Chat history sidebar
|
||||
- [x] tests/copilot.test.tsx — 24 frontend tests
|
||||
|
||||
### Acceptance Criteria Met
|
||||
- ✅ GET /api/v1/sales → 200 + paginated list with filter (date range, status)
|
||||
- ✅ GET /api/v1/sales/:id → 200 + sale detail with vehicle + contact nested
|
||||
- ✅ POST /api/v1/sales mit valid data → 201 + sale object
|
||||
- ✅ POST /api/v1/sales ohne vehicle_id → 422
|
||||
- ✅ POST /api/v1/sales ohne buyer_contact_id → 422
|
||||
- ✅ PUT /api/v1/sales/:id → 200 + updated sale
|
||||
- ✅ DELETE /api/v1/sales/:id → 200 (sale cancelled, vehicle status back to available)
|
||||
- ✅ POST /api/v1/sales/:id/contract → 200 + regenerated contract PDF path
|
||||
- ✅ GET /api/v1/sales/:id/contract → 200 + PDF content (application/pdf)
|
||||
- ✅ Sale mit is_gwg=true und sale_price <= 800 → GwG-Klausel in contract
|
||||
- ✅ POST /api/v1/sales/:id/verify-ust-id → 200 + {verified: false, message: 'BZSt API not available'}
|
||||
- ✅ POST /api/v1/datev/export mit date range → 201 + DATEVExport object
|
||||
- ✅ POST /api/v1/datev/export mit invalid date range → 422
|
||||
- ✅ GET /api/v1/datev/exports → 200 + list of exports
|
||||
- ✅ GET /api/v1/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='available' (in_stock)
|
||||
### Test Results
|
||||
- Backend: 48 passed, 90% coverage (exceeds 80% requirement)
|
||||
- Frontend: 24 passed
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
# Known Errors
|
||||
|
||||
## T07: KI-Copilot
|
||||
|
||||
No known errors. All tests pass.
|
||||
|
||||
### Notes
|
||||
- OpenRouter API key not configured in test environment — tests mock _call_openrouter_chat
|
||||
- Voice transcription falls back to stub message when OPENROUTER_API_KEY is empty
|
||||
- Frontend act() warnings in ChatHistory tests are non-blocking (React state update in async useEffect)
|
||||
+9
-8
@@ -1,12 +1,13 @@
|
||||
# Next Steps
|
||||
|
||||
## T05: COMPLETED
|
||||
## T07: KI-Copilot — COMPLETED
|
||||
|
||||
All acceptance criteria for T05 (Dateiablage pro Fahrzeug + File UI) have been met.
|
||||
All acceptance criteria met. No blockers.
|
||||
|
||||
## Recommended Next Actions
|
||||
1. Integrate FileUpload and FileList components into VehicleDetail page
|
||||
2. Add FileGallery to vehicle detail page for image gallery view
|
||||
3. Consider adding file metadata endpoint (GET /vehicles/:id/files/:fileId/meta) for frontend to fetch metadata without downloading
|
||||
4. Add file count to vehicle list response for quick display
|
||||
5. Consider adding file type filtering in FileList (images only, documents only)
|
||||
### Potential Follow-up Tasks
|
||||
- Integration test with real OpenRouter API (requires API key configuration)
|
||||
- Voice transcription with real audio (currently stub when no API key)
|
||||
- Frontend E2E tests with Playwright
|
||||
- Copilot settings panel (model selection, temperature)
|
||||
- Action result rendering in chat (show vehicle/contact search results inline)
|
||||
- Multi-language support for system prompt
|
||||
|
||||
+36
-50
@@ -1,55 +1,41 @@
|
||||
# Worklog
|
||||
|
||||
## T06: Verkaufsmodul + Rechtsdokumente + DATEV-Export + Sales UI
|
||||
## T07: KI-Copilot — 2026-07-17
|
||||
|
||||
**Date:** 2026-07-17
|
||||
**Status:** COMPLETED
|
||||
### Implemented
|
||||
- Backend: CopilotSession + CopilotChat models with UUID PKs, user FK, JSONB actions
|
||||
- Backend: Copilot service with OpenRouter chat completions, action proposal/execution system
|
||||
- Backend: System prompt with ERP context (vehicle types, contact types, sales workflow) and 5 available actions
|
||||
- Backend: Action registry — search_vehicles, search_contacts, get_sale_overview, create_vehicle, create_contact
|
||||
- Backend: Voice endpoint with audio transcription (OpenRouter or stub fallback)
|
||||
- Backend: Paginated chat history per user, filterable by session_id
|
||||
- Backend: Router registered in main.py under /api/v1/copilot
|
||||
- Frontend: Full chat interface with message list, text input, voice input, action preview, chat history sidebar
|
||||
- Frontend: Web Speech API integration for voice recording via MediaRecorder
|
||||
- Frontend: Action confirmation flow — Copilot proposes, user confirms/dismisses
|
||||
|
||||
### Files Created
|
||||
### Test Evidence
|
||||
- Backend: 48 tests passed, 90% coverage on copilot_service + copilot router
|
||||
- Frontend: 24 tests passed covering all components
|
||||
- OpenRouter fully mocked in all tests
|
||||
|
||||
#### Backend
|
||||
- backend/app/models/sale.py - Sale model with UUID PK, vehicle/buyer/seller FKs, sale_price, status, is_gwg, contract_pdf_path
|
||||
- backend/app/models/datev_export.py - DATEVExport model with start_date, end_date, file_path, total_amount
|
||||
- backend/app/schemas/sale.py - SaleCreate, SaleUpdate, SaleResponse, SaleListResponse, ContractResponse, UstIdVerifyResponse
|
||||
- backend/app/schemas/datev.py - DATEVExportCreate, DATEVExportResponse, DATEVExportListResponse
|
||||
- backend/app/services/sale_service.py - Full CRUD + contract PDF + GwG logic + USt-IdNr. verification
|
||||
- backend/app/services/datev_service.py - Export creation, listing, CSV download
|
||||
- backend/app/utils/contract_pdf.py - HTML template with WeasyPrint, GwG-Klausel §6 Abs. 2 EStG, USt-IdNr. field
|
||||
- backend/app/utils/datev.py - DATEV CSV Buchungsstapel format helper
|
||||
- backend/app/routers/sales.py - Sales CRUD + contract + USt-IdNr. endpoints
|
||||
- backend/app/routers/datev.py - DATEV export + list + download endpoints
|
||||
- backend/tests/test_sales.py - 20 tests covering CRUD, contract PDF, GwG, vehicle status, USt-IdNr.
|
||||
- backend/tests/test_datev.py - 14 tests covering export API, CSV format, validation
|
||||
|
||||
#### Frontend
|
||||
- frontend/lib/sales.ts - Sales API client functions and types
|
||||
- frontend/lib/datev.ts - DATEV API client functions and types
|
||||
- frontend/components/sales/SaleList.tsx - Sales table with filters and pagination
|
||||
- frontend/components/sales/SaleForm.tsx - Sale create form with GwG toggle
|
||||
- frontend/components/sales/ContractPreview.tsx - PDF preview with regenerate/download
|
||||
- frontend/components/sales/DatevExport.tsx - DATEV export page with date range picker
|
||||
- frontend/app/[locale]/verkauf/page.tsx - Sales list page
|
||||
- frontend/app/[locale]/verkauf/[id]/page.tsx - Sale detail with contract preview
|
||||
- frontend/app/[locale]/verkauf/neu/page.tsx - Sale create page
|
||||
- frontend/tests/sales.test.tsx - 11 frontend tests
|
||||
- frontend/tests/datev.test.tsx - 5 frontend tests
|
||||
|
||||
### Files Modified
|
||||
- backend/app/config.py - Added BZST_API_ENABLED=False, WEASYPRINT_OUTPUT_DIR
|
||||
- backend/app/main.py - Registered sales + datev routers
|
||||
- backend/app/models/__init__.py - Added sale + datev_export imports for Base.metadata registration
|
||||
- backend/requirements.txt - Added weasyprint>=62.0
|
||||
|
||||
### Test Results
|
||||
- Backend: 34/34 passed (11.42s)
|
||||
- Frontend: 16/16 passed (1.85s)
|
||||
- Total: 50/50 passed
|
||||
|
||||
### Smoke Test
|
||||
- Backend: All endpoints respond correctly (200/201/404/422)
|
||||
- GwG logic: Clause appears when is_gwg=true AND price <= 800 EUR (§6 Abs. 2 EStG)
|
||||
- Vehicle status: Sale creation → 'sold', sale cancel → 'available'
|
||||
- DATEV CSV: Correct headers, comma decimal separator, DD.MM.YYYY date format
|
||||
- USt-IdNr. verify: Returns 'BZSt API not available' when feature flag disabled
|
||||
- WeasyPrint: Installed, async PDF generation via asyncio.to_thread
|
||||
- Frontend: All components render with mocked API, test IDs present
|
||||
### Files Changed
|
||||
- backend/app/models/copilot.py (new)
|
||||
- backend/app/schemas/copilot.py (new)
|
||||
- backend/app/routers/copilot.py (new)
|
||||
- backend/app/services/copilot_service.py (new)
|
||||
- backend/app/utils/copilot_actions.py (new)
|
||||
- backend/app/utils/copilot_prompt.py (new)
|
||||
- backend/app/main.py (modified — added copilot router import + registration)
|
||||
- backend/tests/test_copilot.py (new)
|
||||
- backend/tests/test_copilot_coverage.py (new)
|
||||
- frontend/lib/copilot.ts (new)
|
||||
- frontend/app/[locale]/ki-copilot/page.tsx (new)
|
||||
- frontend/components/copilot/ChatInterface.tsx (new)
|
||||
- frontend/components/copilot/MessageList.tsx (new)
|
||||
- frontend/components/copilot/ChatInput.tsx (new)
|
||||
- frontend/components/copilot/VoiceInput.tsx (new)
|
||||
- frontend/components/copilot/ActionPreview.tsx (new)
|
||||
- frontend/components/copilot/ChatHistory.tsx (new)
|
||||
- frontend/tests/copilot.test.tsx (new)
|
||||
- test_report.md (new)
|
||||
|
||||
Reference in New Issue
Block a user