feat(opportunities): Phasen des Vermittlungsprozesses, Kanban zuerst, Zahlen im Menue
Drei Dinge: - Die Phasen sind jetzt die des Vermittlungsprozesses: Neu, Beworben, Erstgespraech Berater, Kundenvorstellung, Interview Kunde, Zusage, Beauftragt, Absage. Offen ist alles bis einschliesslich Zusage - dort ist der Einsatz bestaetigt, die Beauftragung steht aber noch aus. migrateOpportunityStages() stellt bestehende Datenbanken um und setzt alle vorhandenen Opportunities auf "Neu": in welcher der neuen Phasen ein Projekt steckt, sagt der alte Trichter nicht (so mit dem Nutzer entschieden). Der Datenbankwert heisst 'Erstgespraech Berater' ohne Umlaut - Projektkonvention fuer Datenbankwerte. Angezeigt wird er ueber STAGE_LABELS; dazu gibt es STAGE_HINTS mit der Erlaeuterung je Phase als Titelhinweis an Auswahl, Badge und Spaltenkopf. - Kanban ist die erste Ansicht der Opportunities. Die Pipeline ist die Arbeitsansicht, Kachel und Liste sind zum Nachschauen. - Hinter "Archiv", beiden "Papierkorb"-Punkten und "Unpassend" steht die Anzahl, wie schon bei "Aus Mails". Die Zahlen kommen aus einem eigenen Endpunkt (/api/badges), weil sie alle ins Menue gehoeren und zusammen kommen sollen; Inhalte laedt weiter jede Ansicht selbst. Der Scanner liegt in einer eigenen Datenbank und kann fehlen - sein Zaehler ist dann null und die Leiste zeigt dort einfach keine Zahl. Der Aufruf haengt bewusst hinter den Daten und nicht im Promise.all: faellt er aus, bleibt das Menue ohne Zahlen statt die Ansicht mit einem Fehler. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
1ac0e2d2c7
commit
42639c65fa
@@ -63,7 +63,7 @@ erDiagram
|
||||
crm_opportunities {
|
||||
int id PK
|
||||
varchar title
|
||||
enum stage "Neu .. Verloren"
|
||||
enum stage "Neu .. Beauftragt | Absage"
|
||||
tinyint probability "0-100"
|
||||
decimal daily_rate
|
||||
decimal duration_days "Personentage, halbe möglich"
|
||||
|
||||
@@ -34,20 +34,20 @@ die Scanner-Einstellungen. Alles andere ist für beide Rollen gleich.
|
||||
│ Kategorien │ Titel der Ansicht [Hell/Dunkel] │
|
||||
│ Akquise ▾ │ │
|
||||
│ Eingang │ │
|
||||
│ Archiv │ │
|
||||
│ Archiv 3│ │
|
||||
│ Opportuni…▾ │───────────────────────────────────────────┤
|
||||
│ Alle │ │
|
||||
│ Papierkorb │ │
|
||||
│ Papierkorb2│ │
|
||||
│ Interviews │ │
|
||||
│ Kontakte ▾ │ Inhalt │
|
||||
│ Alle Kont. │ │
|
||||
│ Aus Mails 5│ │
|
||||
│ Mails ▾ │ │
|
||||
│ Postfach │ │
|
||||
│ Papierkorb │ │
|
||||
│ Papierkorb7│ │
|
||||
│ Scanner ▾ │ │
|
||||
│ Dashboard │ │
|
||||
│ Unpassend │ │
|
||||
│ Unpassend 4│ │
|
||||
│ Suchagenten│ │
|
||||
│ Börsen-… │ │
|
||||
├──────────────┤ │
|
||||
@@ -63,9 +63,12 @@ die Scanner-Einstellungen. Alles andere ist für beide Rollen gleich.
|
||||
auf den Schalter folgt wieder der Systemeinstellung.
|
||||
|
||||

|
||||
* Die Menüpunkte **Kontakte** und **Scanner** klappen beim Anklicken ihre
|
||||
Unterpunkte auf. Die Zahl neben *Aus Mails* sagt, wie viele Funde aus dem
|
||||
Postfach noch auf eine Entscheidung warten.
|
||||
* Die Menüpunkte **Akquise**, **Opportunities**, **Kontakte**, **Mails** und
|
||||
**Scanner** klappen beim Anklicken ihre Unterpunkte auf. Hinter einigen steht
|
||||
eine Zahl: *Aus Mails* (Funde, die auf eine Entscheidung warten), *Archiv*
|
||||
(Akquise-Einträge älter als 14 Tage), beide *Papierkörbe* und *Unpassend*
|
||||
(verworfene Scanner-Treffer). Bei 0 steht dort nichts - eine Null wäre nur
|
||||
Rauschen.
|
||||
* Jedes Fenster, das sich in den Vordergrund legt, schließt auf drei Wege: das
|
||||
**X** oben rechts, die Taste **Esc** oder ein **Klick daneben** in den
|
||||
abgedunkelten Hintergrund. Liegen zwei Fenster übereinander, betrifft das
|
||||
@@ -170,14 +173,40 @@ wechselt man die Darstellung:
|
||||
| --- | --- |
|
||||
| **Kachel** | Überblick mit Volumen, Tagessatz oder Projektpreis, Laufzeit, letzter Interaktion |
|
||||
| **Liste** | viele Einträge vergleichen, Spaltenköpfe sortieren |
|
||||
| **Pipeline** | Fortschritt durch die Phasen, Karten per Maus verschieben |
|
||||
| **Pipeline** (Kanban) | Fortschritt durch die Phasen, Karten per Maus verschieben. **Standardansicht** |
|
||||
|
||||

|
||||
|
||||
Die **Pipeline** zeigt dieselben Opportunities nach Phasen sortiert. Über jeder
|
||||
Spalte steht ihr Volumen; eine Karte wird per Maus in die nächste Phase gezogen.
|
||||
|
||||

|
||||

|
||||
|
||||
### Die Phasen
|
||||
|
||||
Sie folgen dem Vermittlungsprozess. Der Mauszeiger auf einer Phase zeigt dieselbe
|
||||
Erläuterung:
|
||||
|
||||
| Phase | Bedeutung |
|
||||
| --- | --- |
|
||||
| **Neu** | Projekt wurde identifiziert und noch nicht aktiv bearbeitet. |
|
||||
| **Beworben** | Beraterprofil wurde an Vermittler oder Direktkunden übermittelt. |
|
||||
| **Erstgespräch Berater** | Erstes qualifizierendes Gespräch mit dem Berater und Vermittler bzw. Direktkunden hat stattgefunden; ein reines Gespräch mit unserem Vertrieb zählt nicht. |
|
||||
| **Kundenvorstellung** | Beraterprofil wurde dem tatsächlichen Endkunden bzw. Entscheider zur Prüfung vorgestellt. |
|
||||
| **Interview Kunde** | Berater führt ein konkretes fachliches oder persönliches Gespräch mit dem Endkunden. |
|
||||
| **Zusage** | Einsatz des Beraters wurde bestätigt, die formale Beauftragung steht ggf. noch aus. |
|
||||
| **Beauftragt** | Vertrag bzw. Bestellung liegt vor und der Deal ist gewonnen. |
|
||||
| **Absage** | Projekt wird mit diesem Berater nicht weiterverfolgt. |
|
||||
|
||||
Als **offen** zählt alles bis einschließlich *Zusage* - dort ist der Einsatz
|
||||
bestätigt, aber noch nicht beauftragt. *Beauftragt* und *Absage* sind das Ende.
|
||||
Der Filter *Nur offene* nutzt genau diese Grenze, ebenso die Pipeline-Summe in
|
||||
der Kopfzeile.
|
||||
|
||||
> Bei der Umstellung am 18.08.2026 wurden **alle vorhandenen Opportunities auf
|
||||
> „Neu" gesetzt**. Der alte Trichter (Qualifizierung, Angebot, Verhandlung,
|
||||
> Gewonnen, Verloren) ließ nicht erkennen, in welcher der neuen Phasen ein
|
||||
> Projekt steckt.
|
||||
|
||||
**Volumen** rechnet die Anwendung selbst: Tagessatz x Personentage. Das
|
||||
**gewichtete** Volumen multipliziert das noch mit der Abschlusswahrscheinlichkeit.
|
||||
|
||||
@@ -93,6 +93,7 @@ Alle unter `router.use(requireAuth)`.
|
||||
| `events.js` | `GET /`, `POST /`, `PATCH /:id`, `DELETE /:id` | anlegen jeder; ändern/löschen nur Ersteller oder Admin |
|
||||
| `opportunities.js` | `GET /?trash=true`, `POST /`, `PATCH /:id`, `DELETE /:id` (Papierkorb), `POST /:id/restore`, `POST /trash/empty` | ändern, löschen und wiederherstellen nur Ersteller, Zuständiger oder Admin; Leeren jeder Angemeldete |
|
||||
| `acquisitions.js` | `GET /?view=eingang\|archiv\|alle`, `POST /`, `PATCH /:id`, `DELETE /:id`, `POST /:id/opportunity`; Auswahllisten: `GET/POST /options`, `PATCH/DELETE /options/:id` | Einträge ändern/löschen nur Ersteller oder Admin; Auswahllisten jeder Angemeldete |
|
||||
| `badges.js` | `GET /` | Zahlen für die Seitenleiste: Akquise-Archiv, beide Papierkörbe, verworfene Scanner-Treffer. Der Scanner-Zähler ist `null`, wenn dessen Datenbank fehlt |
|
||||
| `mail.js` | `GET /status`, `/messages`, `/messages/:id`, `/candidates`; `POST /messages/:id/links`, `/messages/:id/restore`, `/candidates/:id/adopt`, `/candidates/:id/reject`, `/trash/empty`; `DELETE /links/:id`, `/messages/:id`; `requireAdmin`: `GET/POST /settings`, `POST /test`, `POST /sync` | lesen, zuordnen und löschen jeder; einrichten Admin |
|
||||
|
||||
Wiederkehrende Muster in diesen Routern:
|
||||
@@ -266,6 +267,7 @@ Warum genau diese Konstanten festgelegt sind, steht in
|
||||
| Datei | Inhalt |
|
||||
| --- | --- |
|
||||
| `components/opportunities/OpportunityTrash.tsx` | Papierkorb der Opportunities: wiederherstellen, leeren, Restlaufzeit je Eintrag |
|
||||
| `components/opportunities/opportunityUi.tsx` | `STAGE_LABELS` (Anzeige, mit Umlaut), `STAGE_HINTS` (Erläuterung als Titelhinweis), `STAGE_STYLES`, `STAGE_COLORS`, `StageBadge` |
|
||||
| `components/acquisition/Acquisitions.tsx` | Akquise und Archiv (`view`); Suche, Sortierung, Übernahme, Löschen |
|
||||
| `components/acquisition/AcquisitionForm.tsx` | Eingabe über der Liste; behält Datum, Anbieter, Kanal und Berater für den nächsten Eintrag |
|
||||
| `components/acquisition/AcquisitionTable.tsx` | die Liste; `safeLink()` lässt nur http(s) zum Link werden |
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ Quelltext.
|
||||
| **Art** (eines Kontakts) | Recruiter, Partner oder Endkunde. Spalte `crm_leads.kind`; hieß bis 18.08.2026 „Status" mit den Werten Neu .. Verloren. |
|
||||
| **Papierkorb** (Mails) | Im CRM gelöschte Mails. Umkehrbar, bis er geleert wird. Im Postfach crm@perinco.de bleiben die Mails in jedem Fall; der Abgleich holt gelöschte nicht wieder herein. |
|
||||
| **Papierkorb** (Opportunities) | Gelöschte Opportunities, `crm_opportunities.deleted_at`. Wiederherstellbar; endgültig weg nach 90 Tagen oder beim Leeren. |
|
||||
| **Phase** / Stage | Fortschritt einer Opportunity: Neu, Qualifizierung, Angebot, Verhandlung, Gewonnen, Verloren. |
|
||||
| **Phase** / Stage | Fortschritt einer Opportunity im Vermittlungsprozess: Neu, Beworben, Erstgespräch Berater, Kundenvorstellung, Interview Kunde, Zusage, Beauftragt, Absage. Offen ist alles bis *Zusage*. In der Datenbank steht `Erstgespraech Berater` ohne Umlaut; angezeigt wird er (`STAGE_LABELS`). |
|
||||
| **Pipeline** | Zwei Bedeutungen, je nach Zusammenhang: die Kanban-Ansicht der Opportunities **oder** der Suchlauf des Scanners (`services/pipeline.js`). |
|
||||
| **Projekt** | Ein von einer Börse gescrapter Auftrag. Tabelle `projects`, Aufbewahrung 7 Tage. |
|
||||
| **Scraper** | Der Teil, der mit einem echten Browser (Playwright/Chromium) die Suchseiten der Börsen abruft. |
|
||||
|
||||
Reference in New Issue
Block a user