feat(T06): Verkaufsmodul + Rechtsdokumente + DATEV-Export + Sales UI
This commit is contained in:
+87
-28
@@ -1,44 +1,103 @@
|
||||
# Test Report - T01: Auth + User Management + RBAC + Base Frontend Layout + i18n
|
||||
# Test Report - T06: Verkaufsmodul + Rechtsdokumente + DATEV-Export + Sales UI
|
||||
|
||||
## Backend Tests
|
||||
|
||||
**Command**: `cd backend && python -m pytest tests/ --cov=app --cov-report=term-missing -v`
|
||||
**Command:**
|
||||
```
|
||||
cd backend && python -m pytest tests/test_sales.py tests/test_datev.py --cov=app --cov-report=term-missing -v
|
||||
```
|
||||
|
||||
**Result**: 50 passed in 20.40s
|
||||
**Result:** 34 passed in 11.42s
|
||||
|
||||
### Coverage
|
||||
| Module | Stmts | Miss | Cover |
|
||||
|--------|-------|------|-------|
|
||||
| app/routers/auth.py | 24 | 0 | 100% |
|
||||
| app/routers/users.py | 35 | 1 | 97% |
|
||||
| app/services/auth_service.py | 86 | 4 | 95% |
|
||||
| **TOTAL** | 359 | 25 | 93% |
|
||||
### Test Breakdown
|
||||
|
||||
### Test Files
|
||||
- `tests/test_health.py` (3 tests): health check, no-auth, root endpoint
|
||||
- `tests/test_auth.py` (12 tests): login valid/invalid/inactive/nonexistent, refresh valid/invalid/access-rejected, me with/without/invalid/refresh token
|
||||
- `tests/test_users.py` (15 tests): list admin/non-admin/no-auth, pagination, create admin/non-admin/duplicate/short-pw, update admin/nonexistent, delete soft/nonexistent/non-admin, password hash exclusion
|
||||
- `tests/test_auth_service.py` (20 tests): hash/verify, get_by_email/id found/notfound, authenticate valid/wrong/inactive/nonexistent, token pair, refresh valid/invalid/nonexistent, create success/duplicate, list pagination, update success/notfound/role, deactivate success/notfound
|
||||
#### test_sales.py (20 tests)
|
||||
- TestSaleCRUD::test_list_sales_empty ✅
|
||||
- TestSaleCRUD::test_create_sale ✅
|
||||
- TestSaleCRUD::test_create_sale_without_vehicle_id ✅ (422)
|
||||
- TestSaleCRUD::test_create_sale_without_buyer_contact_id ✅ (422)
|
||||
- TestSaleCRUD::test_get_sale_by_id ✅ (nested vehicle + buyer)
|
||||
- TestSaleCRUD::test_get_sale_not_found ✅ (404)
|
||||
- TestSaleCRUD::test_update_sale ✅
|
||||
- TestSaleCRUD::test_delete_sale_cancels_and_restores_vehicle ✅
|
||||
- TestSaleCRUD::test_list_sales_with_filter ✅ (status filter)
|
||||
- TestSaleCRUD::test_list_sales_with_date_filter ✅ (date range)
|
||||
- TestSaleVehicleStatus::test_create_sale_sets_vehicle_sold ✅
|
||||
- TestSaleVehicleStatus::test_cancel_sale_restores_vehicle_available ✅
|
||||
- TestContractPDF::test_regenerate_contract ✅
|
||||
- TestContractPDF::test_download_contract_not_found ✅ (404)
|
||||
- TestContractPDF::test_download_contract_pdf ✅ (application/pdf)
|
||||
- TestContractPDF::test_gwg_clause_in_contract_html ✅ (GwG bei <=800EUR)
|
||||
- TestContractPDF::test_gwg_clause_not_in_contract_when_price_too_high ✅
|
||||
- TestContractPDF::test_gwg_clause_not_in_contract_when_not_gwg ✅
|
||||
- TestContractPDF::test_contract_html_contains_ust_id_field ✅
|
||||
- TestUstIdVerification::test_verify_ust_id_disabled ✅ (BZSt API not available)
|
||||
|
||||
#### test_datev.py (14 tests)
|
||||
- TestDATEVExportAPI::test_create_export ✅ (201)
|
||||
- TestDATEVExportAPI::test_create_export_invalid_date_range ✅ (422)
|
||||
- TestDATEVExportAPI::test_list_exports ✅
|
||||
- TestDATEVExportAPI::test_download_export_csv ✅ (text/csv)
|
||||
- TestDATEVExportAPI::test_download_export_not_found ✅ (404)
|
||||
- TestDATEVCSVFormat::test_datev_csv_headers ✅
|
||||
- TestDATEVCSVFormat::test_generate_datev_csv_empty ✅
|
||||
- TestDATEVCSVFormat::test_generate_datev_csv_with_sales ✅
|
||||
- TestDATEVCSVFormat::test_validate_datev_csv_invalid_headers ✅
|
||||
- TestDATEVCSVFormat::test_validate_datev_csv_empty ✅
|
||||
- TestDATEVCSVFormat::test_validate_datev_csv_valid ✅
|
||||
- TestDATEVCSVFormat::test_datev_csv_amount_format ✅ (comma separator)
|
||||
- TestDATEVExportService::test_create_export_no_sales_in_range ✅
|
||||
- TestDATEVExportService::test_list_exports_pagination ✅
|
||||
|
||||
### Coverage (T06 modules)
|
||||
- app/models/sale.py: 94%
|
||||
- app/models/datev_export.py: 89%
|
||||
- app/schemas/sale.py: 100%
|
||||
- app/schemas/datev.py: 100%
|
||||
- app/routers/sales.py: 65%
|
||||
- app/routers/datev.py: 76%
|
||||
- app/services/sale_service.py: 43%
|
||||
- app/services/datev_service.py: 76%
|
||||
- app/utils/contract_pdf.py: 75%
|
||||
- app/utils/datev.py: 88%
|
||||
|
||||
## Frontend Tests
|
||||
|
||||
**Command**: `cd frontend && npx vitest run`
|
||||
**Command:**
|
||||
```
|
||||
cd frontend && npx vitest run tests/sales.test.tsx tests/datev.test.tsx
|
||||
```
|
||||
|
||||
**Result**: 16 passed in 2.15s
|
||||
**Result:** 16 passed in 1.85s
|
||||
|
||||
### Test Files
|
||||
- `tests/auth.test.tsx` (10 tests): Button render/loading/click, Input label/error, Card title/children, Toast display, i18n German/English/locale-switch
|
||||
- `tests/i18n.test.tsx` (6 tests): de.json ≥20 keys, en.json ≥20 keys, matching keys, translation function, parameter interpolation, fallback for unknown keys
|
||||
### Test Breakdown
|
||||
|
||||
## TypeScript Check
|
||||
#### sales.test.tsx (11 tests)
|
||||
- SaleList > renders sale list with title ✅
|
||||
- SaleList > displays sales in table ✅
|
||||
- SaleList > shows create button ✅
|
||||
- SaleList > has status filter ✅
|
||||
- SaleList > has date range filters ✅
|
||||
- SaleForm > renders form with required fields ✅
|
||||
- SaleForm > has GwG toggle checkbox ✅
|
||||
- SaleForm > has submit button ✅
|
||||
- ContractPreview > shows empty state when no PDF path ✅
|
||||
- ContractPreview > shows regenerate button ✅
|
||||
- ContractPreview > shows iframe when PDF path exists ✅
|
||||
|
||||
**Command**: `cd frontend && npx tsc --noEmit`
|
||||
|
||||
**Result**: Exit 0, no errors
|
||||
#### datev.test.tsx (5 tests)
|
||||
- DatevExport > renders DATEV export page with title ✅
|
||||
- DatevExport > has date range inputs ✅
|
||||
- DatevExport > has create export button ✅
|
||||
- DatevExport > shows empty state when no exports ✅
|
||||
- DatevExport > displays exports in table ✅
|
||||
|
||||
## Smoke Test
|
||||
|
||||
- Backend: FastAPI app starts, health endpoint returns {"status":"ok"}, login endpoint accepts credentials and returns JWT tokens
|
||||
- Frontend: Login page renders with email/password inputs and submit button, Toast notifications work on error, i18n switches between DE/EN live
|
||||
- Database: PostgreSQL test DB (erp_test) created, tables auto-created/dropped per test, all async operations work correctly
|
||||
- Auth: bcrypt password hashing works, JWT access (15min) + refresh (7d) tokens generated and verified, RBAC enforces admin-only on /users endpoints
|
||||
- Backend: App starts, all endpoints respond correctly (200/201/404/422)
|
||||
- Frontend: Components render with mocked API, all test IDs present
|
||||
- GwG logic: Clause appears in contract HTML when is_gwg=true AND price <= 800 EUR
|
||||
- Vehicle status: Sale creation → vehicle.availability='sold', sale cancel → vehicle.availability='available'
|
||||
- DATEV CSV: Correct headers (Datum;Konto;Gegenkonto;Betrag;Belegfeld;Buchungstext), comma decimal separator
|
||||
- USt-IdNr. verify: Returns {verified: false, message: 'BZSt API not available'} when feature flag disabled
|
||||
- WeasyPrint: Installed and importable, async PDF generation via asyncio.to_thread
|
||||
|
||||
Reference in New Issue
Block a user