feat(opportunities): Uebernahme zurueck in die Akquise schieben
Im Dialog einer Opportunity aus der Akquise nimmt "Zurueck in die Akquise" eine versehentliche Uebernahme zurueck: alle Opportunities aus dem Eintrag wandern in den Papierkorb, der Eintrag steht mit seinem Funddatum wieder in Eingang bzw. Archiv. Neue Spalte crm_opportunities.acquisition_id, damit bei mehreren Beratern alle gefunden werden. Wiederherstellen haengt den Eintrag wieder an die Opportunity. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
0ad7b32dbf
commit
33dedaedfb
@@ -66,6 +66,7 @@ erDiagram
|
||||
int id PK
|
||||
varchar title
|
||||
varchar consultant "fuer welchen Berater"
|
||||
int acquisition_id "Herkunft in der Akquise, ohne FK"
|
||||
enum stage "Neu .. Beauftragt | Absage"
|
||||
tinyint probability "0-100"
|
||||
decimal daily_rate
|
||||
@@ -199,6 +200,16 @@ Acht Eigenheiten, die man kennen muss:
|
||||
stehen, gleich welches Datum er trägt. Ein Kennzeichen
|
||||
„wiederhergestellt" gibt es nicht; es wäre der Zustand, den diese Tabelle
|
||||
gerade nicht führt.
|
||||
- **Der Rückweg von der Opportunity** (`POST /api/opportunities/:id/acquisition`)
|
||||
braucht die Gegenrichtung: `crm_acquisitions.opportunity_id` kennt nur die
|
||||
*erste* Opportunity einer Übernahme, bei mehreren Beratern entstehen aber
|
||||
mehrere. Deshalb trägt jede Opportunity `acquisition_id` (seit 17.09.2026,
|
||||
ohne Fremdschlüssel - die Akquise löscht nach 90 Tagen). `schema.sql` trägt
|
||||
den Verweis für ältere Übernahmen nach, kann das aber nur für die erste.
|
||||
Der Rückweg legt alle lebenden Opportunities mit dieser `acquisition_id` in
|
||||
den Papierkorb und leert beim Eintrag `converted_at` und `opportunity_id`;
|
||||
`found_at` bleibt. Wird eine davon wiederhergestellt, setzt `/restore` den
|
||||
Verweis wieder, sofern der Eintrag frei ist.
|
||||
- **Der Papierkorb ist die Ausnahme davon.** Löschen von Hand ist eine
|
||||
Entscheidung und kein Ablauf, deshalb steht sie in `deleted_at` (plus
|
||||
`deleted_by`, ohne Fremdschlüssel - siehe `schema.sql`). Vorher war das
|
||||
|
||||
@@ -266,12 +266,35 @@ zum Löschen wieder von vorn.
|
||||
|
||||
Bei einem **Rückfaller** (die Bewerbung war schon eine Opportunity) fragt das CRM
|
||||
nach: mit dem Wiederherstellen fällt der Verweis auf die gelöschte Opportunity
|
||||
weg. Der Eintrag ist danach wieder ein gewöhnlicher Fund - liegt die Opportunity
|
||||
noch im Papierkorb und wird sie zurückgeholt, steht sie ab dann *neben* dem
|
||||
Eintrag statt an seiner Stelle.
|
||||
weg. Der Eintrag ist danach wieder ein gewöhnlicher Fund. Liegt die Opportunity
|
||||
noch im Papierkorb und wird sie zurückgeholt, hängt der Eintrag wieder an ihr und
|
||||
verschwindet aus der Akquise - dasselbe Projekt steht nie an zwei Stellen.
|
||||
|
||||
Ein Eintrag, dessen Opportunity noch lebt, lässt sich nicht zurückholen - er
|
||||
steht ohnehin in keiner der beiden Listen.
|
||||
Ein Eintrag, dessen Opportunity noch lebt, lässt sich hier nicht zurückholen - er
|
||||
steht ohnehin in keiner der beiden Listen. Dafür gibt es den Weg von der
|
||||
Opportunity aus (nächster Abschnitt).
|
||||
|
||||
### Übernahme zurücknehmen
|
||||
|
||||
Aus Versehen übernommen? Im Dialog der Opportunity steht unten links
|
||||
**Zurück in die Akquise** - nur bei Opportunities, die aus der Akquise kommen und
|
||||
deren Eintrag dort noch existiert. Nach einer Rückfrage passiert:
|
||||
|
||||
* Der Eintrag steht wieder in der Akquise, als wäre er nie übernommen worden. Das
|
||||
**Funddatum bleibt**: jung im Eingang, älter als 14 Tage im Archiv. In der
|
||||
Auswertung zählt er nicht mehr als *übernommen*.
|
||||
* Die Opportunity wandert in den **Papierkorb** der Opportunities. Waren beim
|
||||
Eintrag **mehrere Berater** eingetragen, sind bei der Übernahme mehrere
|
||||
Opportunities entstanden - sie wandern **alle** mit.
|
||||
* Ungespeicherte Änderungen im Dialog gehen verloren.
|
||||
|
||||
Zurücknehmen darf, wer alle betroffenen Opportunities löschen darf (Ersteller,
|
||||
Zuständiger oder Administrator). Holt jemand eine davon aus dem Papierkorb
|
||||
zurück, hängt der Eintrag wieder an ihr und verschwindet aus der Akquise.
|
||||
|
||||
> Bei Übernahmen **vor dem 17.09.2026** kennt nur die jeweils *erste*
|
||||
> Opportunity ihren Eintrag. Bei mehreren Beratern bleiben die übrigen dann
|
||||
> stehen und müssen von Hand gelöscht werden.
|
||||
|
||||
### Papierkorb
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ Alle unter `router.use(requireAuth)`.
|
||||
| `leads.js` | `GET /`, `POST /`, `PATCH /:id`, `DELETE /:id`; Vorbereich: `GET /mail-pool/sources`, `POST /mail-pool/promote`, `POST /:id/promote` | jeder Angemeldete |
|
||||
| `connections.js` | `GET /`, `POST /`, `PATCH /:id`, `DELETE /:id` | jeder Angemeldete |
|
||||
| `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 |
|
||||
| `opportunities.js` | `GET /?trash=true`, `POST /`, `PATCH /:id`, `DELETE /:id` (Papierkorb), `POST /:id/restore`, `POST /:id/acquisition`, `POST /trash/empty` | ändern, löschen und wiederherstellen nur Ersteller, Zuständiger oder Admin; Leeren jeder Angemeldete. `/:id/acquisition` nimmt eine Übernahme zurück: alle lebenden Opportunities mit derselben `acquisition_id` in den Papierkorb, beim Eintrag `converted_at`/`opportunity_id` leeren (Funddatum bleibt), in einer Transaktion. `/restore` hängt den Eintrag wieder an die Opportunity, wenn er frei ist |
|
||||
| `acquisitions.js` | `GET /?view=eingang\|archiv\|papierkorb\|alle`, `POST /`, `PATCH /:id`, `DELETE /:id` (Papierkorb), `DELETE /:id/permanent`, `POST /trash/empty`, `POST /:id/opportunity`, `POST /:id/reopen`, `POST /:id/restore`; Auswahllisten: `GET/POST /options`, `PATCH/DELETE /options/:id` | Einträge ändern, löschen und zurückholen nur Ersteller oder Admin; Auswahllisten und Leeren jeder Angemeldete. Zwei verschiedene Rückwege, nicht zu verwechseln: `/reopen` holt aus dem **Archiv** in den Eingang (setzt `found_at` auf heute und leert `converted_at`/`opportunity_id` - sonst hält die Übernahme den Eintrag im Archiv fest), `/restore` holt aus dem **Papierkorb** zurück (leert nur `deleted_at`/`deleted_by`, das Funddatum bleibt). Beide antworten 409, wenn der Eintrag im falschen Zustand ist |
|
||||
| `badges.js` | `GET /` | Zahlen für die Seitenleiste: Akquise-Archiv und dessen Papierkorb, Papierkorb der Opportunities und der Mails, verworfene Scanner-Treffer. Der Scanner-Zähler ist `null`, wenn dessen Datenbank fehlt |
|
||||
| `acquisitionRules.js` (kein Router) | Fristen und die SQL-Bedingungen `IS_OPEN`, `IN_ARCHIVE`, `NOT_DUE`, `OPPORTUNITY_GONE`, `NOT_DELETED`, `IN_TRASH`. Geteilt von Liste, Zählern, Aufräumlauf und Menüzahl - zwei Kopien derselben Regel sind einmal auseinandergelaufen. Dazu `splitConsultants` / `joinConsultants` / `normalizeConsultants` für das Feld *Berater*, das mehrere Namen kommagetrennt hält (Gegenstück im Frontend: `src/types.ts`) |
|
||||
|
||||
Reference in New Issue
Block a user