# Test Report - T06: Verkaufsmodul + Rechtsdokumente + DATEV-Export + Sales UI ## Backend Tests **Command:** ``` cd backend && python -m pytest tests/test_sales.py tests/test_datev.py --cov=app --cov-report=term-missing -v ``` **Result:** 34 passed in 11.42s ### Test Breakdown #### 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 tests/sales.test.tsx tests/datev.test.tsx ``` **Result:** 16 passed in 1.85s ### Test Breakdown #### 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 ✅ #### 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: 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