feat(opportunities): Festpreis, Klick daneben, Kontakt von hier
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>
This commit is contained in:
co-authored by
Claude Opus 5
parent
30164e0ae7
commit
025390e18a
@@ -64,6 +64,7 @@ erDiagram
|
||||
tinyint probability "0-100"
|
||||
decimal daily_rate
|
||||
decimal duration_days "Personentage, halbe möglich"
|
||||
decimal fixed_price "Festpreis statt Tagessatz x Laufzeit"
|
||||
date last_interaction_at
|
||||
varchar next_step
|
||||
int owner_id FK
|
||||
|
||||
@@ -58,6 +58,11 @@ die Scanner-Einstellungen. Alles andere ist für beide Rollen gleich.
|
||||
* 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.
|
||||
* 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
|
||||
immer nur das obere. Eine Textmarkierung, die im Fenster beginnt und
|
||||
daneben endet, schließt nichts.
|
||||
|
||||
> Alle Abbildungen in dieser Anleitung zeigen die Anwendung mit **erfundenen
|
||||
> Beispieldaten**. Firmen, Personen und Zahlen darin gibt es nicht.
|
||||
@@ -69,7 +74,7 @@ wechselt man die Darstellung:
|
||||
|
||||
| Ansicht | wofür |
|
||||
| --- | --- |
|
||||
| **Kachel** | Überblick mit Volumen, Tagessatz, Laufzeit, letzter Interaktion |
|
||||
| **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 |
|
||||
|
||||
@@ -85,8 +90,20 @@ Spalte steht ihr Volumen; eine Karte wird per Maus in die nächste Phase gezogen
|
||||
Beide Zahlen stehen live im Formular, auf jeder Karte, als Summe über der Liste,
|
||||
je Pipeline-Spalte und in der Kopfzeile.
|
||||
|
||||
Nicht jedes Projekt rechnet nach Aufwand. Für Festpreise gibt es unter
|
||||
*Projektdaten* das Feld **Projektpreis**. Steht dort eine Zahl, gilt sie als
|
||||
Volumen - Tagessatz und Laufzeit werden dann nicht mehr multipliziert. Die
|
||||
Vorschau im Formular schreibt dazu, welche Grundlage gerade zählt
|
||||
(*Festpreis* oder *Tagessatz x Laufzeit*); Kachel und Liste zeigen statt des
|
||||
Tagessatzes den Projektpreis. Tagessatz und Laufzeit dürfen trotzdem gefüllt
|
||||
bleiben, etwa zur eigenen Kalkulation.
|
||||
|
||||
Zu jeder Opportunity gehören beliebig viele **Ansprechpartner** aus den
|
||||
Kontakten, jeder mit eigener Rolle („Entscheider", „Fachbereich", …).
|
||||
Kontakten, jeder mit eigener Rolle („Entscheider", „Fachbereich", …). Fehlt
|
||||
jemand noch im CRM, öffnet **Neuer Kontakt...** direkt neben der Auswahlliste
|
||||
dasselbe Formular wie unter *Kontakte*. Nach dem Speichern hängt der neue
|
||||
Kontakt sofort als Ansprechpartner an der Opportunity - die man dabei nicht
|
||||
verlässt.
|
||||
|
||||
Ändern und löschen darf der **Ersteller**, der **Zuständige** und jeder
|
||||
**Administrator**. Wer keines davon ist, bekommt eine Fehlermeldung - das prüft
|
||||
|
||||
@@ -250,7 +250,7 @@ Warum genau diese Konstanten festgelegt sind, steht in
|
||||
| `components/scanner/scannerUi.tsx` | `cardClass`, Buttonklassen, `MatchBadge`, `MatchStatusBadge`, `PortalStatusPill`, `formatDateTime`, `projectTimestamp` |
|
||||
| `components/mail/mailUi.tsx` | `Badge`, `ConfidenceBar`, Herkunfts- und Statusbeschriftungen, `formatAddresses`, `avatarColor` |
|
||||
| `components/mail/MailBody.tsx` | Mailinhalt im `<iframe sandbox="">`, externe Bilder per CSP gesperrt |
|
||||
| `components/ui/Modal.tsx` | `Modal` (Escape schließt) und `ConfirmDialog` |
|
||||
| `components/ui/Modal.tsx` | `Modal` und `ConfirmDialog`; `useDismiss()` schließt per Escape und per Klick in den Hintergrund. Escape trifft nur den obersten Dialog (Stapel `openModals`), der Hintergrundklick muss dort beginnen **und** enden |
|
||||
| `components/Toast.tsx` | `useToast().addToast(text, kind)` mit `success`, `error` oder `info` |
|
||||
| `components/ui/DictationField.tsx` | Mikrofon-Knopf, Hinweisbox, Textfeld mit Diktat |
|
||||
| `lib/imageCompress.ts` | `compressImage()` auf 256 px, WebP → JPEG → PNG |
|
||||
@@ -265,7 +265,7 @@ nicht auseinanderlaufen:
|
||||
| `ViewState`, `SettingsTab`, `ADMIN_SETTINGS_TABS`, `SCANNER_VIEWS` | Ansichten und Reiter |
|
||||
| `MAIL_LEAD_SOURCE`, `LeadOriginFilter` | Herkunft „Mail" in `Lead.source` und ihr Filter |
|
||||
| `USER_COLORS`, `userColor()` | Farbe gesetzt, sonst stabil aus der Benutzer-Id |
|
||||
| `opportunityVolume()`, `weightedVolume()`, `formatEuro()` | Tagessatz x Personentage, gewichtet, formatiert |
|
||||
| `opportunityVolume()`, `weightedVolume()`, `formatEuro()` | Festpreis, sonst Tagessatz x Personentage; gewichtet; formatiert |
|
||||
| `OPPORTUNITY_STAGES`, `OPEN_STAGES`, `LEAD_STATUSES`, `CONNECTION_TYPES` | die Aufzählungen der Datenbank |
|
||||
| `eventColor()`, `leadFullName()`, `leadInitials()`, `contactFullName()` | Anzeigelogik |
|
||||
|
||||
|
||||
+2
-2
@@ -20,7 +20,7 @@ Quelltext.
|
||||
| **Dublette** (Aus Mails) | Ein Fund, zu dem es in den Kontakten schon eine Person gibt - erkannt an der E-Mail-Adresse, sonst am vollen Namen. In der Liste **gold** markiert, abweichende Felder hervorgehoben. |
|
||||
| **Kontakt-Vorschlag** | Aus einer Mail gelesene Person, die noch kein Kontakt ist. Tabelle `crm_mail_contact_candidates`. Wird übernommen, ergänzt oder verworfen. |
|
||||
| **Match** / Treffer | Die Bewertung **eines** Projekts für **einen** Agenten: Prozentwert, Pro-Liste, Contra-Liste, Status. Tabelle `matches`. Ein Projekt erzeugt so viele Treffer, wie es aktive Agenten gibt. |
|
||||
| **Opportunity** | Geschäft in Arbeit: Phase, Tagessatz, Laufzeit, Wahrscheinlichkeit, Ansprechpartner. Tabelle `crm_opportunities`. |
|
||||
| **Opportunity** | Geschäft in Arbeit: Phase, Tagessatz und Laufzeit oder Projektpreis, Wahrscheinlichkeit, Ansprechpartner. Tabelle `crm_opportunities`. |
|
||||
| **Phase** / Stage | Fortschritt einer Opportunity: Neu, Qualifizierung, Angebot, Verhandlung, Gewonnen, Verloren. |
|
||||
| **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. |
|
||||
@@ -31,7 +31,7 @@ Quelltext.
|
||||
| **Schwellenwert Anzeige** | `display_threshold` - Treffer darunter bleiben im Dashboard ausgeblendet. |
|
||||
| **Schwellenwert Benachrichtigung** | `match_threshold` - ab hier gibt es Signalton und E-Mail. |
|
||||
| **Verbindung** | Kante zwischen zwei Kontakten im Netzwerkdiagramm, mit Art und Stärke. Tabelle `crm_lead_connections`. |
|
||||
| **Volumen** | Tagessatz x Personentage. **Gewichtet** heißt zusätzlich mit der Abschlusswahrscheinlichkeit multipliziert. |
|
||||
| **Volumen** | Tagessatz x Personentage - oder der **Projektpreis**, wenn einer eingetragen ist. **Gewichtet** heißt zusätzlich mit der Abschlusswahrscheinlichkeit multipliziert. |
|
||||
| **Whisper** | Das Spracherkennungsmodell für das Diktat. Läuft im Browser, nicht auf dem Server. |
|
||||
| **Zugriffsrichtlinie** | `ApplicationAccessPolicy` in Exchange Online. Begrenzt eine App-only-Berechtigung auf einzelne Postfächer - ohne sie gilt sie tenant-weit. |
|
||||
| **Zuständiger** / Owner | Benutzer, dem ein Kontakt oder eine Opportunity zugeordnet ist. Darf sie ändern, auch wenn er sie nicht angelegt hat. |
|
||||
|
||||
Reference in New Issue
Block a user