fix(opportunities): Berater als eigenes Feld statt nur in den Notizen

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>
This commit is contained in:
Sascha Wolf
2026-09-09 14:07:23 +02:00
co-authored by Claude Opus 5
parent 8403f1c39d
commit 93fe8cfd73
13 changed files with 236 additions and 40 deletions
+10
View File
@@ -65,6 +65,7 @@ erDiagram
crm_opportunities {
int id PK
varchar title
varchar consultant "fuer welchen Berater"
enum stage "Neu .. Beauftragt | Absage"
tinyint probability "0-100"
decimal daily_rate
@@ -135,6 +136,15 @@ Acht Eigenheiten, die man kennen muss:
- **`avatar` ist eine Data-URL in der Datenbank.** Der Browser verkleinert jedes
Bild vor dem Upload auf 256 px (`src/lib/imageCompress.ts`), aus 2,9 MB werden
wenige Kilobyte.
- **Der Berater steht an der Opportunity, nicht nur in ihren Notizen.** Bis zum
09.09.2026 schrieb die Übernahme ihn in den Herkunftsvermerk, weil
`crm_opportunities` kein Feld dafür hatte - in Pipeline, Liste und Kacheln war
damit nicht zu sehen, für wen ein Projekt läuft. Jetzt trägt
`crm_opportunities.consultant` genau einen Namen; bei mehreren Beratern in der
Akquise entstehen mehrere Opportunities. Bestehende Zeilen füllt
`migrateOpportunityConsultant()` in `db.js` aus den Notizen nach - nur dort, wo
die Spalte leer ist, damit der Lauf wiederholbar bleibt und nichts
überschreibt.
- **Mehrere Berater stehen in einem Feld.** `crm_acquisitions.consultant`
nimmt eine kommagetrennte Liste auf (`VARCHAR(500)`), keine eigene
Zuordnungstabelle: die Namen sind reiner Text, die Auswahlliste in
+26 -11
View File
@@ -182,11 +182,10 @@ mehr im Auswahlfeld, es zeigt also immer nur, wer noch zu haben ist.
> **Was mehrere Berater bedeuten:** Beim Übernehmen entsteht **je Berater eine
> Opportunity** - jeder durchläuft seinen eigenen Vorgang, einer kann gewonnen
> werden und ein anderer verloren. Ihre Titel bekommen den Namen in Klammern
> angehängt, damit sie sich in Pipeline und Liste auseinanderhalten lassen; bei
> einem einzigen Berater bleibt der Titel unverändert. Im Dashboard zählt der
> Eintrag bei **jedem** der Berater - drei Berater sind drei versendete Profile,
> also drei Bewerbungen.
> werden und ein anderer verloren. Alle tragen denselben Titel und unterscheiden
> sich durch die Spalte **Berater**, die in Pipeline, Liste und Kacheln steht.
> Im Dashboard zählt der Eintrag bei **jedem** der Berater - drei Berater sind
> drei versendete Profile, also drei Bewerbungen.
**Von** ist mit dem **angemeldeten Benutzer** vorbelegt - in der Regel trägt
jeder seine eigenen Funde ein. Trägt Markus etwas für Artur ein, wählt er Artur
@@ -302,14 +301,21 @@ im Archiv.
Der Knopf **Opportunity** legt sie sofort an: Phase *Erstgespräch Berater*, 10 % Wahrscheinlichkeit,
zuständig ist der angemeldete Benutzer. Mit übernommen werden Titel, Endkunde,
Beschreibung, Tagessatz, Laufzeit, Projektpreis, Zeitraum und nächster Schritt.
Sind **mehrere Berater** hinterlegt, entsteht **je Berater eine Opportunity**
mit denselben Projektdaten; ihr Titel trägt den Namen in Klammern. In den Notizen
steht neben dem eigenen Berater auch, mit wem er sich das Projekt teilt
Der **Berater** wandert in das gleichnamige Feld der Opportunity und steht damit
in Pipeline, Liste und Kacheln - für wen ein Projekt läuft, ist neben dem Titel
die wichtigste Angabe. Sind **mehrere Berater** hinterlegt, entsteht **je Berater
eine Opportunity** mit denselben Projektdaten, jede mit ihrem eigenen Namen im
Feld. In den Notizen steht zusätzlich, mit wem er sich das Projekt teilt
(*Auch beworben*).
Anbieter, Von, Kanal, Berater und Link haben in der Opportunity kein Feld - sie
landen als Herkunftsvermerk in den internen Notizen, damit nachvollziehbar
bleibt, woher das Projekt kam.
Anbieter, Von, Kanal und Link haben in der Opportunity kein Feld - sie landen als
Herkunftsvermerk in den internen Notizen, damit nachvollziehbar bleibt, woher das
Projekt kam.
> **Opportunities von vor dem 09.09.2026:** Bis dahin hatte die Opportunity kein
> Feld für den Berater, der Name stand nur im Herkunftsvermerk. Beim ersten Start
> nach der Umstellung holt das CRM ihn von dort in das Feld - von Hand ist nichts
> zu tun.
Ansprechpartner hängt man danach in der Opportunity dran; dort geht das auch für
Kontakte, die es noch nicht gibt.
@@ -375,6 +381,15 @@ Vorschau im Formular schreibt dazu, welche Grundlage gerade zählt
Tagessatzes den Projektpreis. Tagessatz und Laufzeit dürfen trotzdem gefüllt
bleiben, etwa zur eigenen Kalkulation.
Das Feld **Berater** sagt, für wen das Projekt läuft. Die Auswahl ist dieselbe
Liste wie in der Akquise, gepflegt unter *Einstellungen → Akquise* - damit hier
nicht „Nico" und dort „Nico N." entsteht. Der Name steht auf der Kachel, in der
Listenspalte *Berater* (sortierbar), auf der Pipeline-Karte und im Papierkorb; die
Suche findet ihn ebenfalls. Genau **ein** Berater je Opportunity: passt ein Fund
der Akquise zu dreien, entstehen bei der Übernahme drei Opportunities. Steht in
einer alten Opportunity ein Name, den die Liste nicht mehr kennt, bleibt er
wählbar und ist als *(nicht in der Liste)* gekennzeichnet.
Zu jeder Opportunity gehören beliebig viele **Ansprechpartner** aus den
Kontakten, jeder mit eigener Rolle („Entscheider", „Fachbereich", …). Fehlt
jemand noch im CRM, öffnet **Neuer Kontakt...** direkt neben der Auswahlliste