Drei Dinge, die im Alltag gefehlt haben:
- Projektdaten kennen jetzt einen Projektpreis. Ist er gesetzt, gilt er als
Volumen statt Tagessatz x Laufzeit - Festpreisprojekte mussten bisher
ausgerechnet und in den Tagessatz gefaelscht werden.
- Dialoge schliessen auch per Klick in den Hintergrund, nicht nur ueber das X.
Escape trifft dabei nur den obersten Dialog; eine Textmarkierung, die im
Dialog beginnt und daneben endet, schliesst nichts.
- Fehlt ein Ansprechpartner noch im CRM, oeffnet "Neuer Kontakt..." in der
Opportunity denselben Dialog wie unter Kontakte. Der frische Kontakt haengt
danach sofort als Ansprechpartner dran, ohne die Opportunity zu verlassen.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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>
Menüs, Dialoge, Schaltflächen, Platzhalter, Hinweise und die
Fehlermeldungen der API standen in Ersatzschreibweise (oe/ae/ue). Sie
erscheinen als Toast oder Beschriftung direkt in der Oberfläche und
gehören damit richtig geschrieben; sechs sichtbare Texte mit ss statt ß
sind gleich mit erledigt ("Schließen", "Straße", "zu groß").
Unangetastet bleibt bewusst:
- Kommentare im Quelltext - die sind durchgängig ASCII, und der Diff wäre
dreimal so groß ohne Nutzen für den Benutzer
- Protokollzeilen (console.*) - die landen im journal, nicht in der App
- Datenbankwerte und interne Kennungen: 'uebernommen', 'empfaenger',
'vorschlaege', 'laeuft-bereits' stecken in Enums, SQL und
Zustandsvergleichen. Ein Umlaut darin hätte still falsche Ergebnisse
geliefert
- server/src/mail/extract.js - die Muster decken absichtlich beide
Schreibweisen ab: /gr(ü|ue)(ß|ss)e/
- scanner/utils/crypto.js - der Ersatzschlüssel darf sich nicht ändern,
sonst sind gespeicherte Portal-Passwörter nicht mehr lesbar
Geprüft mit einem Rundgang durch die Ansichten und Dialoge: sichtbarer
Text plus title/aria-label/placeholder enthalten keine
Ersatzschreibweisen mehr.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Der eigenstaendige Projekt Scanner zieht komplett ins CRM ein und laeuft
parallel zur bestehenden App weiter - jede geteilte Ressource ist verdoppelt
statt geteilt, damit die alte Installation unberuehrt bleibt:
- eigene Datenbank perinco_scanner, legt sich beim Start selbst an
- eigener SCANNER_ENCRYPTION_KEY, eigenes Upload-Verzeichnis
- eigener Scheduler mit Zeitversatz, damit nicht beide Instanzen gleichzeitig
mit denselben Portal-Cookies scrapen (Rate-Limits, CAPTCHA, doppelter RAM)
- Sperre gegen ueberlappende Laeufe: Scheduler und "Jetzt scannen" teilen sie,
ein zweiter Aufruf bekommt 409 statt doppelter OpenAI-Kosten
Backend unter /api/scanner hinter der CRM-Anmeldung; die HTTP-Basic-Auth des
Originals entfaellt. CV-PDFs kommen als Stream mit Token statt aus einem
statischen Verzeichnis. Bestandsdaten holt "npm run scanner:import" aus der
alten Datenbank, ohne sie zu veraendern.
Oberflaeche in Tailwind und CI-Farben neu gebaut: Menuepunkt Scanner mit
aufklappbaren Unterpunkten, Einstellungen als eigener Reiter.
Whisper hat keinen eigenen Menuepunkt mehr, sondern ist ein Reiter in den
Einstellungen. Damit diese Geraeteeinstellung jeder Rolle offensteht, sind die
Einstellungen jetzt fuer alle sichtbar - welche Reiter erscheinen, entscheidet
die Rolle.
Ausserdem: kein festes Admin-Passwort mehr im Quelltext, playwright exakt auf
1.60.0 gepinnt (nutzt den vorhandenen Chromium-Build des Servers), technische
Dokumentation mit Funktionszeichnungen unter docs/.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>