# Handwerksfreund - Datenstruktur & Domänenmodell Dieses Dokument beschreibt die grundlegende Datenstruktur für das Projekt **Handwerksfreund**. Es dient als Diskussionsgrundlage für die Datenbankmodellierung in Supabase/PostgreSQL. --- ## 1. Entitäten-Übersicht ```mermaid erDiagram KUNDE ||--o{ VERBAUTES_TEIL : "besitzt" KUNDE ||--o{ AUFTRAG : "beauftragt" AUFTRAG ||--o{ VERBAUTES_TEIL : "installiert im Rahmen von" AUFTRAG ||--o{ AUFTRAGS_ANHANG : "enthält n Dokumente/Baupläne" KUNDE ||--o{ TERMIN_EINTRAG : "bezieht sich auf" AUFTRAG ||--o{ TERMIN_EINTRAG : "eingeplant als" ``` --- ## 2. Detaillierte Felddefinitionen ### 2.1 Kunde (`customers`) Stammdaten der Kunden inklusive Geokoordinaten für die Kartendarstellung und Vor-Ort-Notizen. | Feld | Datentyp | Pflichtfeld | Beschreibung / Beispiel | | :--- | :--- | :---: | :--- | | `id` | UUID | Ja | Eindeutige ID (Primärschlüssel) | | `customer_number` | Text | Ja | Eindeutige Kundennummer (z.B. `K-10025`) | | `name` | Text | Ja | Vollständiger Name / Firmenname (z.B. `Max Mustermann`) | | `street` | Text | Ja | Straße & Hausnummer (z.B. `Musterweg 12`) | | `zip_code` | Text | Ja | Postleitzahl (z.B. `12345`) | | `city` | Text | Ja | Stadt (z.B. `Musterstadt`) | | `latitude` | Float (Double) | Ja | Geografische Breite für Karten-Pin | | `longitude` | Float (Double) | Ja | Geografische Länge für Karten-Pin | | `distance_km` | Float (Double) | Nein | Berechnete Entfernung zum Techniker-Standort | | `phone` | Text | Nein | Telefonnummer (z.B. `0171 1234567`) | | `email` | Text | Nein | E-Mail-Adresse (z.B. `max.mustermann@email.de`) | | `notes` | Text | Nein | Vor-Ort-Hinweise (z.B. `Schlüsselbox an der Garage`) | | `first_contact_date` | Datum | Nein | Erstkontakt-Datum (z.B. `10.03.2022`) | | `open_orders_count` | Ganzzahl | Nein | Anzahl offener Aufträge (berechnet oder gecached) | | `last_order_date` | Datum | Nein | Datum des letzten ausgeführten Auftrags | | `created_at` | Zeitstempel | Ja | Erstellungszeitpunkt des Datensatzes | --- ### 2.2 Verbaute Teile / Gerätekartei (`installed_parts`) Alle beim Kunden installierten Geräte, Heizungsanlagen, Thermostate, Filter und Ersatzteile mit Seriennummern. | Feld | Datentyp | Pflichtfeld | Beschreibung / Beispiel | | :--- | :--- | :---: | :--- | | `id` | UUID | Ja | Eindeutige ID (Primärschlüssel) | | `customer_id` | UUID | Ja | Referenz auf den Besitzer (`customers.id`) | | `order_id` | UUID | Nein | Referenz auf den Auftrag, bei dem das Teil verbaut wurde | | `name` | Text | Ja | Produktbezeichnung (z.B. `Buderus Logamax plus GB172-24`) | | `category` | Text | Ja | Geräte-Kategorie (z.B. `Gas-Brennwertgerät`, `Raumthermostat`) | | `serial_number` | Text | Nein | Eindeutige Seriennummer (z.B. `8374747383`) | | `quantity` | Ganzzahl | Ja | Anzahl verbauter Einheiten (Standard: `1`) | | `installed_at` | Datum | Nein | Einbaudatum | | `created_at` | Zeitstempel | Ja | Erstellungszeitpunkt des Datensatzes | --- ### 2.3 Auftrag (`work_orders`) Aufträge und Wartungsarbeiten, die für Kunden angelegt und ausgeführt werden. | Feld | Datentyp | Pflichtfeld | Beschreibung / Beispiel | | :--- | :--- | :---: | :--- | | `id` | UUID | Ja | Eindeutige ID (Primärschlüssel) | | `customer_id` | UUID | Ja | Referenz auf den Kunden (`customers.id`) | | `title` | Text | Ja | Titel des Auftrags (z.B. `Wartung Heizungsanlage`) | | `description` | Text | Nein | Beschreibung & Aufgabenstellung | | `status` | Enum | Ja | Status: `offen`, `inBearbeitung`, `abgeschlossen`, `storniert` | | `scheduled_date` | Datum | Nein | Geplantes Ausführungsdatum | | `completed_at` | Zeitstempel | Nein | Zeitpunkt der Fertigstellung | | `created_at` | Zeitstempel | Ja | Erstellungszeitpunkt | --- ### 2.4 Auftrags-Anhänge & Dokumente (`order_attachments`) 📄📍 Baupläne, CAD-Zeichnungen, Fotos vor Ort, Schaltpläne und Misc-Dateien zu einem Auftrag. > **Speicherung in Supabase**: Die eigentliche Datei (z.B. PDF, PNG) liegt im **Supabase Storage Bucket** (`order-files`). In dieser DB-Tabelle speichern wir die Metadaten & den Storage-Pfad. | Feld | Datentyp | Pflichtfeld | Beschreibung / Beispiel | | :--- | :--- | :---: | :--- | | `id` | UUID | Ja | Eindeutige ID (Primärschlüssel) | | `order_id` | UUID | Ja | Referenz auf den Auftrag (`work_orders.id`) | | `title` | Text | Ja | Name der Datei / Anzeige-Titel (z.B. `Bauplan EG - Sanitär.pdf`) | | `category` | Enum / Text | Ja | Kategorie: `bauplan`, `schaltplan`, `foto_vor_ort`, `abnahmeprotokoll`, `sonstiges` | | `file_path` | Text | Ja | Pfad im Supabase Storage Bucket (z.B. `orders/ord-123/bauplan_eg.pdf`) | | `file_size_bytes` | Ganzzahl | Nein | Dateigröße in Bytes (z.B. `2458120` für ~2.4 MB) | | `mime_type` | Text | Nein | Dateityp (z.B. `application/pdf`, `image/png`) | | `uploaded_at` | Zeitstempel | Ja | Upload-Zeitpunkt | --- ### 2.5 Termin-Eintrag / Tagesplan (`schedule_items`) Zeitleisten-Einträge für die Tages- und Wochenansicht (Aufträge, Besprechungen, Mittagspause, Feierabend). | Feld | Datentyp | Pflichtfeld | Beschreibung / Beispiel | | :--- | :--- | :---: | :--- | | `id` | UUID | Ja | Eindeutige ID (Primärschlüssel) | | `order_id` | UUID | Nein | Verknüpfung zum Auftrag (falls vorhanden) | | `customer_id` | UUID | Nein | Verknüpfung zum Kunden (falls vorhanden) | | `title` | Text | Ja | Titel (z.B. `Max Mustermann - Heizungswartung` oder `Mittagspause`) | | `customer_name` | Text | Nein | Kundenname für Schnellanzeige | | `address` | Text | Nein | Einsatzadresse | | `task_description` | Text | Nein | Spezifische Aufgabe | | `start_time` | Uhrzeit / Text | Ja | Startzeit (z.B. `10:30`) | | `end_time` | Uhrzeit / Text | Ja | Endzeit (z.B. `13:00`) | | `type` | Enum | Ja | Typ: `job`, `routine`, `lunchBreak`, `feierabend` | | `is_completed` | Boolean | Ja | Flag: Auftrag abgeschlossen | | `is_in_progress` | Boolean | Ja | Flag: Anfahrt gestartet / in Bearbeitung | | `scheduled_date` | Datum | Ja | Datum des Tagesplans | | `created_at` | Zeitstempel | Ja | Erstellungszeitpunkt | --- ## 3. Offene Fragen & Diskussionspunkte 1. **Entfernung (`distance_km`)**: Sollen wir die Distanz dynamisch via Geo-Abfrage (PostGIS) zur aktuellen Handwerker-Position berechnen lassen, oder als festes Feld im Kunden speichern? 2. **Kombination `work_orders` & `schedule_items`**: Reicht ein einziges Feld `work_orders` mit Uhrzeit, oder gefällt dir die Trennung von *Auftrag* (Fachlicher Arbeitsauftrag) und *Termin-Eintrag* (Konkreter Kalendereintrag in der Zeitleiste)? 3. **Baupläne / Anhänge**: Gefällt dir die Aufteilung mit `order_attachments`? So kann ein Techniker vor Ort in Flutter auf *"Baupläne"* tippen, bekommt eine Liste aller PDFs/Fotos des Auftrags und kann per Klick direkt neue Fotos vom Handy hochladen!