Files
erp-nutzfahrzeuge/.a0/worklog.md
T

146 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Worklog - ERP Nutzfahrzeuge
## 2026-07-13
- Phase 1 (Discovery + UI Design): Abgeschlossen
- requirements.md erstellt (703 Zeilen)
- UI-Prototyp v8d erstellt und auf webspace.media-on.de gepublished
- component_inventory.md erstellt
- Phase 2 (Architektur): Abgeschlossen
- architecture.md erstellt (1162 Zeilen, 14 ADRs)
- task_graph.json erstellt (8 Tasks T01-T08)
- AGENTS.md erstellt
- Git: 2 Commits auf main (afe6d0a, be5a339), auf Forgejo gepusht
- .gitignore erstellt
- Bereit für Phase 3 (Implementation), wartet auf User-Freigabe
## T01 Auth + User Management + RBAC + Frontend + i18n (2026-07-14)
### Backend
- config.py: Pydantic BaseSettings, alle Env-Vars (DATABASE_URL, REDIS_URL, JWT_SECRET, CORS_ORIGINS, etc.)
- database.py: Async SQLAlchemy engine, session factory, Base, init_db/drop_db
- models/user.py: User mit UUID PK, email, password_hash, role (Enum), language, is_active, timestamps
- schemas/user.py: LoginRequest, TokenResponse, RefreshRequest, UserCreate/Update/Response, UserListResponse
- utils/jwt.py: create_access_token, create_refresh_token, decode_token, verify_access/refresh_token
- services/auth_service.py: hash_password, verify_password, authenticate_user, generate_token_pair, refresh_access_token, create_user, list_users, update_user, deactivate_user
- dependencies.py: get_pagination, get_current_user (JWT extraction), require_role (RBAC)
- routers/auth.py: POST /login, POST /refresh, GET /me
- routers/users.py: GET / (list paginated), POST / (create), PUT /:id (update), DELETE /:id (soft-delete) alle admin-only
- main.py: FastAPI app, CORS middleware, /api/v1 prefix, /health endpoint
- tests/: conftest.py (async fixtures, PostgreSQL), test_auth.py (12 tests), test_users.py (14 tests), test_health.py (3 tests), test_auth_service.py (21 tests)
- requirements.txt, .env.example, pytest.ini, .coveragerc
### Frontend
- package.json, tsconfig.json, next.config.js, tailwind.config.ts, vitest.config.ts
- app/layout.tsx, app/page.tsx, app/globals.css (design tokens als CSS vars)
- app/(auth)/layout.tsx (I18nProvider + ToastProvider wrapper)
- app/(auth)/login/page.tsx (Login-Form mit Validation, API call, Toast on error)
- lib/api.ts (fetch wrapper mit auto-refresh, login, getCurrentUser, listUsers, createUser, deleteUser)
- lib/auth.ts (useAuth hook, useRequireAuth)
- lib/i18n.tsx (I18nProvider, useI18n, DE/EN translation)
- components/ui/: Button, Input, Card, Table, Modal, Toast (alle 6 Komponenten)
- messages/de.json (31 keys), messages/en.json (31 keys)
- tests/setup.ts, tests/auth.test.tsx (5 tests), tests/i18n.test.tsx (7 tests)
### Test Results
- Backend: 50/50 passed, 88% total coverage
- Frontend: 12/12 passed, Next.js build success
- test_report.md erstellt
## T02 Vehicle Management + mobile.de Push + Vehicle UI (2026-07-14)
### Backend
- models/vehicle.py: Vehicle + MobileDeListing models with UUID PK, soft-delete, all fields per spec
- schemas/vehicle.py: VehicleCreate/Update/Response/ListResponse, MobileDeStatusResponse, MobileDePushResponse with auto-compute power_hp
- utils/mobilede_mapping.py: map_fields() converts Vehicle to mobile.de Ad format
- services/vehicle_service.py: CRUD with pagination, filtering, sorting, soft-delete
- services/mobilede_service.py: push/update/delete listing, get status, retry (max 3)
- routers/vehicles.py: 7 endpoints (list, create, detail, update, delete, mobile-de push, mobile-de status)
- config.py: Added MOBILE_DE_API_KEY, MOBILE_DE_SELLER_ID
- main.py: Registered vehicles router
### Frontend
- lib/vehicles.ts: Full API client with typed interfaces
- components/vehicles/: VehicleList, VehicleForm, VehicleDetail, MobileDeStatus
- app/[locale]/fahrzeuge/: list page, neu (create) page, [id] detail page
- tests/vehicles.test.tsx: 16 tests
### Test Results
- Backend: 73/73 pytest passed, 82% total coverage
- Frontend: 16/16 vitest passed
- test_report.md updated
---
## T04: Kontakt-/Kundenverwaltung + Contact UI (2026-07-14)
### Backend
- models/contact.py: Contact + ContactPerson models with UUID PK, soft-delete, CHECK constraints for role/vat_id_status/country
- schemas/contact.py: ContactCreate/Update/Response/ListResponse + ContactPersonCreate/Response with VAT ID field_validator
- utils/ust_validation.py: DE + 10 EU country regex patterns, EU fallback, validate_vat_id, validate_vat_id_or_raise, get_country_code_from_vat_id
- services/contact_service.py: list_contacts (search, role filter with beide inclusion, is_eu filter, is_private filter, sort, pagination), get_contact_by_id, create_contact (with nested persons), update_contact, soft_delete_contact, add_contact_person, remove_contact_person
- routers/contacts.py: 7 endpoints (list, create, detail, update, delete, add person, remove person) with RBAC (all read, admin+verkaeufer write)
- main.py: Registered contacts router
### Frontend
- lib/contacts.ts: Full API client with typed interfaces + validateVatIdFormat frontend validation
- components/contacts/ContactList.tsx: Table with search, role filter, EU/Inland filter, sort, pagination
- components/contacts/ContactForm.tsx: Create/edit form with USt-IdNr. validation, EU/Inland toggle, country selector, role, legal form, address, contact info, is_private
- components/contacts/ContactDetail.tsx: Detail view with contact persons management (add/remove via Modal)
- app/[locale]/kontakte/: list page, neu (create) page, [id] detail page
- tests/contacts.test.tsx: 20 tests
### Test Results
- Backend: 73/73 pytest passed, 91% coverage on contact modules (service 99%, ust_validation 94%, models 93%, schemas 94%, router 67%)
- Frontend: 20/20 vitest passed
- test_report.md updated
---
## T01 Re-Implementation (2026-07-14)
### Backend
- app/config.py: Pydantic BaseSettings with DATABASE_URL, REDIS_URL, JWT_SECRET, JWT_ALGORITHM, JWT_ACCESS_TTL_MINUTES=15, JWT_REFRESH_TTL_DAYS=7, CORS_ORIGINS, UPLOAD_DIR
- app/database.py: Async SQLAlchemy engine, session factory, Base declarative, get_db dependency, init_db/drop_db helpers
- app/models/user.py: User model with UUID PK, email(unique), password_hash, full_name, role(enum admin/verkaeufer/buchhaltung), language(default de), is_active(default true), created_at, updated_at
- app/schemas/user.py: LoginRequest, TokenResponse, RefreshRequest, UserBase/Create/Update/Response/ListResponse, ErrorResponse, HealthResponse
- app/utils/jwt.py: create_access_token, create_refresh_token, decode_token, verify_access_token, verify_refresh_token (HS256, type claim separation)
- app/services/auth_service.py: hash_password (bcrypt), verify_password, get_user_by_email/id, authenticate_user, generate_token_pair, refresh_access_token, create_user, list_users (paginated), update_user, deactivate_user (soft delete)
- app/dependencies.py: get_pagination, get_current_user (JWT bearer extraction), require_role (RBAC factory)
- app/routers/auth.py: POST /login, POST /refresh, GET /me
- app/routers/users.py: GET / (admin only, paginated), POST / (admin only), PUT /:id (admin only), DELETE /:id (admin only, soft delete)
- app/main.py: FastAPI app with CORS, /api/v1 prefix, health endpoint, router registration
- tests/conftest.py: Function-scoped async engine, session, admin/verkaeufer/inactive user fixtures, token fixtures, HTTP client fixtures
- tests/test_health.py: 3 tests
- tests/test_auth.py: 12 tests (login valid/invalid/inactive/nonexistent/email-format, 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 direct service unit tests
- .env.example: All required env vars documented
- requirements.txt: fastapi, uvicorn, sqlalchemy[asyncio], asyncpg, pydantic-settings, python-jose, passlib[bcrypt], redis, python-multipart, pytest, pytest-asyncio, httpx, pytest-cov
### Frontend
- package.json: Next.js 14, React 18, next-intl, Tailwind, Vitest, Testing Library
- tsconfig.json, next.config.js, tailwind.config.ts, postcss.config.js, vitest.config.ts
- app/globals.css: Design tokens as CSS vars (primary, secondary, background, surface, text, error, success, border)
- app/layout.tsx: Root layout
- app/page.tsx: Redirect to /login
- app/(auth)/login/page.tsx: Login form with email/password, validation, Toast on error, i18n integration
- lib/api.ts: Fetch wrapper with auth header injection, token refresh, login, getCurrentUser, listUsers, createUser, deleteUser, healthCheck
- lib/auth.ts: useAuth hook (login, logout, fetchUser), useRequireAuth hook
- lib/i18n.tsx: I18nProvider, useI18n hook, locale switching, parameter interpolation
- components/ui/Button.tsx: Primary/secondary/danger/ghost variants, loading spinner
- components/ui/Input.tsx: Label, error display, forwardRef
- components/ui/Card.tsx: Title + children container
- components/ui/Table.tsx: Generic table with columns + data
- components/ui/Modal.tsx: Overlay modal with close button
- components/ui/Toast.tsx: ToastProvider, useToast hook, success/error/info/warning types
- messages/de.json: 28 keys (login, nav, common, user.role)
- messages/en.json: 28 keys (matching de.json)
- tests/setup.ts: localStorage mock, next/navigation mock
- tests/auth.test.tsx: 10 tests (Button, Input, Card, Toast, i18n DE/EN/switch)
- tests/i18n.test.tsx: 6 tests (key count ≥20, matching keys, translation, interpolation, fallback)
### Test Results
- Backend: 50/50 pytest passed, 93% total coverage (auth_service 95%, routers 98%)
- Frontend: 16/16 vitest passed
- TypeScript: tsc --noEmit exit 0
- test_report.md created