feat: initial architecture - requirements, architecture.md, task_graph, AGENTS.md, UI prototype v8d
This commit is contained in:
+412
@@ -0,0 +1,412 @@
|
||||
# AGENTS.md – ERP Nutzfahrzeuge Implementation Guide
|
||||
|
||||
**Version:** 1.0.0
|
||||
**Datum:** 2026-07-12
|
||||
|
||||
---
|
||||
|
||||
## 1. Project Overview
|
||||
|
||||
ERP-System für Nutzfahrzeug-/Baumaschinen-Handel (~10 Nutzer).
|
||||
- **Backend:** Python 3.12 / FastAPI / SQLAlchemy 2.0 async / PostgreSQL 16 / Redis 7
|
||||
- **Frontend:** Next.js 14 (App Router) / React 18 / TypeScript / Tailwind CSS / next-intl
|
||||
- **Hosting:** Coolify (Docker Compose) auf coolify-01 (46.225.91.159)
|
||||
- **KI:** OpenRouter (Qwen2.5-VL OCR, Flux.1-Pro Bild, Claude/GPT-4 Copilot)
|
||||
- **External:** mobile.de Seller API (Push-Only)
|
||||
|
||||
### Architecture Reference
|
||||
- `docs/architecture.md` – Complete architecture, DB schema, API design, ADRs
|
||||
- `docs/task_graph.json` – Task breakdown with test specs
|
||||
- `docs/requirements.md` – Full requirements (8 modules, 23 features)
|
||||
- `docs/component_inventory.md` – UI components and states
|
||||
|
||||
---
|
||||
|
||||
## 2. Build & Test Commands
|
||||
|
||||
### Backend
|
||||
```bash
|
||||
# Install dependencies
|
||||
cd backend
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Run dev server
|
||||
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
|
||||
|
||||
# Run all tests
|
||||
python -m pytest tests/ -v --cov=app --cov-report=term-missing --cov-report=html
|
||||
|
||||
# Run specific test file
|
||||
python -m pytest tests/test_vehicles.py -v
|
||||
|
||||
# Run with coverage for specific module
|
||||
python -m pytest tests/test_auth.py -v --cov=app/services/auth_service --cov-report=term-missing
|
||||
|
||||
# Lint
|
||||
ruff check app/
|
||||
ruff format app/ --check
|
||||
|
||||
# Database migrations
|
||||
alembic revision --autogenerate -m "description"
|
||||
alembic upgrade head
|
||||
alembic downgrade -1
|
||||
|
||||
# Type check (optional but recommended)
|
||||
mypy app/ --ignore-missing-imports
|
||||
```
|
||||
|
||||
### Frontend
|
||||
```bash
|
||||
cd frontend
|
||||
npm install
|
||||
|
||||
# Run dev server
|
||||
npm run dev
|
||||
|
||||
# Run all tests
|
||||
npx vitest run --coverage
|
||||
|
||||
# Run specific test
|
||||
npx vitest run src/components/vehicles --coverage
|
||||
|
||||
# Lint
|
||||
npx eslint src/ --max-warnings 0
|
||||
npx prettier --check src/
|
||||
|
||||
# Build
|
||||
npm run build
|
||||
|
||||
# Type check
|
||||
npx tsc --noEmit
|
||||
```
|
||||
|
||||
### Docker
|
||||
```bash
|
||||
# Build and start all services
|
||||
docker-compose up -d --build
|
||||
|
||||
# View logs
|
||||
docker-compose logs -f backend
|
||||
docker-compose logs -f frontend
|
||||
|
||||
# Run database migration in container
|
||||
docker-compose exec backend alembic upgrade head
|
||||
|
||||
# Run tests in container
|
||||
docker-compose exec backend python -m pytest tests/ -v
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Test Rules (MANDATORY)
|
||||
|
||||
### TDD Principle
|
||||
- **Write tests first or alongside implementation** – never after
|
||||
- Every PR must include tests
|
||||
- Coverage target: **≥80%** per module
|
||||
|
||||
### Do NOT Modify Existing Tests
|
||||
- Tests are written by the task spec and must not be modified to make them pass
|
||||
- If a test fails, fix the **implementation**, not the test
|
||||
- Exception: test data fixtures can be extended, but existing assertions must not be weakened
|
||||
|
||||
### Backend Test Conventions
|
||||
- **Framework:** pytest + pytest-asyncio + httpx.AsyncClient
|
||||
- **Test DB:** Separate PostgreSQL database `erp_test` (NOT SQLite)
|
||||
- **Fixtures:** `conftest.py` provides:
|
||||
- `async_db` – async SQLAlchemy session (rolled back after each test)
|
||||
- `client` – httpx AsyncClient with app
|
||||
- `auth_headers` – JWT headers for admin/verkaeufer/buchhaltung roles
|
||||
- `seed_data` – minimal seed data (users, vehicle, contact)
|
||||
- **Mocking:** OpenRouter API MUST be mocked in all tests (no real API calls)
|
||||
- **Naming:** `test_<feature>_<scenario>.py` or `test_<module>.py`
|
||||
|
||||
### Frontend Test Conventions
|
||||
- **Framework:** Vitest + React Testing Library
|
||||
- **E2E:** Playwright for critical paths (login, vehicle create, sale wizard)
|
||||
- **Mocking:** API calls mocked via `vi.mock()` or MSW (Mock Service Worker)
|
||||
- **Naming:** `ComponentName.test.tsx` in `__tests__/` folder
|
||||
|
||||
### Test Spec Compliance
|
||||
Every task in `task_graph.json` has a `test_spec` with:
|
||||
- `commands` – Exact commands to run
|
||||
- `expected_results` – What success looks like
|
||||
- `test_files` – Expected test file paths
|
||||
- `coverage_target` – Minimum coverage percentage
|
||||
|
||||
**ALL commands in test_spec.commands MUST pass before a task is considered done.**
|
||||
|
||||
---
|
||||
|
||||
## 4. Code Conventions
|
||||
|
||||
### Python (Backend)
|
||||
```python
|
||||
# Naming
|
||||
snake_case for variables, functions, methods, modules
|
||||
PascalCase for classes (Models, Schemas, Services)
|
||||
UPPER_SNAKE_CASE for constants
|
||||
|
||||
# Imports (ruff isort)
|
||||
# Standard library
|
||||
import os
|
||||
from datetime import datetime
|
||||
# Third party
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
# Local
|
||||
from app.deps import get_db, get_current_user
|
||||
from app.models.vehicle import Vehicle
|
||||
from app.schemas.vehicle import VehicleCreate, VehicleResponse
|
||||
|
||||
# Type hints (mandatory)
|
||||
async def get_vehicle(vehicle_id: UUID, db: AsyncSession) -> Vehicle:
|
||||
...
|
||||
|
||||
# Async everywhere (SQLAlchemy 2.0 async)
|
||||
result = await db.execute(select(Vehicle).where(Vehicle.id == vehicle_id))
|
||||
vehicle = result.scalar_one_or_none()
|
||||
|
||||
# Error handling
|
||||
if vehicle is None:
|
||||
raise HTTPException(status_code=404, detail={"error": {"code": "NOT_FOUND", "message": "Vehicle not found"}})
|
||||
```
|
||||
|
||||
### TypeScript (Frontend)
|
||||
```typescript
|
||||
// Naming
|
||||
camelCase for variables, functions, hooks
|
||||
PascalCase for components, types, interfaces
|
||||
UPPER_SNAKE_CASE for constants
|
||||
|
||||
// Imports order
|
||||
// 1. React/Next
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
// 2. Third party
|
||||
import { useTranslations } from 'next-intl';
|
||||
// 3. Local
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { apiClient } from '@/lib/api-client';
|
||||
|
||||
// Components: function declaration with explicit return type
|
||||
export function FahrzeugListe(): JSX.Element {
|
||||
...
|
||||
}
|
||||
|
||||
// Types: interface for props
|
||||
type FahrzeugListeProps = {
|
||||
vehicles: Vehicle[];
|
||||
isLoading: boolean;
|
||||
};
|
||||
```
|
||||
|
||||
### File Organization
|
||||
- **One model per file** in `models/`
|
||||
- **One router per module** in `routers/`
|
||||
- **One service per domain** in `services/`
|
||||
- **One schema set per module** in `schemas/`
|
||||
- **Components grouped by feature** in `components/<feature>/`
|
||||
|
||||
---
|
||||
|
||||
## 5. Forbidden Patterns
|
||||
|
||||
### Backend
|
||||
- ❌ **No raw SQL queries** – always use SQLAlchemy ORM
|
||||
- ❌ **No synchronous database calls** – always async (`await db.execute(...)`)
|
||||
- ❌ **No secrets in code** – use environment variables / pydantic-settings
|
||||
- ❌ **No `print()` in production code** – use Python `logging`
|
||||
- ❌ **No bare `except:`** – always catch specific exceptions
|
||||
- ❌ **No `# type: ignore`** without comment explaining why
|
||||
- ❌ **No circular imports** – use dependency injection
|
||||
- ❌ **No business logic in routers** – routers only validate + call service
|
||||
- ❌ **No direct model access from routers** – always go through service layer
|
||||
- ❌ **No unencrypted PII** – Ausweisdaten MUST be AES-256 encrypted
|
||||
- ❌ **No real OpenRouter API calls in tests** – always mock
|
||||
- ❌ **No `commit()` in services without explicit reason** – let caller control transactions
|
||||
|
||||
### Frontend
|
||||
- ❌ **No `any` type** – use proper TypeScript types
|
||||
- ❌ **No `console.log` in production** – use a logger utility
|
||||
- ❌ **No inline styles** – use Tailwind classes or CSS modules
|
||||
- ❌ **No direct `fetch()` without auth wrapper** – use `apiClient`
|
||||
- ❌ **No hardcoded API URLs** – use `NEXT_PUBLIC_API_URL` env var
|
||||
- ❌ **No hardcoded translation strings** – use `t('key')` from next-intl
|
||||
- ❌ **No prop drilling > 2 levels** – use context or state management
|
||||
- ❌ **No `useEffect` for data fetching without loading/error states**
|
||||
- ❌ **No forms without validation** – all inputs must have validation
|
||||
- ❌ **No missing `aria-label`** on icon-only buttons
|
||||
|
||||
### General
|
||||
- ❌ **No commits to main without passing tests**
|
||||
- ❌ **No large PRs** – max 800 lines per task
|
||||
- ❌ **No TODO comments without ticket reference**
|
||||
- ❌ **No commented-out code in PRs**
|
||||
- ❌ **No files > 500 lines** – split into modules
|
||||
|
||||
---
|
||||
|
||||
## 6. Token Rule for File Operations
|
||||
|
||||
When working with files (reading, creating, updating):
|
||||
|
||||
### Backend (Forgejo API)
|
||||
```json
|
||||
// READ file (only for MODIFY, not for reference)
|
||||
{"tool_name":"forgejo","tool_args":{"action":"files_get","owner":"Leopoldadmin","repo":"erp-nutzfahrzeuge","path":"backend/app/models/vehicle.py"}}
|
||||
|
||||
// CREATE new file
|
||||
{"tool_name":"forgejo","tool_args":{"action":"files_create","owner":"Leopoldadmin","repo":"erp-nutzfahrzeuge","path":"backend/app/models/vehicle.py","content":"<content>","message":"Add vehicle model","branch":"main"}}
|
||||
|
||||
// UPDATE existing file (requires SHA from files_get)
|
||||
{"tool_name":"forgejo","tool_args":{"action":"files_update","owner":"Leopoldadmin","repo":"erp-nutzfahrzeuge","path":"backend/app/models/vehicle.py","content":"<updated content>","sha":"<SHA>","message":"Update vehicle model","branch":"main"}}
|
||||
|
||||
// CHECK file existence
|
||||
{"tool_name":"forgejo","tool_args":{"action":"files_list","owner":"Leopoldadmin","repo":"erp-nutzfahrzeuge","path":"backend/app/models/"}}
|
||||
```
|
||||
|
||||
### Rules
|
||||
- Use `files_get` ONLY when you need to modify an existing file (need SHA)
|
||||
- Use `files_create` for new files
|
||||
- Use `files_list` to check existence before creating
|
||||
- **NEVER** copy file contents inline in task descriptions – reference by path
|
||||
- **NEVER** read entire files just for reference – use `curl + sed` for snippets
|
||||
- For large reference content (architecture.md, requirements.md): reference by path, don't inline
|
||||
|
||||
---
|
||||
|
||||
## 7. Task Execution Workflow
|
||||
|
||||
### For implementation_engineer
|
||||
|
||||
1. **Read the task** from `task_graph.json` (task ID: T0X)
|
||||
2. **Read architecture.md** sections relevant to the task (DB schema, API design, ADRs)
|
||||
3. **Read requirements.md** for the specific feature IDs listed in `requirement_ids`
|
||||
4. **Implement backend first:** Model → Schema → Service → Router → Tests
|
||||
5. **Implement frontend:** Components → Pages → Tests
|
||||
6. **Run ALL test_spec.commands** and ensure they pass
|
||||
7. **Run lint** (ruff for backend, eslint for frontend)
|
||||
8. **Run build** (npm run build for frontend)
|
||||
9. **Report results** with test output evidence (not just "done")
|
||||
|
||||
### Evidence Requirements (MANDATORY)
|
||||
- Test command output showing pass/fail counts
|
||||
- Coverage report showing ≥80%
|
||||
- Lint output showing 0 errors
|
||||
- Build output showing success
|
||||
- "File written" is NOT evidence. "Commit made" is NOT evidence.
|
||||
- Test output with pass counts IS evidence.
|
||||
|
||||
### Task Completion Checklist
|
||||
- [ ] All acceptance_criteria from task_graph.json verified
|
||||
- [ ] All test_spec.commands pass
|
||||
- [ ] Coverage ≥ coverage_target for covered modules
|
||||
- [ ] Ruff lint clean (backend)
|
||||
- [ ] ESLint clean (frontend)
|
||||
- [ ] Build succeeds (frontend)
|
||||
- [ ] No forbidden patterns introduced
|
||||
- [ ] Test evidence provided in report
|
||||
|
||||
---
|
||||
|
||||
## 8. Environment Variables (Names Only)
|
||||
|
||||
### Backend
|
||||
```
|
||||
DATABASE_URL=postgresql+asyncpg://erp_user:${DB_PASSWORD}@postgres:5432/erp_db
|
||||
REDIS_URL=redis://redis:6379/0
|
||||
JWT_SECRET=${JWT_SECRET}
|
||||
JWT_ALGORITHM=HS256
|
||||
JWT_ACCESS_TTL_MINUTES=15
|
||||
JWT_REFRESH_TTL_DAYS=7
|
||||
ENCRYPTION_KEY=${ENCRYPTION_KEY}
|
||||
OPENROUTER_API_KEY=${OPENROUTER_API_KEY}
|
||||
MOBILE_DE_API_KEY=${MOBILE_DE_API_KEY}
|
||||
MOBILE_DE_SELLER_ID=${MOBILE_DE_SELLER_ID}
|
||||
UPLOAD_DIR=/data/uploads
|
||||
MAX_FILE_SIZE_MB=50
|
||||
CORS_ORIGINS=https://erp.domain.tld
|
||||
```
|
||||
|
||||
### Frontend
|
||||
```
|
||||
NEXT_PUBLIC_API_URL=http://backend:8000/api/v1
|
||||
NEXTAUTH_SECRET=${NEXTAUTH_SECRET}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. Git Workflow
|
||||
|
||||
### Branches
|
||||
- `main` – Production branch, deployed via Coolify
|
||||
- `feature/T0X-<short-name>` – Feature branch per task
|
||||
- `fix/T0X-<short-name>` – Fix branch
|
||||
|
||||
### Commit Messages
|
||||
```
|
||||
feat(T02): add vehicle CRUD with type-specific fields
|
||||
fix(T02): correct FIN validation for 17-char check
|
||||
test(T02): add mobile.de batch push tests
|
||||
refactor(T02): extract field mapping to separate function
|
||||
docs(T02): update vehicle API documentation
|
||||
```
|
||||
|
||||
### PR Process
|
||||
1. Create feature branch from main
|
||||
2. Implement + test + lint + build
|
||||
3. Commit with conventional commit format
|
||||
4. Push branch
|
||||
5. Create PR with task ID reference
|
||||
6. CI runs: pytest, ruff, vitest, eslint, build
|
||||
7. Merge after CI passes
|
||||
|
||||
---
|
||||
|
||||
## 10. Database Migration Rules
|
||||
|
||||
- **Always use Alembic** for schema changes
|
||||
- **Never** modify database directly (psql, pgadmin)
|
||||
- **One migration per schema change** – don't bundle multiple changes
|
||||
- **Test migration up AND down** before committing
|
||||
- **Seed data:** Use a separate seed script (`scripts/seed.py`), not migrations
|
||||
- **Cleanup after migration tasks:**
|
||||
```bash
|
||||
alembic upgrade head # Apply
|
||||
# Verify all tables created
|
||||
python -c "from app.database import engine; from sqlalchemy import inspect; insp = inspect(engine); print(insp.get_table_names())"
|
||||
# Run seed data
|
||||
python scripts/seed.py
|
||||
# Verify foreign keys
|
||||
docker-compose exec postgres psql -U erp_user -d erp_db -c "\d vehicles"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. OpenRouter Integration Rules
|
||||
|
||||
- **Always use** `openrouter_client.py` shared client – never call OpenRouter API directly
|
||||
- **Always set timeout** to 30 seconds
|
||||
- **Always log** interaction to `ai_interactions` table (type, model, tokens, metadata)
|
||||
- **Never send** Ausweisdaten or personal customer data to OpenRouter
|
||||
- **Mock OpenRouter** in all automated tests
|
||||
- **Handle errors gracefully:** API error → 502, timeout → 504, rate limit → 429
|
||||
- **Model selection** via config, not hardcoded in service
|
||||
|
||||
---
|
||||
|
||||
## 12. Security Checklist
|
||||
|
||||
- [ ] JWT authentication on all endpoints (except /auth/login, /auth/refresh, /health)
|
||||
- [ ] RBAC enforced (require_role decorator on every router)
|
||||
- [ ] Input validation via Pydantic schemas on all endpoints
|
||||
- [ ] SQL injection protection via SQLAlchemy ORM (no raw SQL)
|
||||
- [ ] File upload: MIME-type allowlist + size limit
|
||||
- [ ] Ausweisdaten: AES-256-GCM encryption
|
||||
- [ ] CORS: only configured origins
|
||||
- [ ] Audit log: all create/update/delete actions logged
|
||||
- [ ] No secrets in code or git
|
||||
- [ ] HTTPS via Traefik/Let's Encrypt
|
||||
- [ ] DSGVO: no PII to OpenRouter, soft-delete with retention concept
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,95 @@
|
||||
# Component Inventory - ERP Nutzfahrzeuge
|
||||
|
||||
## Version: 1.0
|
||||
## Datum: 2026-07-10
|
||||
|
||||
## Shared Components
|
||||
|
||||
| Component | Description | States |
|
||||
|---|---|---|
|
||||
| **Icon** | SVG-Icon-System mit 50+ Icons | default |
|
||||
| **Badge** | Status-Badge (success, warning, error, info, neutral, primary) | default |
|
||||
| **Button** | Button-Komponente (primary, secondary, ghost, danger) mit Größen (sm, md, lg) | default, hover, focus, active, disabled |
|
||||
| **Card** | Container-Karte mit Header und Body | default |
|
||||
| **KpiCard** | KPI-Kennzahlen-Karte mit Label, Value, Trend, Icon | default, hover |
|
||||
| **Spinner** | Lade-Indikator (sm, lg) | loading |
|
||||
| **EmptyState** | Leer-Zustand mit Icon, Titel, Text, CTA-Button | empty |
|
||||
| **ErrorState** | Fehler-Zustand mit Icon, Titel, Text, Retry-Button | error |
|
||||
| **Avatar** | Nutzer-Avatar mit Initialen (md, lg) | default |
|
||||
| **Toast** | Toast-Notification (success, error, warning, info) mit Auto-Dismiss | default, exit-animation |
|
||||
| **ToastContainer** | Container für Toast-Stack | - |
|
||||
|
||||
## Layout Components
|
||||
|
||||
| Component | Description | States |
|
||||
|---|---|---|
|
||||
| **App** | Root-Komponente mit Router, Sidebar, Topbar, Content | - |
|
||||
| **Sidebar** | Navigation-Sidebar mit Sektionen, Rollen-Filter, User-Profil | active, hover, collapsed (mobile) |
|
||||
| **Topbar** | Header mit Breadcrumb, Sprachumschalter, Dark-Mode-Toggle, Profil-Menü | default, dropdown-open |
|
||||
| **useRouter** | Hash-based SPA Router | - |
|
||||
|
||||
## View Components
|
||||
|
||||
| Component | View | Description | States |
|
||||
|---|---|---|---|
|
||||
| **DashboardView** | #/dashboard | KPIs, Schnellzugriffe, Letzte Aktivitäten, Bevorstehende Tasks, Top-Fahrzeuge | loading, error, happy |
|
||||
| **FahrzeugListe** | #/fahrzeuge | Filterbare/sortierbare Tabelle mit Suche, Pagination, mobile.de-Status | loading, error, empty, happy, partial |
|
||||
| **FahrzeugDetail** | #/fahrzeug/:id | Detailansicht mit 7 Tabs (Allgemein, Technisch, Baumaschinen, Verkaufsinfo, Dokumente, Fotos, mobile.de) | loading, error, not-found, happy |
|
||||
| **FahrzeugForm** | #/fahrzeuge/neu | Formular mit OCR-Upload, Standarddaten, Baumaschinen-Feldern, LKW-Feldern, Validierung | default, ocr-loading, saving, validation-error |
|
||||
| **KontakteListe** | #/kontakte | Kontakt-Liste mit Filter (Rolle, Land), USt-IdNr.-Status, Sortierung | loading, error, empty, happy |
|
||||
| **VerkaufsModul** | #/verkauf | 4-Step Wizard: Fahrzeug/Kunde → Vertragsdetails → Prüfung → Abschluss | step-1, step-2, step-3, step-4, generating, gwg-warning, ust-warning |
|
||||
| **KiCopilot** | #/ki-copilot | Chat-Interface mit Beispiel-Befehlen, Spracheingabe-Button, KI-Funktionen-Übersicht | default, loading, listening |
|
||||
| **Einstellungen** | #/einstellungen | 4 Tabs: Stammdaten, Vertragsvorlagen, Benutzerverwaltung, Firmenprofil | default |
|
||||
|
||||
## Form Components
|
||||
|
||||
| Component | Description | States |
|
||||
|---|---|---|
|
||||
| **Input** | Text-Eingabefeld | default, focus, disabled, error |
|
||||
| **Select** | Dropdown-Auswahl | default, focus, disabled |
|
||||
| **Textarea** | Mehrzeilige Text-Eingabe | default, focus, disabled |
|
||||
| **Label** | Form-Label mit Required-Indikator | default |
|
||||
| **Dropzone** | Drag-and-Drop Upload-Zone | default, hover, dragover, loading |
|
||||
|
||||
## Interactive Components
|
||||
|
||||
| Component | Description | States |
|
||||
|---|---|---|
|
||||
| **Tabs** | Tab-Navigation mit aktiven/inaktiven Tabs | default, active, hover |
|
||||
| **Pagination** | Seiten-Navigation mit Info und Controls | default, active, disabled |
|
||||
| **Toggle** | Switch-Toggle (z.B. Dark Mode) | default, active |
|
||||
| **ProgressBar** | Fortschrittsbalken | default |
|
||||
| **WarningBanner** | Warnungs-Banner mit Icon und Text | default |
|
||||
|
||||
## Data Display Components
|
||||
|
||||
| Component | Description | States |
|
||||
|---|---|---|
|
||||
| **DataTable** | Sortierbare Tabelle mit Header, Zeilen, Hover-Effekt | default, sorted-asc, sorted-desc, hover |
|
||||
| **InfoGrid** | Grid mit Info-Items (Label + Value) | default |
|
||||
| **ImageGrid** | Grid für Foto-Galerie | default, hover |
|
||||
|
||||
## i18n System
|
||||
|
||||
| Component | Description |
|
||||
|---|---|
|
||||
| **translations** | DE + EN Übersetzungs-Objekt (250+ Keys) |
|
||||
| **t(key)** | Übersetzungs-Funktion mit Fallback |
|
||||
| **setLang(lang)** | Sprache setzen und anwenden |
|
||||
| **applyTranslations()** | Alle data-i18n Attribute aktualisieren |
|
||||
|
||||
## Rollen-System
|
||||
|
||||
| Rolle | Berechtigungen |
|
||||
|---|---|
|
||||
| **Admin** | Vollzugriff auf alle Module |
|
||||
| **Verkäufer** | Fahrzeugbestand, mobile.de, Kontakte, Verkauf, KI-Copilot, Bildretusche |
|
||||
| **Buchhaltung** | Lesen: Fahrzeuge/Kontakte/Verkauf, Schreiben: USt-IdNr./GwG/Rechnungen/DATEV |
|
||||
|
||||
## Accessibility Features
|
||||
- Skip-Link zum Hauptinhalt
|
||||
- ARIA-Labels für Icon-Buttons
|
||||
- :focus-visible Outline
|
||||
- Semantisches HTML (nav, main, header, aside, table)
|
||||
- Keyboard-Navigation unterstützt
|
||||
- Kontrast-Level WCAG 2.1 AA
|
||||
@@ -0,0 +1,88 @@
|
||||
# Offene Fragen – ERP Nutzfahrzeug-/Baumaschinen-Handel
|
||||
|
||||
**Stand:** 2026-07-10
|
||||
**Status:** Discovery abgeschlossen – alle Fragen geklärt
|
||||
|
||||
---
|
||||
|
||||
## 1. Tech-Stack
|
||||
|
||||
1. **Backend-Präferenz?** ✅ RESOLVED → Python / FastAPI
|
||||
2. **Frontend-Präferenz?** ✅ RESOLVED → React / Next.js (TypeScript)
|
||||
3. **Datenbank?** ✅ RESOLVED → PostgreSQL 16+
|
||||
4. **PDF-Generierung?** ✅ RESOLVED → Server-seitig (WeasyPrint oder ReportLab)
|
||||
|
||||
## 2. Hosting & Deployment
|
||||
|
||||
5. **Hosting?** ✅ RESOLVED → Coolify self-hosted (Docker) auf eigenem Server
|
||||
6. **CI/CD?** ✅ RESOLVED → Forgejo Actions → Docker Build → Coolify Deploy. Dev + Prod Environments.
|
||||
7. **Domain?** ⏳ SPÄTER → Zu klären mit Coolify (vorhandene Domain nutzbar)
|
||||
|
||||
## 3. mobile.de Integration
|
||||
|
||||
8. **mobile.de Händleraccount vorhanden?** ✅ RESOLVED → JA, aktiver Account mit Seller API-Zugang
|
||||
9. **API-Zugangsdaten?** ✅ RESOLVED → JA, vorhanden (Customer-ID und API-Key)
|
||||
10. **Sync-Richtung?** ✅ RESOLVED → Push-Only (ERP → mobile.de), NICHT bidirektional
|
||||
11. **Sync-Frequenz?** ✅ RESOLVED → Manuell im MVP, ggf. Cron-Job später
|
||||
12. **Nutzfahrzeug-spezifische Felder?** ✅ RESOLVED → JA: LKW-Typ, Art (Bagger, Radlader, etc.), Aufbau, Betriebsstunden statt KM, Leistung kW/PS
|
||||
|
||||
## 4. OCR (Zulassungsbescheinigung)
|
||||
|
||||
13. **OCR-Anbieter-Präferenz?** ✅ RESOLVED → OpenRouter Vision-Modell (Qwen2.5-VL), keine Spezial-API
|
||||
14. **Budget für OCR-API?** ✅ RESOLVED → OpenRouter pay-per-use, Budget vorhanden
|
||||
15. **Datenschutz?** ✅ RESOLVED → DSGVO: Cloud-Verarbeitung via OpenRouter akzeptiert
|
||||
16. **Offline-OCR?** ✅ RESOLVED → Nein, Internetverbindung erforderlich (Cloud)
|
||||
|
||||
## 5. Rechtsdokumente & Compliance
|
||||
|
||||
17. **Rechtsberatung?** ✅ RESOLVED → System generiert Verträge aus Vorlagen. Stammdaten in Einstellungen hinterlegt.
|
||||
18. **GwG-Schwellwert?** ✅ RESOLVED → 10.000 € Barzahlung (gesetzlicher Standard)
|
||||
19. **Ausweisdaten-Speicherung?** ✅ RESOLVED → JA, DSGVO-konform verschlüsselt (AES-256), Zugriff nur Admin + Buchhaltung
|
||||
20. **BZSt-API-Zugang?** ✅ RESOLVED → NEIN, kein Zugang vorhanden. Manuelle Prüfung im MVP, API-Integration später.
|
||||
21. **Steuerberater-Einbindung?** ✅ RESOLVED → JA, DATEV-Export (CSV) eingeplant
|
||||
|
||||
## 6. KI-Copilot
|
||||
|
||||
22. **Sprachsteuerung?** ✅ RESOLVED → Beides: Spracheingabe (Microphone) + Text-Eingabe
|
||||
23. **LLM-Präferenz?** ✅ RESOLVED → OpenRouter (flexibel, z.B. Claude/GPT-4 über OpenRouter)
|
||||
24. **KI-Kosten?** ✅ RESOLVED → OpenRouter pay-per-use, Budget vorhanden
|
||||
25. **KI-Autonomie?** ✅ RESOLVED → KI darf selbstständig handeln (nach User-Bestätigung)
|
||||
|
||||
## 7. KI Bildretusche
|
||||
|
||||
26. **Bildretusche-Anbieter?** ✅ RESOLVED → OpenRouter Flux.1-Pro (Hintergrund entfernen, Spiegelungen retuschieren)
|
||||
27. **Batch-Größe?** ✅ RESOLVED → Batch-Verarbeitung für mehrere Fotos pro Fahrzeug
|
||||
28. **Kosten pro Bild?** ✅ RESOLVED → OpenRouter pay-per-use, Budget vorhanden
|
||||
|
||||
## 8. Budget & Zeitrahmen
|
||||
|
||||
29. **Budget?** ✅ RESOLVED → OpenRouter pay-per-use + mobile.de Händleraccount. Keine harten Budget-Limits.
|
||||
30. **Zeitrahmen?** ✅ RESOLVED → MVP-Phasen sequenziell, keine harten Deadlines
|
||||
31. **MVP-Prioritäten?** ✅ RESOLVED → Logischer Ablauf: Bestand → Kontakte → Verkauf etc. (7 Phasen definiert)
|
||||
|
||||
## 9. Nutzer & Rollen
|
||||
|
||||
32. **Anzahl Nutzer?** ✅ RESOLVED → ~10 Nutzer
|
||||
33. **Rollen?** ✅ RESOLVED → 3 Rollen: Admin, Verkäufer, Buchhaltung (Berechtigungs-Matrix definiert)
|
||||
34. **Auth-Methode?** ✅ RESOLVED → JWT-basiert (Benutzername/Passwort), Session-Timeout 30min
|
||||
|
||||
## 10. Datenmigration
|
||||
|
||||
35. **Bestehende Daten?** ✅ RESOLVED → Keine Datenmigration nötig
|
||||
36. **Format?** ✅ RESOLVED → N/A (keine Bestandsdaten)
|
||||
37. **Menge?** ✅ RESOLVED → N/A (keine Bestandsdaten)
|
||||
|
||||
## 11. Sonstiges
|
||||
|
||||
38. **Projektname?** ⏳ SPÄTER → Zu klären mit User (Branding)
|
||||
39. **Sprachen?** ✅ RESOLVED → Deutsch + Englisch (beides, i18n von Anfang an)
|
||||
40. **Mobile App später?** ✅ RESOLVED → Nein, nur responsive Web-UI (kein native App)
|
||||
|
||||
---
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
- **Resolved:** 38/40
|
||||
- **Später:** 2/40 (Domain, Projektname/Branding)
|
||||
- **Unresolved:** 0/40
|
||||
- **Blockiert für Architecture:** Nein (keine kritischen offenen Fragen)
|
||||
@@ -0,0 +1,703 @@
|
||||
# ERP-System für Nutzfahrzeug-/Baumaschinen-Handel
|
||||
## Requirements Specification
|
||||
|
||||
**Version:** 1.0.0
|
||||
**Datum:** 2026-07-10
|
||||
**Status:** Final – Discovery abgeschlossen
|
||||
**Analyst:** Requirements Analyst (A0)
|
||||
|
||||
---
|
||||
|
||||
## 1. Projektüberblick
|
||||
|
||||
Ein webbasiertes ERP-System für Händler von Nutzfahrzeugen und Baumaschinen (~10 Nutzer). Das System verwaltet Fahrzeugbestände mit Baumaschinen-spezifischen Feldern, Kundenkontakte, Verkaufsprozesse mit Rechtsdokumenten, OCR-basierte Datenerfassung via Vision-Modellen, mobile.de Push-Sync, KI-Copilot (Text + Sprache) und KI-Bildretusche. Alle KI-Funktionen laufen über OpenRouter.
|
||||
|
||||
### Domain Knowledge
|
||||
- **Domain:** Nutzfahrzeug- und Baumaschinenhandel (B2B/B2C)
|
||||
- **Zulassungsdokumente:** Zulassungsbescheinigung Teil I (ZB I = Fahrzeugschein) und Teil II (ZB II = Fahrzeugbrief), EU-einheitlich seit 2005
|
||||
- **mobile.de:** Deutschlands größter Fahrzeugmarkt mit Seller API (REST) für Händler
|
||||
- **Baumaschinen-spezifisch:** LKW-Typ, Art (Bagger, Radlader, etc.), Aufbau, Betriebsstunden statt Kilometerstand, Leistung in kW/PS
|
||||
- **USt-IdNr.-Prüfung:** Gesetzlich vorgeschrieben bei innergemeinschaftlichen Lieferungen (§ 6a UStG, § 27a UStG). BZSt eVatR API-Zugang aktuell NICHT vorhanden – manuelle Prüfung im MVP
|
||||
- **Geldwäsche-Prävention:** Identifikation, Meldepflichten bei Barzahlungen > 10.000 € (GwG)
|
||||
- **Kaufverträge/Rechnungen:** Unterscheidung EU-Inland, EU-Ausland, Dritland
|
||||
- **DATEV:** Standard-Exportformat für Steuerberater-Übergabe
|
||||
|
||||
---
|
||||
|
||||
## 2. Tech-Stack Entscheidungen
|
||||
|
||||
| Komponente | Entscheidung | Begründung |
|
||||
|---|---|---|
|
||||
| **Backend** | Python / FastAPI | Async, OpenAPI-Auto-Docs, Python-Ökosystem für KI/OCR-Integration, schnell zu entwickeln |
|
||||
| **Frontend** | React / Next.js | SSR, große Community, TypeScript-Support, Component-Ökosystem |
|
||||
| **Datenbank** | PostgreSQL | Relational, robust, JSON-Support für flexible Felder, Full-Text-Search |
|
||||
| **Hosting** | Coolify self-hosted (Docker) | Bereits vorhanden, keine Cloud-Abhängigkeit, volle Kontrolle |
|
||||
| **OCR** | OpenRouter Vision-Modell (Qwen2.5-VL) | Keine Spezial-API nötig, DSGVO: Cloud-Verarbeitung akzeptiert |
|
||||
| **KI-Copilot** | OpenRouter (bestes Modell, z.B. Claude/GPT-4) | Flexibel, kein Vendor-Lock-in, KI darf selbstständig handeln |
|
||||
| **KI-Bildretusche** | OpenRouter Flux.1-Pro | Hintergrund entfernen, Spiegelungen retuschieren |
|
||||
| **KI-Vision/Analyse** | OpenRouter Qwen2.5-VL | Fahrzeugfoto-Analyse, ZB I/II Felderkennung |
|
||||
| **i18n** | Deutsch + Englisch | Beide Sprachen von Anfang an |
|
||||
| **DATEV-Export** | CSV/DATEV-kompatibel | Für Steuerberater-Übergabe |
|
||||
|
||||
### Coding Guidelines
|
||||
- **Naming:** snake_case (Python), camelCase (JS/TS), PascalCase (React Components)
|
||||
- **Struktur:** Modulare Feature-Ordner, Shared-Libraries für Common-Logic
|
||||
- **Linting:** ruff (Python), eslint + prettier (TypeScript)
|
||||
- **Tests:** pytest (Backend), jest/playwright (Frontend), Coverage-Target ≥80%
|
||||
- **API-Stil:** RESTful, OpenAPI 3.0, versionierte Endpoints (/api/v1/...)
|
||||
|
||||
### Deployment
|
||||
- **Environments:** Dev + Prod via Coolify (Docker Compose)
|
||||
- **CI/CD:** Forgejo Actions → Docker Build → Coolify Deploy
|
||||
- **Secrets:** Umgebungsvariablen in Coolify, niemals im Code
|
||||
|
||||
---
|
||||
|
||||
## 3. Module und Features
|
||||
|
||||
### Modul M1: Fahrzeugbestand + mobile.de Push-Sync
|
||||
|
||||
#### [F-M1-01] Fahrzeugbestand verwalten
|
||||
**Anforderung:** Vollständige Verwaltung des Fahrzeugbestands mit Standard- und Baumaschinen-spezifischen Feldern. Standardfelder: Marke, Modell/Typ, FIN (Fahrgestellnummer), Baujahr, Erstzulassung, Leistung (kW/PS), Kraftstoffart, Getriebe, Farbe, Zustand, Standort, Verfügbarkeit, Preis. Baumaschinen-spezifische Felder: LKW-Typ, Art (Bagger, Radlader, Kran, etc.), Aufbau, Betriebsstunden (statt KM-Stand), Betriebsstunden-Einheit (h/min).
|
||||
|
||||
**Test Scenarios (Pflicht, mind. 2):**
|
||||
1. **Happy Path:** Neues Baumaschinen-Fahrzeug wird mit allen Pflichtfeldern inkl. Betriebsstunden angelegt. Erwartet: Fahrzeug erscheint in Bestandsliste, FIN validiert (17 Zeichen), Betriebsstunden-Feld sichtbar, alle Felder gespeichert.
|
||||
2. **Edge Case:** Fahrzeug mit doppelter FIN wird angelegt. Erwartet: Fehlermeldung „FIN bereits vorhanden“, kein Speichern.
|
||||
3. **Integration:** Fahrzeug wird angelegt und danach über die Suchfunktion gefunden. Erwartet: Fahrzeug erscheint in Suchergebnissen mit allen eingegebenen Daten inkl. Baumaschinen-Felder.
|
||||
|
||||
**Akzeptanzkriterium:**
|
||||
- Build erfolgreich
|
||||
- Alle 3 Tests grün
|
||||
- Fahrzeugbestand-Seite lädt, Formular mit Baumaschinen-Feldern, Bestandsliste zeigt alle Fahrzeuge
|
||||
|
||||
---
|
||||
|
||||
#### [F-M1-02] mobile.de Push-Sync (nur Push)
|
||||
**Anforderung:** Fahrzeuge aus dem Bestand können auf mobile.de gelistet/aktualisiert werden. Über die mobile.de Seller API (REST) werden Fahrzeugdaten übertragen (Push-Only, NICHT bidirektional). Feldmapping zwischen ERP-Feldern und mobile.de-Feldern. Sync-Status wird pro Fahrzeug angezeigt (Entwurf → gelistet → aktualisiert → verkauft/entfernt). Preisänderungen im ERP können gepusht werden.
|
||||
|
||||
**Test Scenarios (Pflicht, mind. 2):**
|
||||
1. **Happy Path:** Fahrzeug mit vollständigen Daten wird an mobile.de gesendet. Erwartet: API-Response 200/201, Fahrzeug erscheint auf mobile.de, Status im ERP wird auf „gelistet" aktualisiert.
|
||||
2. **Edge Case:** Fahrzeug mit unvollständigen mobile.de-Pflichtfeldern wird gesendet. Erwartet: API-Fehlermeldung wird im ERP angezeigt, Fahrzeug wird nicht gelistet, Status bleibt „Entwurf".
|
||||
3. **Integration:** Fahrzeug wird auf mobile.de gelistet, dann im ERP Preis geändert, Push-Sync erneut ausgeführt. Erwartet: Preis auf mobile.de aktualisiert, Sync-Status „aktualisiert".
|
||||
|
||||
**Akzeptanzkriterium:**
|
||||
- Build erfolgreich
|
||||
- Alle 3 Tests grün
|
||||
- API-Verbindung zu mobile.de konfigurierbar, Push-Listing funktioniert, Status-Tracking korrekt
|
||||
|
||||
---
|
||||
|
||||
#### [F-M1-03] mobile.de Listing-Verwaltung
|
||||
**Anforderung:** Übersicht aller Fahrzeuge mit mobile.de-Status. Filterung nach Status (nicht gelistet, gelistet, Fehler). Batch-Push für mehrere Fahrzeuge. Fehler-Logs pro Fahrzeug einsehbar. Entfernen von Listings auf mobile.de (Delisting).
|
||||
|
||||
**Test Scenarios (Pflicht, mind. 2):**
|
||||
1. **Happy Path:** 3 Fahrzeuge werden per Batch-Push an mobile.de gesendet. Erwartet: Alle 3 erhalten Status „gelistet", Fortschrittsanzeige während Sync.
|
||||
2. **Edge Case:** Ein Fahrzeug von 3 hat fehlende Pflichtfelder. Erwartet: 2 erfolgreich gepusht, 1 mit Fehlermeldung, Fehler-Log einsehbar.
|
||||
3. **Integration:** Fahrzeug wird auf mobile.de delisted. Erwartet: Listing auf mobile.de entfernt, Status im ERP „entfernt".
|
||||
|
||||
**Akzeptanzkriterium:**
|
||||
- Build erfolgreich
|
||||
- Alle 3 Tests grün
|
||||
- Batch-Push, Status-Übersicht, Fehler-Logs und Delisting funktionieren
|
||||
|
||||
---
|
||||
|
||||
### Modul M2: OCR Fahrzeugdaten-Erfassung
|
||||
|
||||
#### [F-M2-01] OCR-Erfassung Zulassungsbescheinigung Teil I (ZB I / Fahrzeugschein)
|
||||
**Anforderung:** Foto des Fahrzeugscheins (ZB I) hochladen, OpenRouter Vision-Modell (Qwen2.5-VL) erkennt Felder automatisch (Felder A–K gemäß KBA-Standard): Marke, Modell, FIN, Erstzulassung, Kennzeichen, Leistung, Hubraum, Kraftstoffart, Schadstoffklasse, etc. Daten werden in Fahrzeugformular eingetragen, User kann korrigieren.
|
||||
|
||||
**Test Scenarios (Pflicht, mind. 2):**
|
||||
1. **Happy Path:** Gut belichtetes Foto einer ZB I wird hochgeladen. Erwartet: Qwen2.5-VL erkennt alle relevanten Felder mit >90% Genauigkeit, Daten werden in Fahrzeugformular eingetragen, User kann korrigieren.
|
||||
2. **Edge Case:** Verschmutztes oder schiefes Foto wird hochgeladen. Erwartet: System gibt Warnung „Bildqualität niedrig", best-effort Erkennung, alle Felder editierbar.
|
||||
3. **Integration:** OCR-Daten werden ins Fahrzeugformular eingetragen, User speichert. Erwartet: Fahrzeug wird mit OCR-Daten angelegt, Felder korrekt übernommen.
|
||||
|
||||
**Akzeptanzkriterium:**
|
||||
- Build erfolgreich
|
||||
- Alle 3 Tests grün
|
||||
- Upload funktioniert, Qwen2.5-VL via OpenRouter erkennt Felder, Daten fließen in Formular
|
||||
|
||||
---
|
||||
|
||||
#### [F-M2-02] OCR-Erfassung Zulassungsbescheinigung Teil II (ZB II / Fahrzeugbrief)
|
||||
**Anforderung:** Foto des Fahrzeugbriefs (ZB II) hochladen, OpenRouter Qwen2.5-VL erkennt Felder: FIN, Hersteller, Typ, Variante, Fahrzeugklasse, Antriebsart, Leistung, Hubraum, zul. Gesamtgewicht, Datum der Erstzulassung, Previous Owner, etc. Daten werden in Fahrzeugformular eingetragen.
|
||||
|
||||
**Test Scenarios (Pflicht, mind. 2):**
|
||||
1. **Happy Path:** Gut belichtetes Foto einer ZB II wird hochgeladen. Erwartet: Alle relevanten Felder werden erkannt, Daten ins Fahrzeugformular eingetragen.
|
||||
2. **Edge Case:** ZB II mit Stempeln/Aufklebern die Teile des Textes verdecken. Erwartet: System warnt, best-effort Erkennung, manuelle Korrektur möglich.
|
||||
3. **Integration:** ZB I und ZB II für dasselbe Fahrzeug hochgeladen. Erwartet: Daten werden zusammengeführt, FIN-Abgleich zwischen ZB I und ZB II, Warnung bei Diskrepanz.
|
||||
|
||||
**Akzeptanzkriterium:**
|
||||
- Build erfolgreich
|
||||
- Alle 3 Tests grün
|
||||
- Upload funktioniert, Qwen2.5-VL erkennt ZB II-Felder, Zusammenführung mit ZB I
|
||||
|
||||
---
|
||||
|
||||
### Modul M3: Kontakt- & Kundenverwaltung
|
||||
|
||||
#### [F-M3-01] Kontakt- und Kundenverwaltung
|
||||
**Anforderung:** Verwaltung von Firmen und Ansprechpartnern. Felder: Firmenname, Rechtsform, Ansprechpartner (Name, Funktion), Adresse (Straße, PLZ, Ort, Land), USt-IdNr., Telefon, E-Mail, Website. Unterscheidung Käufer/Verkäufer. EU-International und Inland. ~10 Nutzer arbeiten mit den Daten.
|
||||
|
||||
**Test Scenarios (Pflicht, mind. 2):**
|
||||
1. **Happy Path:** Neue Firma mit Ansprechpartner wird angelegt als „Käufer". Erwartet: Firma erscheint in Kontaktliste mit Rolle „Käufer", alle Felder gespeichert.
|
||||
2. **Edge Case:** Firma ohne USt-IdNr. (Privatkunde/Dritland) wird angelegt. Erwartet: USt-IdNr. optional, Firma wird gespeichert, Rolle „Käufer" zugewiesen.
|
||||
3. **Integration:** Firma wird als Käufer angelegt, dann Verkauf an diese Firma gestartet. Erwartet: Firmendaten fließen in Kaufvertrag ein.
|
||||
|
||||
**Akzeptanzkriterium:**
|
||||
- Build erfolgreich
|
||||
- Alle 3 Tests grün
|
||||
- Kontaktliste zeigt Firmen mit Rollen, Anlegen/Editieren funktioniert
|
||||
|
||||
---
|
||||
|
||||
#### [F-M3-02] Kundensuche und Filter
|
||||
**Anforderung:** Kunden/Kontakte können gesucht und gefiltert werden nach: Name, Land, Rolle (Käufer/Verkäufer), USt-IdNr.-Status (geprüft/ungeprüft/manuell bestätigt).
|
||||
|
||||
**Test Scenarios (Pflicht, mind. 2):**
|
||||
1. **Happy Path:** Suche nach „Müller" in Kontakten. Erwartet: Alle Kontakte mit „Müller" im Namen erscheinen.
|
||||
2. **Edge Case:** Filter „Land = Deutschland" und „Rolle = Käufer" kombiniert. Erwartet: Nur deutsche Käufer-Firmen erscheinen.
|
||||
3. **Integration:** Gefundener Kontakt wird für Verkauf ausgewählt. Erwartet: Kontakt wird in Verkaufsformular übernommen.
|
||||
|
||||
**Akzeptanzkriterium:**
|
||||
- Build erfolgreich
|
||||
- Alle 3 Tests grün
|
||||
- Such- und Filterfunktion liefert korrekte Ergebnisse
|
||||
|
||||
---
|
||||
|
||||
### Modul M4: Dateiablage pro Fahrzeug
|
||||
|
||||
#### [F-M4-01] Dateiablage pro Fahrzeug
|
||||
**Anforderung:** Jedes Fahrzeug hat einen eigenen Dateibereich. Dokumente (PDF, Verträge, Rechnungen), Fotos (JPG/PNG) und andere Dateien können hochgeladen, kategorisiert, umbenannt und gelöscht werden. Dateivorschau für Bilder und PDFs. Max 50 MB pro Datei. Kategorien: Vertrag, Rechnung, ZB I, ZB II, Foto, Sonstiges.
|
||||
|
||||
**Test Scenarios (Pflicht, mind. 2):**
|
||||
1. **Happy Path:** PDF-Vertrag wird zu Fahrzeug hochgeladen. Erwartet: Datei erscheint in Fahrzeug-Dateibereich, Vorschau sichtbar, Datei kategorisierbar als „Vertrag".
|
||||
2. **Edge Case:** Datei > 50 MB wird hochgeladen. Erwartet: Fehlermeldung „Datei zu groß", kein Upload.
|
||||
3. **Integration:** Foto wird hochgeladen und für KI-Bildretusche (M8) verwendet. Erwartet: Foto ist in Dateiablage sichtbar und für Retusche-Modul auswählbar.
|
||||
|
||||
**Akzeptanzkriterium:**
|
||||
- Build erfolgreich
|
||||
- Alle 3 Tests grün
|
||||
- Datei-Upload, Vorschau, Kategorisierung und Löschung funktionieren
|
||||
|
||||
---
|
||||
|
||||
### Modul M5: Verkaufsmodul mit Rechtsdokumenten
|
||||
|
||||
#### [F-M5-01] Kaufvertrag erstellen
|
||||
**Anforderung:** Verkauf eines Fahrzeugs an einen Kunden. Kaufvertrag wird aus Vertragsvorlagen generiert mit: Fahrzeugdaten, Käufer-/Verkäuferdaten, Preis, Zahlungsbedingungen, Übergabedatum. PDF-Generierung. Unterscheidung EU-Inland, EU-Ausland, Dritland. Vertragsvorlagen basieren auf Stammdaten aus Einstellungen.
|
||||
|
||||
**Test Scenarios (Pflicht, mind. 2):**
|
||||
1. **Happy Path:** Verkauf an deutsche Firma (EU-Inland). Erwartet: Kaufvertrag-PDF wird generiert mit allen Daten, USt ausgewiesen, Vertragsvorlage korrekt angewendet.
|
||||
2. **Edge Case:** Verkauf an Schweizer Firma (Dritland). Erwartet: Kaufvertrag mit 0% USt (Ausfuhrlieferung), Hinweis auf Ausfuhr, andere Vorlage.
|
||||
3. **Integration:** Verkauf startet USt-IdNr.-Prüfung für EU-Ausland-Kunde. Erwartet: Manuelle Prüfung wird angeboten, Ergebnis im Vertrag dokumentiert.
|
||||
|
||||
**Akzeptanzkriterium:**
|
||||
- Build erfolgreich
|
||||
- Alle 3 Tests grün
|
||||
- Kaufvertrag-PDF generiert, alle Varianten (Inland/EU/Dritland) korrekt, Vorlagen aus Stammdaten
|
||||
|
||||
---
|
||||
|
||||
#### [F-M5-02] USt-IdNr.-Überprüfung (manuell)
|
||||
**Anforderung:** Manuelle USt-IdNr.-Prüfung im MVP (kein BZSt eVatR API-Zugang vorhanden). User gibt Prüfergebnis manuell ein (gültig/ungültig, Prüdatum, Art der Prüfung). Prüfergebnis wird dokumentiert. BZSt API-Integration als „später" markiert. System warnt bei EU-Ausland-Verkauf ohne gültige USt-IdNr.
|
||||
|
||||
**Test Scenarios (Pflicht, mind. 2):**
|
||||
1. **Happy Path:** User prüft USt-IdNr. manuell (extern) und trägt Ergebnis „gültig" ein. Erwartet: Prüfergebnis mit Datum gespeichert, Status „geprüft".
|
||||
2. **Edge Case:** EU-Ausland-Verkauf ohne geprüfte USt-IdNr. Erwartet: Warnung „USt-IdNr. nicht geprüft", Verkauf kann erst nach Bestätigung fortgesetzt werden.
|
||||
3. **Integration:** USt-IdNr.-Prüfung wird im Verkaufsprozess angefordert. Erwartet: Prüfung angefordert, User trägt Ergebnis ein, Vertrag wird fortgesetzt.
|
||||
|
||||
**Akzeptanzkriterium:**
|
||||
- Build erfolgreich
|
||||
- Alle 3 Tests grün
|
||||
- Manuelle Prüfung dokumentiert, Warnung bei fehlender Prüfung, BZSt API als „später" markiert
|
||||
|
||||
---
|
||||
|
||||
#### [F-M5-03] Geldwäsche-Prävention
|
||||
**Anforderung:** Identifikation des Vertragspartners (Ausweisdaten: Typ, Nummer, Ausstellungsland). Meldepflicht bei Barzahlungen > 10.000 € (GwG). System warnt automatisch bei Überschreitung. Dokumentation der Identifikation und etwaiger Meldungen. Ausweisdaten werden DSGVO-konform gespeichert (verschlüsselt, Zugriffsbeschränkung auf Admin/Buchhaltung).
|
||||
|
||||
**Test Scenarios (Pflicht, mind. 2):**
|
||||
1. **Happy Path:** Verkauf mit Barzahlung 8.000 €. Erwartet: Keine Warnung, Identifikation wird erfasst aber keine Meldepflicht.
|
||||
2. **Edge Case:** Verkauf mit Barzahlung 12.000 €. Erwartet: Warnung „Meldepflicht nach GwG", Meldedokument wird vorbereitet, Verkauf kann erst nach Bestätigung fortgesetzt werden.
|
||||
3. **Integration:** Identifikation wird im Kaufvertrag dokumentiert. Erwartet: Ausweisdaten (Typ, Nummer, Ausstellungsland) im Vertrag enthalten, verschlüsselt in DB gespeichert.
|
||||
|
||||
**Akzeptanzkriterium:**
|
||||
- Build erfolgreich
|
||||
- Alle 3 Tests grün
|
||||
- GwG-Warngrenze funktioniert, Identifikation erfasst, DSGVO-konforme Speicherung
|
||||
|
||||
---
|
||||
|
||||
#### [F-M5-04] Rechnung und Lieferbescheinigung
|
||||
**Anforderung:** Rechnung wird aus Verkauf generiert (PDF). Lieferbescheinigung für EU-Innergemeinschaftliche Lieferungen. Rechnungsnummer fortlaufend, steuerrechtlich korrekt für Inland/EU-Ausland/Dritland.
|
||||
|
||||
**Test Scenarios (Pflicht, mind. 2):**
|
||||
1. **Happy Path:** Rechnung für EU-Inland-Verkauf wird generiert. Erwartet: Rechnungs-PDF mit USt, fortlaufende Nummer, Lieferbescheinigung beiliegend.
|
||||
2. **Edge Case:** Rechnung für Dritland-Verkauf (Ausfuhrlieferung). Erwartet: Rechnung mit 0% USt, Ausfuhrvermerke, Lieferbescheinigung.
|
||||
3. **Integration:** Rechnung wird aus abgeschlossenem Kaufvertrag generiert. Erwartet: Alle Daten aus Vertrag übernommen, Nummer inkrementiert.
|
||||
|
||||
**Akzeptanzkriterium:**
|
||||
- Build erfolgreich
|
||||
- Alle 3 Tests grün
|
||||
- Rechnungs-PDF generiert, Nummerierung korrekt, alle Varianten
|
||||
|
||||
---
|
||||
|
||||
#### [F-M5-05] DATEV-Export
|
||||
**Anforderung:** Export von Verkaufs- und Rechnungsdaten im DATEV-kompatiblen Format (CSV) für die Übergabe an den Steuerberater. Filterung nach Zeitraum. Export enthält: Belegnummer, Datum, Konto, Betrag, USt, Gegenkonto, Kundennummer.
|
||||
|
||||
**Test Scenarios (Pflicht, mind. 2):**
|
||||
1. **Happy Path:** DATEV-Export für Januar 2026 wird ausgeführt. Erwartet: CSV-Datei mit allen Verkäufen des Monats, DATEV-Format korrekt, herunterladbar.
|
||||
2. **Edge Case:** Export für Zeitraum ohne Verkäufe. Erwartet: Leere CSV mit Headern, Hinweis „Keine Daten im Zeitraum".
|
||||
3. **Integration:** DATEV-Export nach Verkaufsabschluss. Erwartet: Verkauf erscheint im nächsten Export, Beträge korrekt.
|
||||
|
||||
**Akzeptanzkriterium:**
|
||||
- Build erfolgreich
|
||||
- Alle 3 Tests grün
|
||||
- DATEV-CSV korrekt formatiert, Filterung funktioniert, Download verfügbar
|
||||
|
||||
---
|
||||
|
||||
#### [F-M5-06] Vertragsvorlagen-Verwaltung (Stammdaten)
|
||||
**Anforderung:** Vertragsvorlagen werden in den Einstellungen als Stammdaten hinterlegt. Pro Vertragsart (Kaufvertrag Inland, EU-Ausland, Dritland, Rechnung, Lieferbescheinigung) wird eine Vorlage definiert. Variablen werden markiert ({{fahrzeug}}, {{kaeufer}}, {{preis}}, etc.). Admin kann Vorlagen editieren.
|
||||
|
||||
**Test Scenarios (Pflicht, mind. 2):**
|
||||
1. **Happy Path:** Admin erstellt neue Vertragsvorlage für EU-Ausland-Verkauf. Erwartet: Vorlage wird gespeichert, Variablen markiert, bei Verkauf automatisch angewendet.
|
||||
2. **Edge Case:** Vorlage ohne Variablen wird gespeichert. Erwartet: Warnung „Keine Variablen gefunden", Vorlage speicherbar aber nicht funktional.
|
||||
3. **Integration:** Vorlage wird geändert, danach neuer Kaufvertrag erstellt. Erwartet: Neue Vorlage wird verwendet, Variablen korrekt ersetzt.
|
||||
|
||||
**Akzeptanzkriterium:**
|
||||
- Build erfolgreich
|
||||
- Alle 3 Tests grün
|
||||
- Vorlagen-Editor funktioniert, Variablen werden ersetzt, pro Vertragsart zuweisbar
|
||||
|
||||
---
|
||||
|
||||
### Modul M6: Responsive UI (Querschnitt)
|
||||
|
||||
#### [F-M6-01] Responsive Web-UI
|
||||
**Anforderung:** Web-UI funktioniert auf Desktop (≥1280px), Tablet (768–1279px) und Mobile (<768px). Alle Formulare sind touch-optimiert. Navigation passt sich an Bildschirmgröße an (Hamburger-Menü auf Mobile). Gilt für alle Module (Querschnitt).
|
||||
|
||||
**Test Scenarios (Pflicht, mind. 2):**
|
||||
1. **Happy Path:** Desktop-Ansicht bei 1920px Breite. Erwartet: Alle Navigationselemente sichtbar, Formulare nebeneinander angeordnet.
|
||||
2. **Edge Case:** Mobile-Ansicht bei 375px Breite. Erwartet: Hamburger-Menü, Formulare untereinander, Buttons groß genug für Touch.
|
||||
3. **Integration:** Fahrzeugformular auf Mobile ausgefüllt. Erwartet: Alle Felder zugänglich, OCR-Upload funktioniert, Speichern funktioniert.
|
||||
|
||||
**Akzeptanzkriterium:**
|
||||
- Build erfolgreich
|
||||
- Alle 3 Tests grün
|
||||
- UI funktioniert auf allen 3 Breakpoints
|
||||
|
||||
---
|
||||
|
||||
#### [F-M6-02] Internationalisierung (i18n: Deutsch + Englisch)
|
||||
**Anforderung:** Alle UI-Texte, Labels, Fehlermeldungen und Systemmeldungen sind auf Deutsch und Englisch verfügbar. Sprache kann pro User eingestellt werden. Default: Deutsch. Datums-/Zahlenformate passen sich an Sprache an.
|
||||
|
||||
**Test Scenarios (Pflicht, mind. 2):**
|
||||
1. **Happy Path:** User stellt Sprache auf Englisch um. Erwartet: Alle UI-Texte auf Englisch, Datumsformat MM/DD/YYYY, Dezimaltrennzeichen Punkt.
|
||||
2. **Edge Case:** Fehlende Übersetzung für ein Label. Erwartet: Fallback auf Deutsch, Warnung im Dev-Log.
|
||||
3. **Integration:** Sprache wird umgestellt, neues Fahrzeug angelegt. Erwartet: Formular-Labels auf Englisch, Daten werden sprachunabhängig gespeichert.
|
||||
|
||||
**Akzeptanzkriterium:**
|
||||
- Build erfolgreich
|
||||
- Alle 3 Tests grün
|
||||
- DE + EN vollständig, Sprache pro User einstellbar, Formate passen sich an
|
||||
|
||||
---
|
||||
|
||||
### Modul M7: KI-Copilot
|
||||
|
||||
#### [F-M7-01] KI-Copilot – Fahrzeug anlegen
|
||||
**Anforderung:** KI-Assistent versteht natürlichsprachliche Befehle (Text/Sprache). Beispiel: „Lege ein neues Fahrzeug an: Mercedes Actros, Baujahr 2019, 150.000 km, 45.000 Euro". KI extrahiert Daten und füllt Fahrzeugformular aus. KI darf selbstständig handeln (Auto-Save nach Bestätigung). LLM via OpenRouter.
|
||||
|
||||
**Test Scenarios (Pflicht, mind. 2):**
|
||||
1. **Happy Path:** „Neues Fahrzeug: MAN TGL 2018, 120000 km, 32000 €". Erwartet: Fahrzeugformular wird vorausgefüllt mit Marke=MAN, Modell=TGL, Baujahr=2018, KM=120000, Preis=32000. KI speichert nach Bestätigung.
|
||||
2. **Edge Case:** „Füge ein Fahrzeug hinzu" ohne weitere Daten. Erwartet: KI fragt nach fehlenden Pflichtfeldern.
|
||||
3. **Integration:** KI legt Fahrzeug an und listet es gleichzeitig auf mobile.de. Erwartet: Fahrzeug wird gespeichert und mobile.de Push-Sync wird ausgelöst.
|
||||
|
||||
**Akzeptanzkriterium:**
|
||||
- Build erfolgreich
|
||||
- Alle 3 Tests grün
|
||||
- KI versteht Befehl via OpenRouter, füllt Formular, speichert nach Bestätigung
|
||||
|
||||
---
|
||||
|
||||
#### [F-M7-02] KI-Copilot – Suchen und Verkaufen
|
||||
**Anforderung:** KI kann Fahrzeuge suchen („Finde alle LKW unter 30.000 €") und Verkaufsprozesse starten („Verkaufe Fahrzeug FIN XYZ123 an Müller GmbH"). KI darf selbstständig handeln – führt Aktionen nach Bestätigung aus.
|
||||
|
||||
**Test Scenarios (Pflicht, mind. 2):**
|
||||
1. **Happy Path:** „Finde alle Fahrzeuge über 50.000 €". Erwartet: Gefilterte Bestandsliste mit Fahrzeugen > 50.000 €.
|
||||
2. **Edge Case:** „Verkaufe Fahrzeug an Müller GmbH" ohne FIN. Erwartet: KI fragt nach Fahrzeug-Identifikation.
|
||||
3. **Integration:** „Verkaufe FIN XYZ an Müller GmbH, Barzahlung 15000 €". Erwartet: Verkaufsprozess startet, GwG-Warnung erscheint (unter 10.000 → keine, über 10.000 → Warnung).
|
||||
|
||||
**Akzeptanzkriterium:**
|
||||
- Build erfolgreich
|
||||
- Alle 3 Tests grün
|
||||
- KI führt Suchen aus und startet Verkaufsprozesse nach Bestätigung
|
||||
|
||||
---
|
||||
|
||||
#### [F-M7-03] KI-Copilot – Dokumente erstellen
|
||||
**Anforderung:** KI kann Dokumente erstellen („Erstelle Kaufvertrag für Fahrzeug FIN XYZ an Müller GmbH"). KI sammelt alle nötigen Daten und generiert PDF. KI darf selbstständig handeln.
|
||||
|
||||
**Test Scenarios (Pflicht, mind. 2):**
|
||||
1. **Happy Path:** „Erstelle Rechnung für letzten Verkauf". Erwartet: Rechnungs-PDF wird generiert mit Daten aus letztem Verkauf.
|
||||
2. **Edge Case:** „Erstelle Kaufvertrag" ohne Kunden- oder Fahrzeugdaten. Erwartet: KI fragt nach fehlenden Daten.
|
||||
3. **Integration:** KI erstellt Kaufvertrag und löst USt-IdNr.-Prüfung aus. Erwartet: Vertrag generiert, manuelle Prüfung angefordert, Ergebnis im Vertrag.
|
||||
|
||||
**Akzeptanzkriterium:**
|
||||
- Build erfolgreich
|
||||
- Alle 3 Tests grün
|
||||
- KI generiert Dokumente korrekt via OpenRouter
|
||||
|
||||
---
|
||||
|
||||
#### [F-M7-04] KI-Copilot – Spracheingabe
|
||||
**Anforderung:** KI-Assistent akzeptiert Spracheingabe (Microphone-Input) zusätzlich zu Text. Sprache wird zu Text transkribiert (via OpenRouter oder Browser Web Speech API) und dann als Befehl verarbeitet.
|
||||
|
||||
**Test Scenarios (Pflicht, mind. 2):**
|
||||
1. **Happy Path:** User spricht „Lege neues Fahrzeug an: Volvo FH16, Baujahr 2020, 80000 Stunden, 55000 Euro". Erwartet: Sprache wird transkribiert, Fahrzeugformular vorausgefüllt.
|
||||
2. **Edge Case:** Unverständliche Spracheingabe. Erwartet: KI fragt „Konnte Sie nicht verstehen, bitte wiederholen".
|
||||
3. **Integration:** Spracheingabe wird genutzt um Verkauf zu starten. Erwartet: Transkribierter Text wird als Befehl verarbeitet, Verkaufsprozess startet.
|
||||
|
||||
**Akzeptanzkriterium:**
|
||||
- Build erfolgreich
|
||||
- Alle 3 Tests grün
|
||||
- Spracheingabe funktioniert, Transkription korrekt, Befehl wird ausgeführt
|
||||
|
||||
---
|
||||
|
||||
### Modul M8: KI Bildretusche & Preisvergleich
|
||||
|
||||
#### [F-M8-01] KI Bildretusche – Hintergrund entfernen
|
||||
**Anforderung:** Fahrzeugfoto hochladen, OpenRouter Flux.1-Pro entfernt Hintergrund und ersetzt durch neutralen (weiß/grau). Ergebnis kann gespeichert werden. Foto wird in Fahrzeug-Dateiablage abgelegt.
|
||||
|
||||
**Test Scenarios (Pflicht, mind. 2):**
|
||||
1. **Happy Path:** Foto eines LKW vor einer Werkstatt wird hochgeladen. Erwartet: Flux.1-Pro entfernt Hintergrund, neutraler Hintergrund, Fahrzeug klar erkennbar.
|
||||
2. **Edge Case:** Foto mit sehr geringer Auflösung. Erwartet: Warnung „Niedrige Auflösung", best-effort Retusche, User kann Original behalten.
|
||||
3. **Integration:** Retuschiertes Foto wird in Fahrzeug-Dateiablage gespeichert. Erwartet: Foto erscheint in Dateiablage, kann für mobile.de-Listing verwendet werden.
|
||||
|
||||
**Akzeptanzkriterium:**
|
||||
- Build erfolgreich
|
||||
- Alle 3 Tests grün
|
||||
- Bildretusche via Flux.1-Pro funktioniert, Ergebnis speicherbar
|
||||
|
||||
---
|
||||
|
||||
#### [F-M8-02] KI Bildretusche – Spiegelungen entfernen
|
||||
**Anforderung:** Spiegelungen und Reflexionen auf Fahrzeugoberfläche werden durch OpenRouter Flux.1-Pro reduziert/entfernt. Batch-Verarbeitung für mehrere Fotos eines Fahrzeugs.
|
||||
|
||||
**Test Scenarios (Pflicht, mind. 2):**
|
||||
1. **Happy Path:** Foto mit starker Spiegelung wird hochgeladen. Erwartet: Flux.1-Pro reduziert Spiegelung, Fahrzeugoberfläche klarer.
|
||||
2. **Edge Case:** Foto ohne Spiegelungen. Erwartet: Foto bleibt unverändert, Hinweis „Keine Retusche nötig".
|
||||
3. **Integration:** Batch von 5 Fotos wird verarbeitet. Erwartet: Alle 5 Fotos retuschiert, Fortschrittsanzeige, alle speicherbar.
|
||||
|
||||
**Akzeptanzkriterium:**
|
||||
- Build erfolgreich
|
||||
- Alle 3 Tests grün
|
||||
- Spiegelungs-Retusche und Batch-Verarbeitung via Flux.1-Pro funktionieren
|
||||
|
||||
---
|
||||
|
||||
#### [F-M8-03] Preisvergleich mobile.de für ähnliche Fahrzeuge
|
||||
**Anforderung:** Für ein Fahrzeug im Bestand werden ähnliche Inserate auf mobile.de gesucht (gleiche Marke/Modell, ähnliches Baujahr/KM/Stunden). Vergleichspreise werden grafisch aufbereitet (Durchschnitt, Median, Preisverteilung). Read-Only (kein Import).
|
||||
|
||||
**Test Scenarios (Pflicht, mind. 2):**
|
||||
1. **Happy Path:** Für Mercedes Actros 2019 werden mobile.de-Vergleichspreise abgerufen. Erwartet: Liste mit 5-20 vergleichbaren Fahrzeugen, Durchschnittspreis berechnet.
|
||||
2. **Edge Case:** Sehr seltenes Fahrzeug, keine Vergleiche auf mobile.de. Erwartet: Hinweis „Keine Vergleichsfahrzeuge", Empfehlung basierend auf weiter gefassten Kriterien.
|
||||
3. **Integration:** Preisvergleich wird angezeigt, User entscheidet Preisanpassung. Erwartet: Preis wird im ERP aktualisiert, optional mobile.de Push-Sync.
|
||||
|
||||
**Akzeptanzkriterium:**
|
||||
- Build erfolgreich
|
||||
- Alle 3 Tests grün
|
||||
- Preisvergleich zeigt mobile.de-Daten, grafische Aufbereitung, Read-Only
|
||||
|
||||
---
|
||||
|
||||
## 4. Rollen & Berechtigungen
|
||||
|
||||
### Rollen-Definition
|
||||
|
||||
| Rolle | Beschreibung |
|
||||
|---|---|
|
||||
| **Admin** | Vollzugriff auf alle Module, Einstellungen, Vorlagen, Benutzer-Verwaltung |
|
||||
| **Verkäufer** | Fahrzeugbestand, mobile.de Sync, Kontakte, Verkauf, Dateiablage, KI-Copilot, Bildretusche |
|
||||
| **Buchhaltung** | Verkauf (Lesen), Rechnungen, DATEV-Export, Ausweisdaten (GwG), USt-IdNr.-Prüfung |
|
||||
|
||||
### Berechtigungs-Matrix
|
||||
|
||||
| Modul / Feature | Admin | Verkäufer | Buchhaltung |
|
||||
|---|---|---|---|
|
||||
| M1: Fahrzeugbestand (CRUD) | ✅ | ✅ | 📖 |
|
||||
| M1: mobile.de Push-Sync | ✅ | ✅ | ❌ |
|
||||
| M2: OCR Erfassung | ✅ | ✅ | ❌ |
|
||||
| M3: Kontaktverwaltung (CRUD) | ✅ | ✅ | 📖 |
|
||||
| M4: Dateiablage | ✅ | ✅ | 📖 |
|
||||
| M5: Kaufvertrag erstellen | ✅ | ✅ | 📖 |
|
||||
| M5: USt-IdNr.-Prüfung | ✅ | ❌ | ✅ |
|
||||
| M5: Geldwäsche-Prävention | ✅ | 📖 | ✅ |
|
||||
| M5: Rechnung & Lieferbescheinigung | ✅ | 📖 | ✅ |
|
||||
| M5: DATEV-Export | ✅ | ❌ | ✅ |
|
||||
| M5: Vertragsvorlagen-Verwaltung | ✅ | ❌ | ❌ |
|
||||
| M6: Responsive UI | ✅ | ✅ | ✅ |
|
||||
| M6: i18n (Sprache wählen) | ✅ | ✅ | ✅ |
|
||||
| M7: KI-Copilot | ✅ | ✅ | 📖 |
|
||||
| M8: KI Bildretusche | ✅ | ✅ | ❌ |
|
||||
| M8: Preisvergleich | ✅ | ✅ | 📖 |
|
||||
| Einstellungen / Stammdaten | ✅ | ❌ | ❌ |
|
||||
| Benutzer-Verwaltung | ✅ | ❌ | ❌ |
|
||||
|
||||
✅ = Vollzugriff | 📖 = Nur Lesen | ❌ = Kein Zugriff
|
||||
|
||||
---
|
||||
|
||||
## 5. mobile.de Seller API – Push-Only Felder
|
||||
|
||||
### Sync-Richtung: **Push-Only** (ERP → mobile.de, NICHT bidirektional)
|
||||
|
||||
### Feldmapping ERP → mobile.de
|
||||
|
||||
| ERP-Feld | mobile.de Seller API Feld | Anmerkung |
|
||||
|---|---|---|
|
||||
| Marke | make | Pflichtfeld |
|
||||
| Modell/Typ | model | Pflichtfeld |
|
||||
| FIN | vin | 17 Zeichen |
|
||||
| Baujahr | firstRegistration | YYYY-MM |
|
||||
| Kilometerstand / Betriebsstunden | mileage | Einheit: km oder h (mobile.de supported hours für Baumaschinen) |
|
||||
| Preis | price | EUR, netto/brutto kennzeichnen |
|
||||
| Leistung kW | powerKw | Pflichtfeld für LKW |
|
||||
| Leistung PS | powerHp | Berechnet aus kW |
|
||||
| Kraftstoffart | fuelType | diesel, petrol, electric, etc. |
|
||||
| Getriebe | transmission | manual, automatic |
|
||||
| Farbe | color | |
|
||||
| Zustand | condition | new, used |
|
||||
| LKW-Typ | category | LKW-spezifische Kategorie |
|
||||
| Art (Bagger, Radlader, etc.) | bodyType | Baumaschinen-spezifisch |
|
||||
| Aufbau | equipment | Freitext |
|
||||
| Standort | sellerLocation | PLZ, Ort |
|
||||
| Fotos | images | URLs oder Base64 |
|
||||
| Beschreibung | description | Freitext, multi-language |
|
||||
| Verfügbarkeit | availabilityStatus | available, reserved, sold |
|
||||
|
||||
### API-Endpunkte (Push)
|
||||
- **Listing erstellen:** POST /api/seller/listings
|
||||
- **Listing aktualisieren:** PUT /api/seller/listings/{listingId}
|
||||
- **Listing entfernen:** DELETE /api/seller/listings/{listingId}
|
||||
- **Listing-Status:** GET /api/seller/listings/{listingId}/status
|
||||
|
||||
---
|
||||
|
||||
## 6. OpenRouter Modell-Empfehlungen
|
||||
|
||||
| Use Case | Modell | OpenRouter ID | Begründung |
|
||||
|---|---|---|---|
|
||||
| **KI-Copilot (Text + Sprache)** | Bestes verfügbares Modell | openrouter/auto oder claude-3.5-sonnet, gpt-4o | Flexibel, Auto-Routing wählt bestes Modell |
|
||||
| **OCR ZB I/II (Vision)** | Qwen2.5-VL | qwen/qwen-2.5-vl-72b-instruct | Spezialisiert auf Dokumenterkennung, Multilingual |
|
||||
| **Bildretusche (Hintergrund/Spiegelungen)** | Flux.1-Pro | black-forest-labs/flux-1.1-pro | State-of-the-art Bildgenerierung/-bearbeitung |
|
||||
| **Fahrzeugfoto-Analyse** | Qwen2.5-VL | qwen/qwen-2.5-vl-72b-instruct | Vision-Modell für Bildverständnis |
|
||||
|
||||
### DSGVO-Hinweis
|
||||
- OpenRouter verarbeitet Daten in der Cloud (User hat zugestimmt)
|
||||
- Keine sensiblen Personendaten an OpenRouter senden (Ausweisdaten NICHT an KI übertragen)
|
||||
- Fahrzeugdaten und Fotos werden an OpenRouter gesendet (keine Ausweisdaten auf Fotos)
|
||||
|
||||
---
|
||||
|
||||
## 7. MVP-Phasen-Vorschlag
|
||||
|
||||
| Phase | Module | Inhalt | Priorität |
|
||||
|---|---|---|---|
|
||||
| **Phase 1** | M1 | Fahrzeugbestand + mobile.de Push-Sync | Höchste – Kernfunktion |
|
||||
| **Phase 2** | M3 | Kontakt- & Kundenverwaltung | Hoch – Voraussetzung für Verkauf |
|
||||
| **Phase 3** | M4 | Dateiablage pro Fahrzeug | Hoch – Voraussetzung für OCR/Bildretusche |
|
||||
| **Phase 4** | M2 | OCR Fahrzeugdaten-Erfassung | Mittel – Effizienz-Feature |
|
||||
| **Phase 5** | M5 | Verkaufsmodul mit Rechtsdokumenten | Hoch – Geschäftsprozess |
|
||||
| **Phase 6** | M7 | KI-Copilot | Mittel – Automatisierung |
|
||||
| **Phase 7** | M8 | KI Bildretusche & Preisvergleich | Niedrig – Optimierung |
|
||||
| **Querschnitt** | M6 | Responsive UI + i18n | Alle Phasen – gilt überall |
|
||||
|
||||
### Phasen-Abhängigkeiten
|
||||
```
|
||||
Phase 1 (M1) → Phase 2 (M3) → Phase 3 (M4) → Phase 4 (M2)
|
||||
↓
|
||||
Phase 5 (M5) ←Phase 2 (M3) ←Phase 1 (M1)
|
||||
↓
|
||||
Phase 6 (M7) → Phase 7 (M8)
|
||||
```
|
||||
M6 (Responsive UI + i18n) läuft parallel zu allen Phasen.
|
||||
|
||||
---
|
||||
|
||||
## 8. Sicherheit & Compliance
|
||||
|
||||
### DSGVO-Konformität
|
||||
- **Ausweisdaten:** Verschlüsselt in PostgreSQL gespeichert (AES-256), Zugriff nur Admin + Buchhaltung
|
||||
- **Personendaten:** DSGVO-konform, Löschkonzept für Kunden-Daten (Aufbewahrungsfristen beachten)
|
||||
- **OpenRouter:** Cloud-Verarbeitung akzeptiert, keine Ausweisdaten an KI senden
|
||||
- **Audit-Log:** Alle Änderungen an Kundendaten werden protokolliert (Wer, Was, Wann)
|
||||
|
||||
### Geldwäsche-Prävention (GwG)
|
||||
- Identifikation bei Barzahlungen > 10.000 € (Ausweisdaten erfassen)
|
||||
- Meldepflicht wird systemseitig angezeigt
|
||||
- Meldedokument wird vorbereitet
|
||||
- Dokumentation der Identifikation im Kaufvertrag
|
||||
|
||||
### Technische Sicherheit
|
||||
- **CSRF:** Token-basiert (FastAPI + Next.js)
|
||||
- **XSS:** Input-Sanitization, CSP-Headers
|
||||
- **SQL-Injection:** ORM (SQLAlchemy), keine raw SQL queries
|
||||
- **File-Upload-Validation:** MIME-Type-Check, Größenlimit 50MB, Virenscan empfohlen
|
||||
- **Auth:** JWT-basiert, Session-Timeout 30min, Refresh-Token
|
||||
- **HTTPS:** Via Coolify/Traefik (Let's Encrypt)
|
||||
|
||||
---
|
||||
|
||||
## 9. Constraints (Technische Rahmenbedingungen)
|
||||
|
||||
### Tech-Stack (finalisiert)
|
||||
- **Backend:** Python 3.12+ / FastAPI
|
||||
- **Frontend:** React 18+ / Next.js 14+ / TypeScript
|
||||
- **Datenbank:** PostgreSQL 16+
|
||||
- **ORM:** SQLAlchemy 2.0 (async)
|
||||
- **KI/OCR/Bild:** OpenRouter API (Qwen2.5-VL, Flux.1-Pro, Claude/GPT-4)
|
||||
- **Auth:** JWT (python-jose) + bcrypt
|
||||
- **PDF-Generierung:** WeasyPrint oder ReportLab
|
||||
- **DATEV-Export:** CSV (Python csv module)
|
||||
- **i18n:** next-intl (Next.js) + FastAPI gettext
|
||||
|
||||
### Hosting
|
||||
- **Plattform:** Coolify self-hosted auf eigenem Server
|
||||
- **Container:** Docker Compose (app, db, redis optional)
|
||||
- **SSL:** Let's Encrypt via Traefik
|
||||
- **Domain:** Zu klären (Coolify verwaltet)
|
||||
|
||||
### Externe APIs
|
||||
- **mobile.de Seller API:** REST API (Push-Only)
|
||||
- **OpenRouter:** LLM + Vision + Bildgenerierung
|
||||
- **BZSt eVatR API:** NICHT verfügbar im MVP (manuelle Prüfung)
|
||||
- **DATEV:** Keine API, CSV-Export
|
||||
|
||||
### Budget/Timeline
|
||||
- API-Kosten: OpenRouter (pay-per-use), mobile.de (Händleraccount)
|
||||
- Timeline: MVP-Phasen sequenziell, keine harten Deadlines
|
||||
|
||||
---
|
||||
|
||||
## 10. Non-Goals (Explizit nicht Teil des Systems)
|
||||
|
||||
- **Kein** komplettes Buchhaltungssystem (Fibu, Bilanz, Steuererklärung)
|
||||
- **Kein** Werkstatt-/Reparatur-Auftragsmanagement
|
||||
- **Kein** Ersatzteil-/Lagerverwaltung
|
||||
- **Kein** Fuhrparkmanagement / Telematik
|
||||
- **Kein** eigenes Zahlungs-Gateway (Zahlungsabwicklung extern)
|
||||
- **Kein** mobile App (nur responsive Web-UI)
|
||||
- **Kein** eigenes KI-Modell-Training (Nutzung externer APIs via OpenRouter)
|
||||
- **Kein** Marketing-/Newsletter-System
|
||||
- **Kein** Versandlogistik-/Transportmanagement
|
||||
- **Kein** mobile.de Import (nur Push, NICHT bidirektional)
|
||||
- **Kein** BZSt eVatR API-Integration im MVP (manuelle Prüfung)
|
||||
- **Keine** Datenmigration (keine Bestandsdaten zu importieren)
|
||||
|
||||
---
|
||||
|
||||
## 11. Annahmen (Assumptions)
|
||||
|
||||
1. Der User hat einen aktiven mobile.de Händleraccount mit Seller API-Zugang
|
||||
2. Der User verfügt über deutsche Zulassungsbescheinigungen (ZB I und ZB II) für OCR-Erfassung
|
||||
3. Der User ist umsatzsteuerpflichtig und benötigt USt-IdNr.-Prüfung für EU-Lieferungen
|
||||
4. Der User verkauft an B2B (Firmen) und ggf. B2C (Privatkunden)
|
||||
5. Der User hat Budget für OpenRouter API-Kosten (pay-per-use)
|
||||
6. Das System wird von ~10 Nutzern im Büro genutzt (kein Massen-System)
|
||||
7. Rechtsdokumente basieren auf deutschem/EU-Recht
|
||||
8. KI-Copilot benötigt Internetverbindung (OpenRouter Cloud)
|
||||
9. DSGVO: Cloud-Verarbeitung via OpenRouter ist akzeptiert
|
||||
10. BZSt eVatR API-Zugang ist NICHT vorhanden – manuelle Prüfung im MVP
|
||||
11. Keine Datenmigration von Altsystemen nötig
|
||||
12. Vertragsvorlagen werden als Stammdaten vom Admin gepflegt
|
||||
13. KI darf selbstständig handeln (nach User-Bestätigung)
|
||||
14. ~10 Nutzer mit Rollen Admin/Verkäufer/Buchhaltung
|
||||
15. i18n: Deutsch + Englisch von Anfang an
|
||||
|
||||
---
|
||||
|
||||
## 12. Discovery Checklist (20 Kategorien)
|
||||
|
||||
| # | Kategorie | Status | Anmerkung |
|
||||
|---|-----------|--------|-----------|
|
||||
| 1 | Auth | **ja** | JWT-Auth, 3 Rollen (Admin/Verkäufer/Buchhaltung), ~10 Nutzer, Session-Timeout 30min |
|
||||
| 2 | Daten | **ja** | Validierung, Pagination, Search/Filter in M1/M3 definiert, Soft-Delete für Fahrzeuge/Kontakte |
|
||||
| 3 | Fehler | **ja** | Toast-Notifications, Error-Pages (404/500), API-Fehler-Handling, Error-Logging |
|
||||
| 4 | Skalierung | **nein** | ~10 Nutzer, keine Skalierungsanforderungen, keine Caching/Rate-Limiting nötig |
|
||||
| 5 | Sicherheit | **ja** | CSRF, XSS, SQL-Injection-Schutz, File-Upload-Validation, DSGVO, Ausweisdaten verschlüsselt |
|
||||
| 6 | UX | **ja** | Responsive (M6), Loading-States, Empty-States, Confirmation-Dialogs, i18n DE+EN |
|
||||
| 7 | Infrastruktur | **später** | Backup/Restore via Coolify, Monitoring/Alerting später, Health-Checks via FastAPI |
|
||||
| 8 | Multi-User | **ja** | ~10 Nutzer, 3 Rollen, Concurrency via DB-Locking (optimistic), keine Real-time-Updates nötig |
|
||||
| 9 | Migration | **nein** | Keine Datenmigration nötig (keine Altsysteme) |
|
||||
| 10 | Mobile | **ja** | Responsive Web-UI (M6), keine native App, Touch-optimiert |
|
||||
| 11 | Integration | **ja** | mobile.de Seller API (Push), OpenRouter (LLM/Vision/Bild), DATEV-Export (CSV) |
|
||||
| 12 | Compliance | **ja** | DSGVO, Geldwäsche-Prävention (GwG), USt-IdNr.-Prüfung (manuell), Audit-Log |
|
||||
| 13 | Performance | **später** | Standard-Optimierung, PostgreSQL-Indizes, Lazy Loading, keine speziellen Anforderungen |
|
||||
| 14 | i18n | **ja** | Deutsch + Englisch, Datums-/Zahlenformate, Sprache pro User einstellbar |
|
||||
| 15 | Accessibility | **später** | Grundlegende WCAG-Konformität (Keyboard-Nav, Kontrast), Standard-Implementation |
|
||||
| 16 | Analytics/Tracking | **nein** | Kein Usage-Tracking im MVP |
|
||||
| 17 | Environments | **ja** | Dev + Prod via Coolify (Docker), Env-Variablen in Coolify, Secrets-Management via Coolify |
|
||||
| 18 | Dokumentation | **später** | User-Docs/API-Docs nach MVP, OpenAPI-Auto-Docs via FastAPI verfügbar |
|
||||
| 19 | Testing-Strategie | **ja** | pytest (Backend), jest/playwright (Frontend), Coverage-Target ≥80%, E2E für Kernprozesse |
|
||||
| 20 | Naming/Branding | **später** | Projektname/Branding – zu klären mit User, Domain via Coolify |
|
||||
| 21 | Scheduling/Background-Jobs | **später** | mobile.de Sync ggf. als Cron-Job – MVP: manuell, OpenRouter API-Calls async |
|
||||
|
||||
**Status: 21/21 Kategorien beantwortet** (Kategorie 21 = Scheduling, optional)
|
||||
|
||||
---
|
||||
|
||||
## 13. Test Coverage Summary
|
||||
|
||||
| Feature ID | Feature | Test Scenarios | Status |
|
||||
|---|---|---|---|
|
||||
| F-M1-01 | Fahrzeugbestand verwalten | 3 | ✅ |
|
||||
| F-M1-02 | mobile.de Push-Sync | 3 | ✅ |
|
||||
| F-M1-03 | mobile.de Listing-Verwaltung | 3 | ✅ |
|
||||
| F-M2-01 | OCR ZB I (Qwen2.5-VL) | 3 | ✅ |
|
||||
| F-M2-02 | OCR ZB II (Qwen2.5-VL) | 3 | ✅ |
|
||||
| F-M3-01 | Kontakt- und Kundenverwaltung | 3 | ✅ |
|
||||
| F-M3-02 | Kundensuche und Filter | 3 | ✅ |
|
||||
| F-M4-01 | Dateiablage pro Fahrzeug | 3 | ✅ |
|
||||
| F-M5-01 | Kaufvertrag erstellen | 3 | ✅ |
|
||||
| F-M5-02 | USt-IdNr.-Überprüfung (manuell) | 3 | ✅ |
|
||||
| F-M5-03 | Geldwäsche-Prävention | 3 | ✅ |
|
||||
| F-M5-04 | Rechnung und Lieferbescheinigung | 3 | ✅ |
|
||||
| F-M5-05 | DATEV-Export | 3 | ✅ |
|
||||
| F-M5-06 | Vertragsvorlagen-Verwaltung | 3 | ✅ |
|
||||
| F-M6-01 | Responsive Web-UI | 3 | ✅ |
|
||||
| F-M6-02 | Internationalisierung (i18n) | 3 | ✅ |
|
||||
| F-M7-01 | KI-Copilot – Fahrzeug anlegen | 3 | ✅ |
|
||||
| F-M7-02 | KI-Copilot – Suchen und Verkaufen | 3 | ✅ |
|
||||
| F-M7-03 | KI-Copilot – Dokumente erstellen | 3 | ✅ |
|
||||
| F-M7-04 | KI-Copilot – Spracheingabe | 3 | ✅ |
|
||||
| F-M8-01 | KI Bildretusche – Hintergrund (Flux.1-Pro) | 3 | ✅ |
|
||||
| F-M8-02 | KI Bildretusche – Spiegelungen (Flux.1-Pro) | 3 | ✅ |
|
||||
| F-M8-03 | Preisvergleich mobile.de | 3 | ✅ |
|
||||
|
||||
**Test Coverage: 23/23 Features mit Test-Szenarien (100%)**
|
||||
|
||||
---
|
||||
|
||||
## 14. Handoff Summary
|
||||
|
||||
- **Requirements Status:** Final – Discovery abgeschlossen
|
||||
- **Discovery Checklist:** 21/21 Kategorien beantwortet
|
||||
- **Test Coverage:** 23/23 Features mit je 3 Test-Szenarien (100%)
|
||||
- **Module:** 8 (M1-M8)
|
||||
- **Features:** 23
|
||||
- **MVP-Phasen:** 7 Phasen + 1 Querschnitt (M6)
|
||||
- **Open Questions:** Siehe open_questions.md (alle resolved oder als „später" markiert)
|
||||
- **Ready for UI Design:** YES
|
||||
- **Ready for Architecture:** NO (erst nach UI Design Approval)
|
||||
|
||||
---
|
||||
|
||||
## 15. Offene Fragen
|
||||
|
||||
Siehe `open_questions.md` für kategorisierte Klärungsfragen mit resolved/unresolved Status.
|
||||
@@ -0,0 +1,353 @@
|
||||
{
|
||||
"project": "erp-nutzfahrzeuge",
|
||||
"version": "1.0.0",
|
||||
"created": "2026-07-12",
|
||||
"mvp_phase_order": ["T01", "T02", "T03", "T04", "T05", "T06", "T07"],
|
||||
"cross_cutting": "M6 (Responsive UI + i18n) is integrated into every task",
|
||||
"total_tasks": 7,
|
||||
"tasks": [
|
||||
{
|
||||
"id": "T01",
|
||||
"title": "Core Infrastructure + Auth + Shared UI Foundation",
|
||||
"module": "M6 (cross-cutting) + Auth + Users",
|
||||
"mvp_phase": "Phase 0 – Foundation",
|
||||
"description": "Complete project setup for backend (FastAPI + SQLAlchemy async + Alembic) and frontend (Next.js 14 + Tailwind + next-intl). Implements: database connection, config management (pydantic-settings), JWT auth service (login, refresh, logout with Redis token store), RBAC middleware, user management CRUD (admin only), audit_log model + middleware, health endpoint, i18n backend (Accept-Language). Frontend: App shell with Sidebar + Topbar, login page, JWT token management, API client, i18n setup (de/en), all shared UI components (Button, Card, Input, Select, Textarea, Label, Badge, Spinner, EmptyState, ErrorState, Avatar, Toast, ToastContainer, Tabs, Pagination, Toggle, ProgressBar, WarningBanner, DataTable, InfoGrid, Dropzone, Icon system). Dashboard view with KPI cards.",
|
||||
"dependencies": [],
|
||||
"requirement_ids": ["F-M6-01", "F-M6-02", "Auth", "UserManagement"],
|
||||
"estimated_lines": 800,
|
||||
"assigned_subagent": "implementation_engineer",
|
||||
"acceptance_criteria": [
|
||||
"POST /api/v1/auth/login with valid credentials returns 200 + JWT + refresh_token",
|
||||
"POST /api/v1/auth/login with invalid credentials returns 401",
|
||||
"POST /api/v1/auth/refresh with valid refresh_token returns 200 + new JWT",
|
||||
"POST /api/v1/auth/refresh with invalid refresh_token returns 401",
|
||||
"GET /api/v1/auth/me with valid JWT returns 200 + user data + role",
|
||||
"GET /api/v1/auth/me without JWT returns 401",
|
||||
"GET /api/v1/users without admin role returns 403",
|
||||
"GET /api/v1/users with admin role returns 200 + paginated user list",
|
||||
"POST /api/v1/users creates user, returns 201",
|
||||
"PUT /api/v1/users/:id updates user, returns 200",
|
||||
"DELETE /api/v1/users/:id soft-deletes user (is_active=false), returns 200",
|
||||
"GET /api/v1/health returns 200",
|
||||
"Audit log entry created on login, user create, user update, user delete",
|
||||
"Frontend: Login page renders, login form submits, JWT stored, redirect to dashboard",
|
||||
"Frontend: Sidebar shows navigation items filtered by role",
|
||||
"Frontend: Language switch (DE/EN) updates all UI texts",
|
||||
"Frontend: Responsive layout works at 375px, 768px, 1920px breakpoints",
|
||||
"All shared UI components render correctly with all states"
|
||||
],
|
||||
"test_spec": {
|
||||
"commands": [
|
||||
"cd backend && python -m pytest tests/test_auth.py tests/test_users.py -v --cov=app --cov-report=term-missing",
|
||||
"cd backend && ruff check app/",
|
||||
"cd frontend && npx vitest run src/components/ui src/lib --coverage",
|
||||
"cd frontend && npx eslint src/ --max-warnings 0",
|
||||
"cd frontend && npm run build"
|
||||
],
|
||||
"expected_results": "All auth tests pass (login, refresh, logout, RBAC). User CRUD tests pass. Ruff lint clean. Frontend component tests pass. ESLint clean. Next.js build succeeds.",
|
||||
"test_files": [
|
||||
"backend/tests/test_auth.py",
|
||||
"backend/tests/test_users.py",
|
||||
"backend/tests/conftest.py",
|
||||
"frontend/src/components/ui/__tests__/Button.test.tsx",
|
||||
"frontend/src/components/ui/__tests__/Input.test.tsx",
|
||||
"frontend/src/lib/__tests__/auth.test.ts",
|
||||
"frontend/src/lib/__tests__/api-client.test.ts"
|
||||
],
|
||||
"coverage_target": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "T02",
|
||||
"title": "Vehicle Management + mobile.de Push-Sync",
|
||||
"module": "M1",
|
||||
"mvp_phase": "Phase 1 – Core Function",
|
||||
"description": "Complete vehicle management system. Backend: vehicles model (with type-specific fields for LKW/PKW/Baumaschine/Stapler/Transporter), vehicle_service (CRUD + filter by type/availability/price range + search + sort + pagination + soft-delete), vehicle router (5 endpoints), FIN validation (17 chars, unique). mobile_de_listings model, mobile_de_service (push_listing, update_listing, delete_listing, get_status, batch_push, field mapping ERP→mobile.de), mobile_de router (5 endpoints). Frontend: FahrzeugListe (filterable/sortable table with search, pagination, mobile.de status badges), FahrzeugDetail (7 tabs: Allgemein, Technisch, Baumaschinen, Verkaufsinfo, Dokumente, Fotos, mobile.de), FahrzeugForm (with type-specific conditional fields, OCR upload placeholder, validation), mobile.de listing management view with batch push and error logs.",
|
||||
"dependencies": ["T01"],
|
||||
"requirement_ids": ["F-M1-01", "F-M1-02", "F-M1-03"],
|
||||
"estimated_lines": 700,
|
||||
"assigned_subagent": "implementation_engineer",
|
||||
"acceptance_criteria": [
|
||||
"GET /api/v1/vehicles returns 200 with paginated, filterable, sortable vehicle list",
|
||||
"GET /api/v1/vehicles?type=baumaschine&min_price=10000&max_price=50000 returns only matching vehicles",
|
||||
"GET /api/v1/vehicles?search=mercedes returns vehicles matching make or model",
|
||||
"POST /api/v1/vehicles with valid data returns 201, vehicle appears in list",
|
||||
"POST /api/v1/vehicles with duplicate FIN returns 409 'FIN bereits vorhanden'",
|
||||
"POST /api/v1/vehicles with FIN != 17 chars returns 422 validation error",
|
||||
"POST /api/v1/vehicles with vehicle_type=baumaschine and operating_hours saves correctly",
|
||||
"GET /api/v1/vehicles/:id returns 200 with full vehicle detail",
|
||||
"PUT /api/v1/vehicles/:id updates fields, returns 200",
|
||||
"DELETE /api/v1/vehicles/:id soft-deletes (deleted_at set), returns 200, not in list",
|
||||
"POST /api/v1/vehicles/:id/mobile-de/push with complete data returns 200, sync_status='gelistet'",
|
||||
"POST /api/v1/vehicles/:id/mobile-de/push with missing required fields returns 400, sync_status='fehler'",
|
||||
"POST /api/v1/mobile-de/batch-push with 3 vehicles pushes all, returns summary",
|
||||
"DELETE /api/v1/vehicles/:id/mobile-de/listing returns 200, sync_status='entfernt'",
|
||||
"GET /api/v1/mobile-de/listings returns listings filtered by sync_status",
|
||||
"Buchhaltung role: GET /api/v1/vehicles returns 200 (read-only), POST returns 403",
|
||||
"Frontend: FahrzeugListe renders with filter bar, sortable columns, pagination",
|
||||
"Frontend: FahrzeugForm shows Baumaschine fields conditionally when type=baumaschine",
|
||||
"Frontend: FahrzeugDetail shows 7 tabs with correct data",
|
||||
"Frontend: mobile.de batch push shows progress, errors per vehicle"
|
||||
],
|
||||
"test_spec": {
|
||||
"commands": [
|
||||
"cd backend && python -m pytest tests/test_vehicles.py tests/test_mobile_de.py -v --cov=app/routers/vehicles --cov=app/routers/mobile_de --cov=app/services/vehicle_service --cov=app/services/mobile_de_service --cov-report=term-missing",
|
||||
"cd backend && ruff check app/routers/vehicles.py app/routers/mobile_de.py app/services/vehicle_service.py app/services/mobile_de_service.py app/models/vehicle.py app/models/mobile_de.py",
|
||||
"cd frontend && npx vitest run src/components/vehicles --coverage",
|
||||
"cd frontend && npm run build"
|
||||
],
|
||||
"expected_results": "All vehicle CRUD tests pass. FIN validation tests pass. mobile.de push/batch/delisting tests pass (mocked API). Filter/search/pagination tests pass. RBAC tests pass. Ruff lint clean. Frontend component tests pass. Build succeeds.",
|
||||
"test_files": [
|
||||
"backend/tests/test_vehicles.py",
|
||||
"backend/tests/test_mobile_de.py",
|
||||
"frontend/src/components/vehicles/__tests__/FahrzeugListe.test.tsx",
|
||||
"frontend/src/components/vehicles/__tests__/FahrzeugForm.test.tsx",
|
||||
"frontend/src/components/vehicles/__tests__/FahrzeugDetail.test.tsx"
|
||||
],
|
||||
"coverage_target": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "T03",
|
||||
"title": "Contact & Customer Management",
|
||||
"module": "M3",
|
||||
"mvp_phase": "Phase 2 – Precondition for Sales",
|
||||
"description": "Complete contact management system. Backend: contacts model (company_name, legal_form, address, country, vat_id, role kaeufer/verkaeufer/beide, vat_id_status, is_private, soft-delete), contact_persons model (name, function, phone, email), ust_id_status_history model. contact_service (CRUD + search by name/country/role/vat_id_status + filter + sort + pagination + soft-delete + cascade delete contact_persons), contact router (5 endpoints). Frontend: KontakteListe (with filter by role, country, USt-IdNr.-status, search, sort, pagination), contact detail/form with contact persons sub-form, USt-IdNr. status badge component.",
|
||||
"dependencies": ["T01"],
|
||||
"requirement_ids": ["F-M3-01", "F-M3-02"],
|
||||
"estimated_lines": 450,
|
||||
"assigned_subagent": "implementation_engineer",
|
||||
"acceptance_criteria": [
|
||||
"GET /api/v1/contacts returns 200 with paginated, filterable contact list",
|
||||
"GET /api/v1/contacts?role=kaeufer&country=DE returns only German buyers",
|
||||
"GET /api/v1/contacts?search=Müller returns contacts matching company_name",
|
||||
"GET /api/v1/contacts?vat_id_status=geprueft returns only checked contacts",
|
||||
"POST /api/v1/contacts with valid company data returns 201",
|
||||
"POST /api/v1/contacts with is_private=true and no vat_id returns 201 (vat_id optional for private)",
|
||||
"GET /api/v1/contacts/:id returns 200 with contact + contact_persons array",
|
||||
"PUT /api/v1/contacts/:id updates fields including contact_persons, returns 200",
|
||||
"DELETE /api/v1/contacts/:id soft-deletes, contact_persons cascaded, returns 200",
|
||||
"Buchhaltung role: GET returns 200 (read-only), POST/PUT/DELETE returns 403",
|
||||
"Frontend: KontakteListe renders with filters, search, pagination",
|
||||
"Frontend: Contact form with contact persons sub-form (add/remove persons)",
|
||||
"Frontend: USt-IdNr. status badge shows correct color per status"
|
||||
],
|
||||
"test_spec": {
|
||||
"commands": [
|
||||
"cd backend && python -m pytest tests/test_contacts.py -v --cov=app/routers/contacts --cov=app/services/contact_service --cov=app/models/contact --cov-report=term-missing",
|
||||
"cd backend && ruff check app/routers/contacts.py app/services/contact_service.py app/models/contact.py",
|
||||
"cd frontend && npx vitest run src/components/contacts --coverage",
|
||||
"cd frontend && npm run build"
|
||||
],
|
||||
"expected_results": "All contact CRUD tests pass. Search/filter tests pass. Contact persons cascade test passes. Soft-delete test passes. RBAC tests pass. Ruff lint clean. Frontend tests pass. Build succeeds.",
|
||||
"test_files": [
|
||||
"backend/tests/test_contacts.py",
|
||||
"frontend/src/components/contacts/__tests__/KontakteListe.test.tsx",
|
||||
"frontend/src/components/contacts/__tests__/ContactForm.test.tsx"
|
||||
],
|
||||
"coverage_target": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "T04",
|
||||
"title": "Document Management & File Storage",
|
||||
"module": "M4",
|
||||
"mvp_phase": "Phase 3 – Precondition for OCR/Retouch",
|
||||
"description": "Complete document/file management system. Backend: documents model (vehicle_id FK, sale_id FK nullable, filename, file_path, file_type MIME, file_size, category, uploaded_by). document_service (upload with MIME-type allowlist + size validation ≤50MB, storage to local filesystem under /data/uploads/vehicles/{vehicle_id}/, thumbnail generation for images via Pillow, file delete, list with category filter, StorageBackend abstraction interface for future S3). document router (3 endpoints: list, upload, delete + download endpoint). Frontend: document upload Dropzone component (drag-and-drop, progress, validation), document grid with category filter, image preview lightbox, PDF iframe preview, file size display.",
|
||||
"dependencies": ["T02"],
|
||||
"requirement_ids": ["F-M4-01"],
|
||||
"estimated_lines": 400,
|
||||
"assigned_subagent": "implementation_engineer",
|
||||
"acceptance_criteria": [
|
||||
"GET /api/v1/vehicles/:id/documents returns 200 with document list filtered by category",
|
||||
"POST /api/v1/vehicles/:id/documents with valid PDF (≤50MB) returns 201, file stored, document row created",
|
||||
"POST /api/v1/vehicles/:id/documents with file >50MB returns 413 'Datei zu groß'",
|
||||
"POST /api/v1/vehicles/:id/documents with invalid MIME type returns 415",
|
||||
"POST /api/v1/vehicles/:id/documents with image generates thumbnail",
|
||||
"DELETE /api/v1/vehicles/:id/documents/:doc_id removes file from disk + DB row, returns 200",
|
||||
"GET document download returns file with correct Content-Type header",
|
||||
"Buchhaltung role: GET returns 200 (read-only), POST/DELETE returns 403",
|
||||
"Frontend: Dropzone accepts drag-and-drop, shows upload progress",
|
||||
"Frontend: Document grid shows files with category icons, size, upload date",
|
||||
"Frontend: Image preview opens in lightbox, PDF opens in iframe",
|
||||
"Frontend: Category filter works (Vertrag, Rechnung, ZB I, ZB II, Foto, Sonstiges)"
|
||||
],
|
||||
"test_spec": {
|
||||
"commands": [
|
||||
"cd backend && python -m pytest tests/test_documents.py -v --cov=app/routers/documents --cov=app/services/document_service --cov=app/models/document --cov-report=term-missing",
|
||||
"cd backend && ruff check app/routers/documents.py app/services/document_service.py app/models/document.py app/utils/",
|
||||
"cd frontend && npx vitest run src/components/documents --coverage",
|
||||
"cd frontend && npm run build"
|
||||
],
|
||||
"expected_results": "All document upload/delete/list tests pass. MIME validation test passes. Size limit test passes. Thumbnail generation test passes. RBAC tests pass. Ruff lint clean. Frontend tests pass. Build succeeds.",
|
||||
"test_files": [
|
||||
"backend/tests/test_documents.py",
|
||||
"frontend/src/components/documents/__tests__/Dropzone.test.tsx",
|
||||
"frontend/src/components/documents/__tests__/DocumentGrid.test.tsx"
|
||||
],
|
||||
"coverage_target": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "T05",
|
||||
"title": "OCR Service + OpenRouter Integration",
|
||||
"module": "M2",
|
||||
"mvp_phase": "Phase 4 – Efficiency Feature",
|
||||
"description": "Complete OCR integration via OpenRouter. Backend: openrouter_client.py (shared async HTTP client with httpx, chat_completion for LLM, vision_completion for Qwen2.5-VL, image_generation for Flux.1-Pro, timeout handling, error handling, token tracking). ocr_service.py (ZB I field extraction, ZB II field extraction, image quality check warning, FIN cross-validation between ZB I and ZB II with discrepancy warning, field mapping to vehicle schema). ai_interactions model (log all AI calls with type, input, output, model, tokens, metadata). OCR router endpoints (2: POST zb1, POST zb2). Frontend: OCR upload Dropzone integrated into FahrzeugForm, OCR loading state, OCR results display with editable fields, quality warnings display, FIN mismatch warning.",
|
||||
"dependencies": ["T02", "T04"],
|
||||
"requirement_ids": ["F-M2-01", "F-M2-02"],
|
||||
"estimated_lines": 500,
|
||||
"assigned_subagent": "implementation_engineer",
|
||||
"acceptance_criteria": [
|
||||
"POST /api/v1/vehicles/ocr/zb1 with valid image returns 200 + extracted fields (make, fin, first_registration, etc.)",
|
||||
"POST /api/v1/vehicles/ocr/zb2 with valid image returns 200 + extracted fields (fin, hersteller, typ, etc.)",
|
||||
"OCR response includes confidence score and warnings array",
|
||||
"OCR response with low-quality image includes warning 'Bildqualität niedrig'",
|
||||
"POST /api/v1/vehicles/ocr/zb1 logs interaction in ai_interactions table",
|
||||
"OCR endpoint rejects non-image files with 415",
|
||||
"OCR endpoint rejects images >10MB with 413",
|
||||
"OpenRouter API error returns 502 with graceful error message",
|
||||
"OpenRouter client timeout (30s) returns 504",
|
||||
"Buchhaltung role: POST OCR returns 403",
|
||||
"Frontend: OCR upload in FahrzeugForm triggers loading state",
|
||||
"Frontend: OCR results auto-fill form fields, all editable",
|
||||
"Frontend: Quality warning banner displayed when warnings present",
|
||||
"Frontend: FIN mismatch warning when ZB I and ZB II FINs differ",
|
||||
"Tests mock OpenRouter API (no real API calls in CI)"
|
||||
],
|
||||
"test_spec": {
|
||||
"commands": [
|
||||
"cd backend && python -m pytest tests/test_ocr.py tests/test_openrouter_client.py -v --cov=app/services/ocr_service --cov=app/services/openrouter_client --cov=app/routers/ai --cov-report=term-missing",
|
||||
"cd backend && ruff check app/services/ocr_service.py app/services/openrouter_client.py app/routers/ai.py",
|
||||
"cd frontend && npx vitest run src/components/vehicles/__tests__/OCRUpload.test.tsx --coverage",
|
||||
"cd frontend && npm run build"
|
||||
],
|
||||
"expected_results": "All OCR tests pass with mocked OpenRouter. Field extraction tests pass. Quality warning test passes. FIN cross-validation test passes. Token tracking test passes. Error handling tests pass (timeout, API error). RBAC test passes. Ruff lint clean. Frontend tests pass. Build succeeds.",
|
||||
"test_files": [
|
||||
"backend/tests/test_ocr.py",
|
||||
"backend/tests/test_openrouter_client.py",
|
||||
"frontend/src/components/vehicles/__tests__/OCRUpload.test.tsx"
|
||||
],
|
||||
"coverage_target": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "T06",
|
||||
"title": "Sales Module + Legal Documents + Compliance",
|
||||
"module": "M5",
|
||||
"mvp_phase": "Phase 5 – Business Process",
|
||||
"description": "Complete sales module with legal document generation and compliance features. Backend: sales model (vehicle_id, buyer_id, seller_id, sale_type, price_net/gross, vat_rate, payment_method, status, contract_number, invoice_number). identification_data model (AES-256-GCM encrypted ID number). ust_id_checks model. contract_templates model. settings model (firmenprofil, system config). sale_service (CRUD + status workflow + contract number generation + invoice number generation). contract_service (WeasyPrint PDF generation from templates with Jinja2 variable replacement, supports inland/eu_ausland/drittland variants). datev_service (CSV export with date range filter, DATEV format). gwg_service (GwG warning >10000 EUR bar, identification data encryption/decryption). ust_id_service (manual check entry, warning for EU without check). settings_service (firmenprofil, master_data CRUD, contract_templates CRUD). Routers: sales (6 endpoints), compliance (3 endpoints), datev (1), settings (6+ endpoints). Frontend: VerkaufsModul 4-step wizard (Fahrzeug/Kunde → Vertragsdetails → Prüfung → Abschluss), GwG warning banner, USt-IdNr. warning, Einstellungen view (4 tabs: Stammdaten, Vertragsvorlagen, Benutzerverwaltung, Firmenprofil).",
|
||||
"dependencies": ["T02", "T03"],
|
||||
"requirement_ids": ["F-M5-01", "F-M5-02", "F-M5-03", "F-M5-04", "F-M5-05", "F-M5-06"],
|
||||
"estimated_lines": 800,
|
||||
"assigned_subagent": "implementation_engineer",
|
||||
"acceptance_criteria": [
|
||||
"GET /api/v1/sales returns 200 with paginated, filterable sales list",
|
||||
"POST /api/v1/sales with valid vehicle_id + buyer_id returns 201",
|
||||
"GET /api/v1/sales/:id returns 200 with sale detail",
|
||||
"PUT /api/v1/sales/:id updates status/data, returns 200",
|
||||
"POST /api/v1/sales/:id/contract generates PDF, returns 200 + PDF download",
|
||||
"Contract PDF for inland sale includes USt (19%)",
|
||||
"Contract PDF for drittland sale includes 0% USt + Ausfuhrvermerke",
|
||||
"POST /api/v1/sales/:id/invoice generates invoice PDF with sequential invoice_number",
|
||||
"POST /api/v1/sales/:id/ust-id-check with manual result returns 200, updates contact vat_id_status",
|
||||
"POST /api/v1/sales/:id/identification with GwG data encrypts ID number (AES-256), returns 200",
|
||||
"GET identification data decrypts only for admin/buchhaltung role",
|
||||
"Sale with barzahlung >10000 EUR triggers GwG warning in response",
|
||||
"EU-Ausland sale without checked USt-IdNr. triggers warning in response",
|
||||
"GET /api/v1/sales/datev-export?from=2026-01-01&to=2026-01-31 returns CSV file",
|
||||
"DATEV export with no sales in range returns CSV with headers only",
|
||||
"GET /api/v1/settings/contract-templates returns 200 with templates list",
|
||||
"POST /api/v1/settings/contract-templates creates template, returns 201",
|
||||
"PUT /api/v1/settings/contract-templates/:id updates template, returns 200",
|
||||
"GET /api/v1/settings/master-data?category=kraftstoffart returns 200 with entries",
|
||||
"RBAC: Verkäufer cannot access invoice/ust-id/identification/datev endpoints (403)",
|
||||
"RBAC: Buchhaltung cannot create sales (403), can access invoice/ust-id/datev (200)",
|
||||
"Frontend: 4-step wizard renders, navigation between steps works",
|
||||
"Frontend: GwG warning banner appears when barzahlung >10000",
|
||||
"Frontend: USt-IdNr. warning appears for EU-Ausland without check",
|
||||
"Frontend: Einstellungen 4 tabs render with correct content per role",
|
||||
"Frontend: Contract template editor with variable highlighting"
|
||||
],
|
||||
"test_spec": {
|
||||
"commands": [
|
||||
"cd backend && python -m pytest tests/test_sales.py tests/test_datev.py tests/test_compliance.py -v --cov=app/routers/sales --cov=app/services/sale_service --cov=app/services/contract_service --cov=app/services/datev_service --cov=app/services/gwg_service --cov=app/services/ust_id_service --cov=app/routers/settings --cov-report=term-missing",
|
||||
"cd backend && ruff check app/routers/sales.py app/services/ app/utils/crypto.py app/utils/pdf.py",
|
||||
"cd frontend && npx vitest run src/components/sales src/components/settings --coverage",
|
||||
"cd frontend && npm run build"
|
||||
],
|
||||
"expected_results": "All sales CRUD tests pass. Contract PDF generation tests pass (inland/eu/drittland). Invoice generation test passes. GwG warning test passes. USt-IdNr. check test passes. DATEV export format test passes. AES encryption/decryption test passes. Settings/contract template CRUD tests pass. RBAC tests pass (all 3 roles). Ruff lint clean. Frontend tests pass. Build succeeds.",
|
||||
"test_files": [
|
||||
"backend/tests/test_sales.py",
|
||||
"backend/tests/test_datev.py",
|
||||
"backend/tests/test_compliance.py",
|
||||
"frontend/src/components/sales/__tests__/VerkaufsModul.test.tsx",
|
||||
"frontend/src/components/settings/__tests__/Einstellungen.test.tsx"
|
||||
],
|
||||
"coverage_target": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "T07",
|
||||
"title": "KI Copilot + Image Retouch + Price Comparison",
|
||||
"module": "M7 + M8",
|
||||
"mvp_phase": "Phase 6+7 – Automation & Optimization",
|
||||
"description": "Complete AI features. Backend: copilot_service.py (parse natural language commands via OpenRouter LLM, structured JSON response with action type + data, execute actions: create vehicle, search vehicles, start sale, generate document, ask for missing data). copilot router (3 endpoints: text, voice, history). voice transcription via OpenRouter or browser Web Speech API. image_retouch_service.py (background removal via Flux.1-Pro, reflection reduction, batch processing). image retouch router (2 endpoints: single, batch). price_comparison_service.py (search mobile.de for similar vehicles, calculate average/median, return comparison data). price comparison router (1 endpoint). All AI interactions logged in ai_interactions. Frontend: KiCopilot chat interface (message list, input box, example commands, voice input button with microphone, loading state), image retouch UI (select photo from vehicle documents, retouch button, before/after preview, save to documents), price comparison view (bar chart with vehicle prices, average/median lines, price distribution).",
|
||||
"dependencies": ["T02", "T04", "T05", "T06"],
|
||||
"requirement_ids": ["F-M7-01", "F-M7-02", "F-M7-03", "F-M7-04", "F-M8-01", "F-M8-02", "F-M8-03"],
|
||||
"estimated_lines": 600,
|
||||
"assigned_subagent": "implementation_engineer",
|
||||
"acceptance_criteria": [
|
||||
"POST /api/v1/ai/copilot with 'Neues Fahrzeug: MAN TGL 2018, 120000 km, 32000 €' returns 200 + structured action {action: 'create_vehicle', data: {make: 'MAN', model: 'TGL', year: 2018, mileage_km: 120000, price: 32000}}",
|
||||
"POST /api/v1/ai/copilot with 'Füge ein Fahrzeug hinzu' (no data) returns 200 + {action: 'ask_for_data', missing_fields: ['make', 'model', 'price']}",
|
||||
"POST /api/v1/ai/copilot with 'Finde alle Fahrzeuge über 50000 €' returns 200 + {action: 'search_vehicles', filters: {min_price: 50000}}",
|
||||
"POST /api/v1/ai/copilot with 'Verkaufe FIN XYZ an Müller GmbH' returns 200 + {action: 'start_sale', vehicle_id: '...', buyer_id: '...'}",
|
||||
"POST /api/v1/ai/copilot/voice with audio file returns 200 + transcribed text + processed action",
|
||||
"GET /api/v1/ai/interactions returns 200 with paginated AI interaction history",
|
||||
"POST /api/v1/ai/image/retouch with image returns 200 + retouched image URL",
|
||||
"POST /api/v1/ai/image/batch-retouch with multiple images returns 200 + progress per image",
|
||||
"GET /api/v1/vehicles/:id/price-comparison returns 200 + similar vehicles list with prices + average + median",
|
||||
"Price comparison for rare vehicle returns 200 + {comparisons: [], message: 'Keine Vergleichsfahrzeuge'}",
|
||||
"All AI endpoints log to ai_interactions table",
|
||||
"Buchhaltung role: GET copilot history returns 200 (read-only), POST copilot returns 403",
|
||||
"Buchhaltung role: POST image retouch returns 403, GET price comparison returns 200 (read-only)",
|
||||
"Frontend: KiCopilot chat renders messages, input, example commands",
|
||||
"Frontend: Voice input button starts recording, shows listening state",
|
||||
"Frontend: Image retouch UI shows before/after preview",
|
||||
"Frontend: Price comparison chart renders with bars, average line, median line",
|
||||
"Tests mock OpenRouter API (no real API calls in CI)"
|
||||
],
|
||||
"test_spec": {
|
||||
"commands": [
|
||||
"cd backend && python -m pytest tests/test_copilot.py tests/test_image_retouch.py tests/test_price_comparison.py -v --cov=app/services/copilot_service --cov=app/services/image_retouch_service --cov=app/services/price_comparison_service --cov=app/routers/ai --cov-report=term-missing",
|
||||
"cd backend && ruff check app/services/copilot_service.py app/services/image_retouch_service.py app/services/price_comparison_service.py app/routers/ai.py",
|
||||
"cd frontend && npx vitest run src/components/ai --coverage",
|
||||
"cd frontend && npm run build"
|
||||
],
|
||||
"expected_results": "All copilot tests pass with mocked OpenRouter (text + voice). Action parsing tests pass. Image retouch tests pass with mocked Flux.1-Pro. Batch processing test passes. Price comparison test passes. RBAC tests pass. All AI interactions logged. Ruff lint clean. Frontend tests pass. Build succeeds.",
|
||||
"test_files": [
|
||||
"backend/tests/test_copilot.py",
|
||||
"backend/tests/test_image_retouch.py",
|
||||
"backend/tests/test_price_comparison.py",
|
||||
"frontend/src/components/ai/__tests__/KiCopilot.test.tsx",
|
||||
"frontend/src/components/ai/__tests__/ImageRetouch.test.tsx",
|
||||
"frontend/src/components/ai/__tests__/PriceComparison.test.tsx"
|
||||
],
|
||||
"coverage_target": 80
|
||||
}
|
||||
}
|
||||
],
|
||||
"cleanup_rules": {
|
||||
"after_migration_tasks": "Run alembic upgrade head, verify all tables created, run seed data script, verify foreign keys, remove any temporary migration scripts",
|
||||
"after_each_task": "Run ruff --fix, run eslint --fix, remove dead code, verify no console.log/print left in production code"
|
||||
},
|
||||
"dependency_graph": {
|
||||
"T01": [],
|
||||
"T02": ["T01"],
|
||||
"T03": ["T01"],
|
||||
"T04": ["T02"],
|
||||
"T05": ["T02", "T04"],
|
||||
"T06": ["T02", "T03"],
|
||||
"T07": ["T02", "T04", "T05", "T06"]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user