Am Kontakt gibt es unter der E-Mail-Adresse das Kästchen "Einverständnis für Mails". Ohne Adresse ist es gesperrt. Der Zeitpunkt wird in `mail_consent_at` mitgeschrieben und im Kontakt angezeigt: bei einer Beschwerde ist nicht die Frage, ob ein Einverständnis vorliegt, sondern seit wann. Beim Widerruf wird er geleert; ein erneutes Speichern verschiebt ihn nicht. Der Knopf "Mailingliste erstellen" in der Kontaktleiste sammelt alle Adressen mit Haken, durch Komma getrennt, mit Zähler am Knopf. Rechts im Feld ein Kopiersymbol (Zwischenablage, mit Fallback für Browser ohne die Schnittstelle) und ein Mailsymbol. Zum Mailsymbol zwei Entscheidungen: - Die Adressen gehen ins BCC, nicht ins An-Feld. Im An-Feld sähe jeder Empfänger die vollständige Kundenliste. - Windows gibt an das Mailprogramm nur rund 2000 Zeichen weiter. Ab 1900 Zeichen ist das Symbol deshalb gesperrt und der Dialog erklärt es - sonst wäre die Empfängerliste unbemerkt abgeschnitten. Nur für richtige Kontakte: Der Vorbereich "Aus Mails" hat das Kästchen nicht, und beim Übernehmen wird der Haken nicht mitgesetzt - dass jemand eine Mail geschrieben hat, ist keine Einwilligung in Werbung. Das Backend weist ein `mail_consent` für Einträge mit `mail_pool = 1` ab. Sichtbar ohne Öffnen: grünes Briefsymbol in der Kachel, Häkchen hinter der Adresse in der Liste. Geprüft im Browser gegen das Stub-Backend: Haken setzen und widerrufen, Zähler, Komma-Liste, Zwischenablage, mailto mit BCC, kein Kästchen im Vorbereich (15 Prüfungen). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Dokumentation perinco CRM
Technische Dokumentation mit Funktionszeichnungen. Die Diagramme sind Mermaid und werden von Gitea direkt gerendert.
Neu hier? Wer die Anwendung benutzen will, fängt bei 07 Anleitung für Benutzer an. Wer daran entwickeln will, bei 08 Anleitung für Entwickler. Beide setzen keine Vorkenntnisse voraus.
| Kapitel | Inhalt |
|---|---|
| 01 Architektur | Topologie, Prozesse, Ports, Anfrageweg, Rollen |
| 02 Datenmodell | Tabellen beider Datenbanken als ER-Diagramme |
| 03 Projekt Scanner | Suchlauf von der Börse bis zum Treffer, Parallelbetrieb |
| 04 Diktat | Spracherkennung im Browser, Modell-Lebenszyklus |
| 05 Frontend | Ansichten, Menü, Komponentenkarte, Zustand |
| 06 Betrieb | Deployment, Umgebungsvariablen, Dienste, Störungssuche |
| 07 Anleitung für Benutzer | Bedienung aller Bereiche, Schritt für Schritt |
| 08 Anleitung für Entwickler | Einrichten, erweitern, bekannte Fallen |
| 09 Quellcode-Referenz | jede Datei, ihre Exporte und Zusagen |
| 10 Glossar | Agent, Match, Lead, Opportunity, Status- und Portalwerte |
| 11 Postfachanbindung | crm@perinco.de über Microsoft Graph, Kontakte aus Mails |
Die Designentscheidungen und die Messwerte zur Spracherkennung stehen im README des Projekts.
Das Ganze in einem Bild
flowchart TB
subgraph Browser
SPA["React-SPA<br/>Vite-Build"]
WSP["Whisper im Web Worker<br/>WebGPU / WASM"]
end
subgraph Server["Server 212.227.135.41"]
AP["Apache<br/>:443"]
API["Express-Backend<br/>127.0.0.1:5006"]
SCH["Scanner-Scheduler<br/>node-cron"]
MSCH["Mail-Scheduler<br/>node-cron"]
PW["Playwright<br/>Chromium"]
DB1[("MariaDB<br/>perinco_CRM")]
DB2[("MariaDB<br/>perinco_scanner")]
ALT["alte Scanner-App<br/>:5005"]
DB3[("MariaDB<br/>project_scanner")]
end
OAI["OpenAI<br/>gpt-4o-mini"]
BOERSE["Projektbörsen<br/>freelancermap, hays, ..."]
GRAPH["Microsoft Graph<br/>crm@perinco.de"]
SPA -->|"HTTPS /api"| AP
AP --> API
API --> DB1
API --> DB2
SCH --> PW
PW --> BOERSE
SCH --> OAI
SCH --> DB2
API -.-> SCH
API -.-> MSCH
MSCH -->|"Delta Query, nur lesend"| GRAPH
MSCH --> DB1
ALT --> DB3
ALT --> BOERSE
SPA -.->|"Audio bleibt im Browser"| WSP
classDef alt fill:#f7f7f7,stroke:#9a9a9a,stroke-dasharray: 4 3
class ALT,DB3 alt
Gestrichelt: die ursprüngliche Scanner-App, die bis zur Ablosung parallel weiterläuft. Sie hat ihre eigene Datenbank und wird vom CRM nicht angefasst.