Bei der Uebernahme aus der Akquise verschwand die wichtigste Angabe nach dem Titel: fuer wen das Projekt laeuft. Die Opportunity hatte kein Feld dafuer, also schrieb die Uebernahme den Namen in den Herkunftsvermerk der Notizen - in Pipeline, Liste und Kacheln war er damit nicht zu sehen, und suchen liess sich nur im Notiztext. crm_opportunities.consultant traegt ihn jetzt selbst. Genau ein Name je Opportunity: passt ein Fund zu drei Beratern, entstehen bei der Uebernahme drei Opportunities. Sichtbar in Pipeline-Karte, Kachel, Papierkorb und als sortierbare Spalte direkt hinter dem Titel; die Suche fasst ihn mit ein, und im Dialog kommt die Auswahl aus derselben Liste wie in der Akquise (Einstellungen -> Akquise), damit nicht "Nico" und "Nico N." nebeneinander entstehen. Bestehende Opportunities holt migrateOpportunityConsultant() beim Start aus ihren Notizen nach - nur dort, wo die Spalte leer ist. Damit ist der Lauf wiederholbar und ueberschreibt nichts, was seither von Hand gesetzt wurde; ein Merker in crm_settings ist dafuer nicht noetig. Der Text in den Notizen bleibt stehen: er ist der Herkunftsnachweis samt Anbieter, Kanal und Link. Der Namenszusatz im Titel entfaellt wieder. Er war gestern dazugekommen, damit sich mehrere Opportunities aus einem Fund unterscheiden liessen - mit einer eigenen Spalte ist er nur noch Rauschen. Nebenbei: der Block, der won_at nachzieht, stand zweimal in schema.sql. Idempotent und damit harmlos, aber eine Kopie - jetzt einmal. 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.