feat(reports): DATEV-Monatsblatt-Export (Blanko-Vorlage) für Steuerberater
Neuer PDF-Export GET /reports/datev-monthly/export: ein Blatt pro Mitarbeiter/Monat im Layout der DATEV-Stundenaufzeichnungs-Vorlage (Beginn/Pause/Ende/Dauer + K/U/UU/F/SA/SU-Kürzel + Bemerkungen + Summe + Unterschriftsfelder). Führt time_entries, Absences und Feiertage pro Kalendertag zusammen. Außerdem: Mustervorlagen für neue Backend-Module (Model/Schema/Router/ Migration/Test) und eine Frontend-Page-Vorlage, abgeleitet vom hours_payouts-Modul als aktuellstem sauberen Muster. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CviFgc739S89xS97pvjszj
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
"""TEMPLATE – Mustervorlage für Pydantic-v2-Schemas.
|
||||
|
||||
Anleitung:
|
||||
1. Nach app/schemas/<name>.py kopieren, XxxThing ersetzen
|
||||
2. Computed-Felder (z.B. *_name) im Router nachträglich befüllen, nie im Schema
|
||||
selbst berechnen (Router = einzige Stelle mit DB-Zugriff für den Response-Bau)
|
||||
"""
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class XxxThingCreate(BaseModel):
|
||||
user_id: uuid.UUID
|
||||
note: str | None = Field(None, max_length=500)
|
||||
|
||||
|
||||
class XxxThingReject(BaseModel):
|
||||
rejection_reason: str | None = Field(None, max_length=500)
|
||||
|
||||
|
||||
class XxxThingOut(BaseModel):
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
id: uuid.UUID
|
||||
company_id: uuid.UUID
|
||||
user_id: uuid.UUID
|
||||
user_name: str = "" # Computed im Router (first_name + last_name)
|
||||
note: str | None
|
||||
status: str = "requested"
|
||||
rejection_reason: str | None = None
|
||||
created_by: uuid.UUID
|
||||
created_by_name: str = "" # Computed im Router
|
||||
decided_by: uuid.UUID | None = None
|
||||
decided_by_name: str = "" # Computed im Router
|
||||
decided_at: datetime | None = None
|
||||
created_at: datetime
|
||||
|
||||
|
||||
class XxxThingListResponse(BaseModel):
|
||||
items: list[XxxThingOut]
|
||||
total_count: int
|
||||
Reference in New Issue
Block a user