# 📌 CRM-Konzept für den Telefon-Akquise-Workflow --- ## **📂 1. Datenmodell (Anpassungen)** --- ### **1.1. Bestehende Tabellen (ohne Änderungen)** - **`User`** (Mitarbeiter) - **`Customer`** (Kunde) - **`Project`** (Projekt) - **`Contact`** (Kontakt) - **`ProjektUser`** (Zuordnung User → Projekt) - **`CallLogsTag`** (Zuordnung CallLog → Tag) --- ### **1.2. Anpassungen an bestehenden Tabellen** #### **`Tag` (Erweiterung für Wiedervorlage-Logik)** | **Feld** | **Typ** | **Beschreibung** | **Standardwert** | | -------------------------------- | ------------ | ---------------------------------------------------------------------------------- | ---------------- | | `id` | Integer | Primärschlüssel | - | | `name` | String(200) | Name des Tags | - | | `description` | String(2000) | Beschreibung (optional) | `NULL` | | `color` | String(20) | Farbe für UI (optional) | `NULL` | | `parent_id` | Integer | Selbstreferenz für hierarchische Tags | `NULL` | | `is_parent` | Boolean | `True` = Gruppierungsknoten | `False` | | **`is_erledigend`** | **Boolean** | **`True` = Kontakt wird als *erledigt* markiert, wenn dieser Tag zugewiesen wird** | **`False`** | | **`loest_wiedervorlage_aus`** | **Boolean** | **`True` = Tag löst eine Wiedervorlage aus** | **`False`** | | **`wiedervorlage_abstand_tage`** | **Integer** | **Anzahl Tage bis zur Wiedervorlage (falls `loest_wiedervorlage_aus = True`)** | **`NULL`** | --- #### **`CallLog` (Anpassung für Wiedervorlage-Datum)** | **Feld** | **Typ** | **Beschreibung** | **Standardwert** | | ------------------------- | -------- | -------------------------------------------------------------------------- | ------------------- | | `id` | Integer | Primärschlüssel | - | | `contact_id` | Integer | Fremdschlüssel → `Contact` | - | | `user_id` | Integer | Fremdschlüssel → `User` | - | | `note_text` | Text | Text der Gesprächsnotiz | - | | `created_at` | DateTime | Erstellungsdatum | `CURRENT_TIMESTAMP` | | **`wiedervorlage_datum`** | **Date** | **Wiedervorlage-Datum (automatisch berechnet oder manuell überschrieben)** | **`NULL`** | --- #### **`Contact` (Anpassung für optimistisches Locking)** | **Feld** | **Typ** | **Beschreibung** | **Standardwert** | | ------------- | ----------- | --------------------------------------------- | ---------------- | | `id` | Integer | Primärschlüssel | - | | `project_id` | Integer | Fremdschlüssel → `Project` | - | | `first_name` | String(100) | Vorname des Kontakts | - | | `last_name` | String(100) | Nachname des Kontakts | - | | `phone` | String(20) | Telefonnummer | - | | `email` | String(100) | E-Mail (optional) | `NULL` | | **`version`** | **Integer** | **Versionsnummer für optimistisches Locking** | **`0`** | --- #### **`Project` (kein Status-Feld)** | **Feld** | **Typ** | **Beschreibung** | **Standardwert** | | ------------- | ----------- | --------------------------- | ------------------- | | `id` | Integer | Primärschlüssel | - | | `customer_id` | Integer | Fremdschlüssel → `Customer` | - | | `name` | String(200) | Name des Projekts | - | | `created_at` | DateTime | Erstellungsdatum | `CURRENT_TIMESTAMP` | --- ### **1.3. Neue Methoden (Statusberechnung)** #### **Methode für `Contact`: `is_erledigt()`** - **Zweck**: Dynamisch prüfen, ob ein Kontakt als *erledigt* gilt. - **Logik**: - Falls der Kontakt **keine Gesprächsnotizen** hat → `False` (nicht erledigt). - Falls **alle Gesprächsnotizen** des Kontakts **mindestens einen Tag mit `is_erledigend = True`** haben → `True` (erledigt). - Sonst → `False` (nicht erledigt). **Pseudocode:** ```python # Methode in der Contact-Klasse def is_erledigt(self): if not self.call_logs: return False for notiz in self.call_logs: for tag in notiz.tags: if not tag.is_erledigend: return False return True ``` --- #### **Methode für `Project`: `is_erledigt()`** - **Zweck**: Dynamisch prüfen, ob ein Projekt als *erledigt* gilt. - **Logik**: - Falls das Projekt **keine Kontakte** hat → `True` (erledigt). - Falls **alle Kontakte** des Projekts `is_erledigt() = True` sind → `True` (erledigt). - Sonst → `False` (nicht erledigt). **Pseudocode:** ```python # Methode in der Project-Klasse def is_erledigt(self): if not self.contacts: return True for kontakt in self.contacts: if not kontakt.is_erledigt(): return False return True ``` --- ### **1.4. Neue Tabellen (für spätere Protokollierung)** #### **`KontaktLog` (optional)** | **Feld** | **Typ** | **Beschreibung** | | ------------ | ---------- | ---------------------------------------------------------- | | `id` | Integer | Primärschlüssel | | `kontakt_id` | Integer | Fremdschlüssel → `Contact` | | `user_id` | Integer | Fremdschlüssel → `User` | | `timestamp` | DateTime | Zeitstempel der Änderung | | `aktion` | String(50) | Art der Änderung (z. B. *"Notiz hinzugefügt"*) | | `alte_werte` | JSON | Alte Werte (z. B. `{"wiedervorlage_datum": "2026-09-20"}`) | | `neue_werte` | JSON | Neue Werte (z. B. `{"wiedervorlage_datum": "2026-09-25"}`) | --- --- --- ## **🖥️ 2. Benutzeroberfläche (Masken & Workflows)** --- ### **2.1. Hauptmenü** - **Menüpunkte**: - **Tages-Workflow** - **Projekte** - **Kontakte** - **Statistiken** --- ### **2.2. Tages-Workflow: Gefilterte Liste** #### **Anzeige** - **Tabellenansicht** mit Spalten: | **Spalte** | **Beschreibung** | **Beispiel** | | ------------- | ----------------------------------------- | ------------------------- | | Kunde | Name des Kunden | "Muster GmbH" | | Projekt | Name des Projekts | "Neukundengewinnung 2026" | | Kontakt | Name des Ansprechpartners | "Max Mustermann" | | Telefon | Telefonnummer | "+49 123 45678" | | Letzte Notiz | Kurztext der letzten Gesprächsnotiz | "Nicht erreicht" | | Wiedervorlage | Nächstes Wiedervorlage-Datum | "20.09.2026" | | **Status** | **Dynamisch berechnet (`is_erledigt()`)** | "Offen" / "Erledigt" | - **Sortierung**: 1. Überfällige Wiedervorlagen 2. Kontakte ohne Gesprächsnotizen 3. Kontakte mit Wiedervorlage in der aktuellen Woche --- #### **Filterleiste** | **Filter** | **Typ** | **Mögliche Werte** | | ------------------- | ---------------- | ----------------------------------------------------------------------- | | Kunde | Dropdown | Alle Kunden, die der Mitarbeiter bearbeiten darf | | Projektstatus | Dropdown | *Offen*, *In Bearbeitung* (dynamisch berechnet) | | **Tag-Kategorie** | **Dropdown** | **`Erledigend`**, **`Nicht-erledigend`**, **`Wiedervorlage-Tags`** | | **Einzelne Tags** | **Multi-Select** | **Alle verfügbaren Tags** (z. B. *"Nicht erreicht"*, *"Wiedervorlage"*) | | Wiedervorlage-Datum | Dropdown | *Heute*, *Nächste 3 Tage*, *Überfällig*, *Aktuelle Woche* | - **Aktionsbuttons**: - **"Filter anwenden"** (Aktualisiert die Liste) - **"Zurücksetzen"** (Setzt alle Filter zurück) - **"Workflow beginnen"** (Startet die Bearbeitung mit dem ersten Eintrag) --- ### **2.3. Bearbeitungsmaske** #### **Kopfzeile: Projekt- und Kontaktinformationen** - **Kundeninfo**: Name des Kunden und Projektname. - **Kontaktinfo**: Name, Telefonnummer, E-Mail. - **Button**: *"Kontakt bearbeiten"* **Beispiel:** ``` Kunde: Muster GmbH Projekt: Neukundengewinnung 2026 Kontakt: Max Mustermann | +49 123 45678 | max@muster.de ``` --- #### **Tabelle der bisherigen Gesprächsnotizen** | **Spalte** | **Beschreibung** | **Beispiel** | | ------------- | ---------------------------- | ------------------------------- | | Datum | Erstellungsdatum und Uhrzeit | "19.09.2026, 14:30" | | Mitarbeiter | Name des Mitarbeiters | "Gerd Goldberg" | | Notiz | Text der Gesprächsnotiz | "Nicht erreicht" | | Tags | Zugewiesene Tags | "Nicht erreicht, Wiedervorlage" | | Wiedervorlage | Wiedervorlage-Datum | "20.09.2026" | - **Sortierung**: Neueste Notiz zuerst. - **Funktionen**: - Klick auf Notiz → Details anzeigen. - **Button**: *"Notiz bearbeiten"* --- #### **Formular für neue Gesprächsnotiz** - **Felder**: - **Notiztext** (Textarea, Pflichtfeld) - **Tags** (Multi-Select-Dropdown mit allen verfügbaren Tags) - **Wiedervorlage-Datum** (Datumspicker, **automatisch berechnet oder manuell überschreibbar**) - **Buttons**: - **"Speichern und weiter"** (Speichert und lädt den nächsten Kontakt) - **"Speichern"** (Speichert und bleibt auf dem aktuellen Kontakt) - **"Abbrechen"** (Verwirft Änderungen, Rückkehr zur Liste) --- #### **Navigation** - **Button: "Zurück zur Liste"**: - Kehrt zur **gefilterten Liste** zurück. - Die Liste berücksichtigt bereits alle Änderungen (z. B. neue Notizen, Statusänderungen). - **Button: "Nächster Kontakt"**: - Lädt manuell den nächsten Kontakt aus der Liste. --- ### **2.4. Konfliktmeldung (bei optimistischem Locking)** - **Anzeige**: ``` Dieser Kontakt wurde von [Mitarbeiter] bearbeitet und als erledigt markiert. Möchten Sie die aktuelle Version neu laden? ``` - **Optionen**: - *"Neu laden"* (Lädt die aktuelle Version des Kontakts). - *"Trotzdem speichern"* (Überschreibt die Änderungen, **nur für Admins**). --- ### **2.5. Hinweis bei übersprungenen Kontakten** - **Automatisches Überspringen** von Kontakten, die nicht mehr den Filterkriterien entsprechen. - **Hinweis in der UI**: ``` Kontakt [Name] wurde übersprungen, da er nicht mehr den Filterkriterien entspricht (Grund: [z. B. 'Wiedervorlage-Datum außerhalb der gefilterten Woche' oder 'Kontakt wurde als erledigt markiert']). ``` --- --- --- ## **🔄 3. Workflows & Logik** --- ### **3.1. Wiedervorlage-Datum Berechnung** - **Automatische Berechnung**: - Falls **kein manuelles `wiedervorlage_datum`** in der Notiz gesetzt ist: - **Minimum** der `wiedervorlage_abstand_tage` aller ausgewählten Tags mit `loest_wiedervorlage_aus = True`. - **Wiedervorlage-Datum = Erstellungsdatum der Notiz + Minimum-Abstand**. - **Manuelle Überschreibung**: - Der Mitarbeiter kann das **`wiedervorlage_datum`** jederzeit manuell ändern (z. B. über den Datumspicker). --- ### **3.2. Statusberechnung (dynamisch)** - **Kontaktstatus**: - Wird **dynamisch** über die Methode `is_erledigt()` berechnet (siehe [1.3](#13-neue-methoden-statusberechnung)). - **Kein statisches `status`-Feld** in der Datenbank. - **Projektstatus**: - Wird **dynamisch** über die Methode `is_erledigt()` berechnet. --- ### **3.3. Tages-Workflow (Ablauf)** 1. **Aufruf des Tages-Workflows**: - Mitarbeiter wählt **"Tages-Workflow"** aus. - **System**: Zeigt die **priorisierte Liste** der Kontakte an (sortiert nach Wiedervorlage-Datum). 2. **Filter anwenden**: - Mitarbeiter wählt Filter (z. B. Kunde, Tag-Kategorie, einzelne Tags). - **System**: Aktualisiert die Liste basierend auf den Filtern. 3. **Workflow beginnen**: - Mitarbeiter klickt auf **"Workflow beginnen"**. - **System**: Lädt den **ersten Kontakt** aus der gefilterten Liste in die Bearbeitungsmaske. 4. **Bearbeitung des Kontakts**: - Mitarbeiter erfasst eine **neue Gesprächsnotiz** (Text, Tags, **Wiedervorlage-Datum**). - **System**: - Berechnet das **`wiedervorlage_datum`** (falls nicht manuell gesetzt). - Inkrementiert die **`version`** des Kontakts (für optimistisches Locking). 5. **Speichern und weiter**: - Mitarbeiter klickt auf **"Speichern und weiter"**. - **System**: - Speichert die Notiz und prüft die **`version`** des Kontakts. - Falls **Konflikt** (Version stimmt nicht überein **UND** Status wurde Wesentlich geändert): - Zeigt **Konfliktmeldung** an. - Lädt den **nächsten Kontakt** aus der Liste, der die **Filterkriterien erfüllt**. - Falls kein Kontakt mehr passt: - Zeigt Meldung: *"Keine weiteren Kontakte entsprechen den Filterkriterien."* - Kehrt zur **gefilterten Liste** zurück. --- ### **3.4. Dynamische Filterprüfung** - **Beim Laden des nächsten Kontakts**: - **System prüft**: - Ist der Kontakt noch **nicht erledigt** (`is_erledigt() = False`)? - Liegt das **Wiedervorlage-Datum** noch im gefilterten Zeitraum? - Falls der Kontakt **nicht mehr passt**: - Lädt den **nächsten Kontakt**, der die Kriterien erfüllt. --- --- --- ## **📊 4. Beispiel-Daten** --- ### **4.1. Tags** | **Name** | **`is_erledigend`** | **`loest_wiedervorlage_aus`** | **`wiedervorlage_abstand_tage`** | | ------------------ | ------------------- | ----------------------------- | -------------------------------- | | Uninteressiert | `True` | `False` | `NULL` | | Wiedervorlage | `False` | `True` | `7` | | Nicht erreicht | `False` | `True` | `3` | | Rückruf vereinbart | `False` | `True` | `1` | | Falsche Nummer | `False` | `False` | `NULL` | | Erfolgreich | `False` | `False` | `NULL` | | Termin vereinbart | `False` | `True` | `14` | --- ### **4.2. Gesprächsnotizen** | **Kontakt** | **Notiz** | **Tags** | **Wiedervorlage-Datum** | **Berechnung** | | -------------- | -------------------- | ------------------ | ----------------------- | ----------------------------- | | Max Mustermann | "Nicht erreicht" | Nicht erreicht | **20.09.2026** | Heute + 3 Tage (Tag-Abstand) | | Anna Schmidt | "Rückruf vereinbart" | Rückruf vereinbart | **21.09.2026** | Heute + 1 Tag (Tag-Abstand) | | Peter Müller | "Termin vereinbart" | Termin vereinbart | **04.10.2026** | Heute + 14 Tage (Tag-Abstand) | --- --- --- ## **🔍 5. Zusammenfassung der Änderungen** | **Bereich** | **Änderung / Neuerung** | | ---------------------- | --------------------------------------------------------------------------------------------- | | **Datenmodell** | **Kein `status`-Feld** in `Project` oder `Contact` → **dynamische Methoden `is_erledigt()`**. | | **`CallLog`** | **Einziges `wiedervorlage_datum`-Feld** (automatisch berechnet oder manuell überschrieben). | | **`Contact`** | **`version`-Feld** für optimistisches Locking. | | **Filter** | **Einzelne Tags** als Filteroption (Mehrfachauswahl). | | **Bearbeitungsmaske** | **Wiedervorlage-Datum** ist manuell änderbar, wird aber automatisch aus Tags berechnet. | | **Workflow-Logik** | Dynamische Filterprüfung beim Laden des nächsten Kontakts. | | **Konfliktbehandlung** | Optimistisches Locking mit `version`-Feld + Meldung bei **wesentlichen Änderungen**. |