docs: echte Umlaute in der Dokumentation
893 Stellen in Fliesstext, Tabellen und Mermaid-Beschriftungen. Dazu die sichtbaren ss-Fälle (ausschließlich, groß, außen, schließt, heißt, draußen, weiße, anstoßen, Straße). Nicht angetastet, damit die Doku weiter beschreibt, was wirklich in der Datenbank steht: - Codeblöcke und Code-Spans - dort stehen Bezeichner, SQL, Enum-Werte und Dateinamen: `mail_pool`, `'uebernommen'`, `extract.js` - in Mermaid nur der Text in Anführungszeichen; Knotennamen, Pfeile und Werte wie source = 'Mail' bleiben, wie sie sind - `empfaenger` im ER-Diagramm von crm_mail_contact_candidates: die Aufzählung dort nennt die Datenbankwerte, nicht die Anzeige Die Menü-Skizze in der Benutzeranleitung zeigt jetzt die aufgeklappten Kontakte mit "Aus Mails" samt Zähler. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
8b7ce448a6
commit
7973dc07b1
+34
-34
@@ -7,9 +7,9 @@ Zwei Datenbanken, absichtlich getrennt:
|
||||
| `perinco_CRM` | Benutzer, Kontakte, Opportunities, Termine, Postfach, Einstellungen | `mysql2` direkt, Schema aus `server/src/schema.sql` |
|
||||
| `perinco_scanner` | Suchagenten, Portale, Projekte, Treffer, Scanner-Einstellungen | Sequelize, Schema aus den Modellen (`sequelize.sync()`) |
|
||||
|
||||
Die Trennung ist kein Zufall: die Scanner-Tabellen sind eine 1:1-Uebernahme aus
|
||||
der eigenstaendigen App. Gleiche Tabellennamen, gleiche Spalten - nur in einer
|
||||
eigenen Datenbank, damit beide Anwendungen parallel laufen koennen.
|
||||
Die Trennung ist kein Zufall: die Scanner-Tabellen sind eine 1:1-Übernahme aus
|
||||
der eigenständigen App. Gleiche Tabellennamen, gleiche Spalten - nur in einer
|
||||
eigenen Datenbank, damit beide Anwendungen parallel laufen können.
|
||||
|
||||
## perinco_CRM
|
||||
|
||||
@@ -61,7 +61,7 @@ erDiagram
|
||||
enum stage "Neu .. Verloren"
|
||||
tinyint probability "0-100"
|
||||
decimal daily_rate
|
||||
decimal duration_days "Personentage, halbe moeglich"
|
||||
decimal duration_days "Personentage, halbe möglich"
|
||||
date last_interaction_at
|
||||
varchar next_step
|
||||
int owner_id FK
|
||||
@@ -88,15 +88,15 @@ erDiagram
|
||||
|
||||
Vier Eigenheiten, die man kennen muss:
|
||||
|
||||
- **`crm_leads` fuehrt zwei Bestaende.** `mail_pool = 0` ist der gepflegte
|
||||
- **`crm_leads` führt zwei Bestände.** `mail_pool = 0` ist der gepflegte
|
||||
Kontaktbestand, `mail_pool = 1` der Vorbereich „Aus Mails" mit den Funden des
|
||||
Postfachabgleichs. Nur der Kontaktbestand erscheint in Kontaktliste,
|
||||
Opportunities, Kalender und Netzwerk; der Vorbereich hat seine eigene Ansicht.
|
||||
Eine Spalte statt einer zweiten Tabelle, damit `crm_mail_links` und
|
||||
`crm_mail_contact_candidates` fuer beide Bestaende gelten
|
||||
`crm_mail_contact_candidates` für beide Bestände gelten
|
||||
([11 Postfachanbindung](11-postfach.md)).
|
||||
- **`tags` ist Text, kein JSON-Typ.** Bewusst, damit es auf aelteren
|
||||
MariaDB-Versionen ohne JSON-Funktionen laeuft. Das Backend serialisiert.
|
||||
- **`tags` ist Text, kein JSON-Typ.** Bewusst, damit es auf älteren
|
||||
MariaDB-Versionen ohne JSON-Funktionen läuft. Das Backend serialisiert.
|
||||
- **`crm_lead_connections` speichert das Paar sortiert** (kleinere Id in
|
||||
`from_lead_id`). Der Unique-Key verhindert damit auch die Umkehrung als
|
||||
Duplikat, obwohl die Verbindung ungerichtet gedacht ist.
|
||||
@@ -106,7 +106,7 @@ Vier Eigenheiten, die man kennen muss:
|
||||
|
||||
### Postfach crm@perinco.de
|
||||
|
||||
Diese Tabellen liegen in derselben Datenbank, haengen aber nur ueber
|
||||
Diese Tabellen liegen in derselben Datenbank, hängen aber nur über
|
||||
`crm_mail_links` und `crm_mail_contact_candidates.lead_id` am Rest. Fachliche
|
||||
Beschreibung in [11 Postfachanbindung](11-postfach.md).
|
||||
|
||||
@@ -116,21 +116,21 @@ erDiagram
|
||||
crm_mail_messages ||--o{ crm_mail_contact_candidates : liefert
|
||||
crm_leads ||--o{ crm_mail_links : "lead_id"
|
||||
crm_opportunities ||--o{ crm_mail_links : "opportunity_id"
|
||||
crm_leads ||--o{ crm_mail_contact_candidates : "lead_id, nach Uebernahme"
|
||||
crm_leads ||--o{ crm_mail_contact_candidates : "lead_id, nach Übernahme"
|
||||
|
||||
crm_mail_messages {
|
||||
int id PK
|
||||
varchar graph_id "Id aus Microsoft Graph"
|
||||
char graph_id_hash UK "SHA-256 hex, traegt die Eindeutigkeit"
|
||||
char graph_id_hash UK "SHA-256 hex, trägt die Eindeutigkeit"
|
||||
varchar conversation_id "Unterhaltung"
|
||||
varchar subject
|
||||
varchar from_email
|
||||
longtext to_json "[{name,email}] als Text"
|
||||
datetime received_at "UTC"
|
||||
longtext body_text "aus HTML gewandelt, Zeilen erhalten"
|
||||
longtext body_html "entschaerft fuer die Anzeige"
|
||||
longtext body_html "entschärft für die Anzeige"
|
||||
tinyint has_attachments
|
||||
tinyint is_deleted "im Postfach geloescht"
|
||||
tinyint is_deleted "im Postfach gelöscht"
|
||||
}
|
||||
crm_mail_links {
|
||||
int id PK
|
||||
@@ -151,13 +151,13 @@ erDiagram
|
||||
varchar company
|
||||
enum origin "absender | empfaenger | signatur | text"
|
||||
tinyint confidence "0-100"
|
||||
enum status "offen | uebernommen | verworfen | dublette"
|
||||
int lead_id FK "gesetzt ab uebernommen"
|
||||
enum status "offen | übernommen | verworfen | dublette"
|
||||
int lead_id FK "gesetzt ab übernommen"
|
||||
}
|
||||
crm_mail_sync_state {
|
||||
tinyint id PK "immer 1"
|
||||
varchar mailbox
|
||||
text delta_link "naechster Graph-Aufruf"
|
||||
text delta_link "nächster Graph-Aufruf"
|
||||
tinyint has_more "nextLink offen"
|
||||
datetime last_run_at
|
||||
datetime last_success_at
|
||||
@@ -171,20 +171,20 @@ erDiagram
|
||||
|
||||
Vier Eigenheiten:
|
||||
|
||||
- **Die Graph-ID hat einen Hash daneben.** Sie ist mit ueber 150 Zeichen zu lang
|
||||
fuer einen Unique-Index unter `utf8mb4`; die Eindeutigkeit traegt deshalb
|
||||
- **Die Graph-ID hat einen Hash daneben.** Sie ist mit über 150 Zeichen zu lang
|
||||
für einen Unique-Index unter `utf8mb4`; die Eindeutigkeit trägt deshalb
|
||||
`graph_id_hash` (SHA-256 als Hex, `CHAR(64)`).
|
||||
- **`received_at` steht in UTC**, anders als `crm_events.starts_at` (lokale
|
||||
Wandzeit). Graph liefert UTC, und eine stille Umrechnung beim Speichern waere
|
||||
Wandzeit). Graph liefert UTC, und eine stille Umrechnung beim Speichern wäre
|
||||
eine Fehlerquelle. Das Frontend rechnet um (`parseMailDate` in
|
||||
`src/lib/mailApi.ts`).
|
||||
- **`crm_mail_links` erlaubt NULL in beiden Fremdschluesseln.** MariaDB laesst in
|
||||
einem Unique-Index mehrere NULL zu - die beiden Schluessel sperren damit genau
|
||||
- **`crm_mail_links` erlaubt NULL in beiden Fremdschlüsseln.** MariaDB lässt in
|
||||
einem Unique-Index mehrere NULL zu - die beiden Schlüssel sperren damit genau
|
||||
die Doppelung desselben Paares, und eine Mail kann an mehreren Kontakten und
|
||||
mehreren Opportunities haengen.
|
||||
- **`crm_settings` enthaelt keine Geheimnisse.** Zugangsdaten fuer Microsoft 365
|
||||
stehen ausschliesslich in `server/.env`, damit ein Datenbank-Dump keine Secrets
|
||||
enthaelt.
|
||||
mehreren Opportunities hängen.
|
||||
- **`crm_settings` enthält keine Geheimnisse.** Zugangsdaten für Microsoft 365
|
||||
stehen ausschließlich in `server/.env`, damit ein Datenbank-Dump keine Secrets
|
||||
enthält.
|
||||
|
||||
## perinco_scanner
|
||||
|
||||
@@ -197,7 +197,7 @@ erDiagram
|
||||
agents {
|
||||
int id PK
|
||||
varchar name
|
||||
varchar email "fuer Benachrichtigungen"
|
||||
varchar email "für Benachrichtigungen"
|
||||
longtext cv_text "aus dem PDF extrahiert"
|
||||
varchar cv_file_path "Pfad im Upload-Verzeichnis"
|
||||
varchar keywords "kommagetrennt, Suchbegriffe"
|
||||
@@ -207,7 +207,7 @@ erDiagram
|
||||
projects {
|
||||
int id PK
|
||||
varchar portal "freelancermap.de, hays.de, ..."
|
||||
varchar portal_project_id "Id der Boerse"
|
||||
varchar portal_project_id "Id der Börse"
|
||||
varchar title
|
||||
longtext description
|
||||
varchar location
|
||||
@@ -244,12 +244,12 @@ erDiagram
|
||||
|
||||
- **`matches` hat einen Unique-Key auf `(agent_id, project_id)`.** Dadurch wird
|
||||
jedes Projekt pro Agent genau einmal von OpenAI bewertet - das ist der Grund,
|
||||
warum ein zweiter Scan-Lauf ueber dieselben Projekte nichts kostet.
|
||||
- **`projects` wird nach 7 Tagen aufgeraeumt** (`cleanupOldProjects`), die
|
||||
warum ein zweiter Scan-Lauf über dieselben Projekte nichts kostet.
|
||||
- **`projects` wird nach 7 Tagen aufgeräumt** (`cleanupOldProjects`), die
|
||||
Treffer verschwinden per `ON DELETE CASCADE` mit.
|
||||
- **`settings` ist ein Schluessel-Wert-Speicher.** Geheimnisse (`openai_api_key`,
|
||||
- **`settings` ist ein Schlüssel-Wert-Speicher.** Geheimnisse (`openai_api_key`,
|
||||
`smtp_pass`) liefert die API nur maskiert als `********` aus; ein leeres oder
|
||||
maskiertes Feld beim Speichern laesst den gespeicherten Wert unberuehrt.
|
||||
maskiertes Feld beim Speichern lässt den gespeicherten Wert unberührt.
|
||||
|
||||
## Statuswege
|
||||
|
||||
@@ -259,16 +259,16 @@ stateDiagram-v2
|
||||
new --> reviewed : "Als Gesehen markieren"
|
||||
new --> applied : "Als Beworben markieren"
|
||||
reviewed --> applied
|
||||
applied --> new : "Zurueck auf Neu"
|
||||
applied --> new : "Zurück auf Neu"
|
||||
reviewed --> new
|
||||
new --> rejected : "Passt nicht"
|
||||
reviewed --> rejected
|
||||
applied --> rejected
|
||||
rejected --> new : "Zurueck ins Dashboard"
|
||||
rejected --> new : "Zurück ins Dashboard"
|
||||
rejected --> [*] : loeschen
|
||||
new --> [*] : loeschen
|
||||
```
|
||||
|
||||
`rejected` ist der einzige Status, der aus dem Dashboard verschwindet und
|
||||
stattdessen im Reiter *Unpassend* auftaucht. Solche Treffer zaehlen auch in den
|
||||
stattdessen im Reiter *Unpassend* auftaucht. Solche Treffer zählen auch in den
|
||||
Kennzahlen nicht mit.
|
||||
|
||||
Reference in New Issue
Block a user