Bisher verschwand ein Fund mit der Uebernahme aus Eingang und Archiv.
Beim Durchgehen blieb damit offen, ob er schon angefasst wurde. Jetzt
bleibt der Eintrag stehen und zeigt statt "Opportunity" den blauen Knopf
"Uebernommen" mit Haken; ein Klick springt zur Opportunity.
Dafuer entscheidet nicht mehr IS_OPEN ueber die Listen, sondern die neuen
Regeln IN_INBOX und RETURNED: ein Rueckfaeller (Opportunity im Papierkorb
oder geloescht) gehoert weiter ins Archiv, alles andere bleibt in seiner
Liste. Zaehler und Menuezahl folgen derselben Regel. IS_OPEN bleibt fuer
den Loeschlauf: was zu einer lebenden Opportunity gehoert, wird nicht
weggeraeumt.
Solange die Opportunity lebt, sind Bearbeiten, Loeschen und "Zurueck in
die Akquise" am Eintrag gesperrt - er ist ihr Herkunftsnachweis, und der
Rueckweg von der Opportunity braucht ihn. Das Loeschen weist auch das
Backend ab, nicht nur die Oberflaeche.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Ein gefundenes Projekt passt oft zu mehr als einem Berater, und fuer
jeden geht eine eigene Bewerbung heraus. Das Feld "Berater" liess bisher
nur einen Namen zu.
Gespeichert wird eine kommagetrennte Liste in crm_acquisitions.consultant
(auf VARCHAR(500) erweitert, Migration in db.js) und keine eigene
Zuordnungstabelle: die Namen sind reiner Text, die Auswahlliste in
crm_acquisition_options ist eine Pflegehilfe und kein Fremdschluessel.
Suche, Sortierung und Anzeige der Liste arbeiten damit weiter auf einem
Feld. Die Funktionen zum Zerlegen stehen in acquisitionRules.js, das
Gegenstueck fuer das Frontend in src/types.ts, geprueft von
server/test/acquisition.test.mjs.
Zerlegt wird an vier Stellen:
- Uebernahme: je Berater eine Opportunity, alle in einer Transaktion.
Ihre Titel tragen den Namen in Klammern, weil die Opportunity kein
eigenes Feld fuer den Berater hat und in Pipeline und Liste sonst
identische Zeilen stehen; bei einem einzigen Berater bleibt der Titel
unveraendert. In den Notizen steht neben dem eigenen Berater auch, mit
wem er sich das Projekt teilt. Der Eintrag merkt sich die erste
Opportunity - sie entscheidet nur darueber, ob er wieder im Eingang
auftaucht.
- Verlauf (crm_acquisition_history): ein Berater je Zeile. Ein Eintrag
mit drei Beratern sind drei Bewerbungen, "Nico, Lisa" waere sonst ein
eigener Schluessel neben "Nico" und "Lisa".
- Dashboard: dieselbe Zaehlung. Die Summe der Balken liegt damit ueber
der Gesamtzahl "Bewerbungen", die weiter die Eintraege zaehlt.
- Auswahlliste pflegen: Umbenennen ersetzt den Namen innerhalb der
Liste, Loeschen zaehlt auch, wer nur einer von mehreren ist. Ein
Gleichheitsvergleich uebersah beides.
In der Oberflaeche haengt das Auswahlfeld jeweils einen Namen an, die
Gewaehlten stehen als Plaketten darunter und lassen sich einzeln
entfernen; ein bereits gewaehlter Berater verschwindet aus der Liste.
Bewusst kein <select multiple>: Strg-Klick ist mit der Maus unauffindbar
und mit einer Beruehrung gar nicht bedienbar.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Loeschen in der Akquise war ein echtes DELETE: der Eintrag stand danach
in keiner Liste, auch nicht im Archiv, und war nicht zurueckholbar. Jetzt
setzt es `deleted_at`/`deleted_by`, die Zeile bleibt 90 Tage stehen.
Der Papierkorb ist die eine Ausnahme von der Regel, dass diese Tabelle
keinen Zustand fuehrt: Loeschen von Hand ist eine Entscheidung, kein
Ablauf. Was dort liegt, blenden alle anderen Abfragen ueber NOT_DELETED
aus - Eingang, Archiv, Menuezahlen und Dashboard. Der Aufraeumlauf ueber
`found_at` laesst geloeschte Zeilen ausdruecklich liegen, sonst waere ein
alter Fund im Papierkorb sofort weg; der Papierkorb raeumt ab
`deleted_at`.
Zwei Rueckwege, deshalb zwei Routen. `/reopen` (bisher `/restore`) holt
aus dem Archiv in den Eingang und setzt das Funddatum auf heute.
`/restore` holt aus dem Papierkorb zurueck und laesst das Funddatum in
Ruhe - der Eintrag soll dort auftauchen, wo er hingehoert, also im
Archiv, wenn er alt ist. Die Meldung nennt das Ziel.
Dazu `DELETE /:id/permanent` und `POST /trash/empty`. Im Papierkorb wird
nicht gepflegt: Bearbeiten und Uebernehmen antworten 409.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Die Liste zeigte die zurueckgefallene Bewerbung, der Zaehler am Menue nicht: er
filterte weiter auf "nie uebernommen". Genau der Fehler, den zwei Kopien
derselben Regel machen.
Fristen und Bedingungen stehen jetzt in server/src/acquisitionRules.js und
werden von der Liste, den Zaehlern, dem Aufraeumlauf und der Menuezahl
gemeinsam benutzt.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>