Vertragsauswahl: Kundennr./Zählernr./Telefonnr. in allen Pickern

Zentraler Helper contractLabel.ts liefert je nach Vertragstyp die
sinnvollen Zusatzinfos (nur wenn Daten vorhanden):
- Kdnr. <customer.customerNumber> (immer)
- Anbieter-Vtr. <contractNumberAtProvider>
- Zähler <meterNumber> (Strom/Gas)
- Mobil <main-SIM-Nummer> (Mobilfunk)
- Festnetz <main-phone> (Internet)

Backend contractApi.getAll include um energyDetails.meter und
internetDetails.phoneNumbers erweitert – vorher fehlten die im
Response.

Angewendet auf 5 Call-Sites:
- AssignToContractModal (Email-zu-Vertrag zuordnen)
- TaskList (Mitarbeiter- und Kundenportal-"Neue Aufgabe/Anfrage")
- Dashboard (Support-Anfrage-Modal)
- PdfTemplates (Test-Vorlage-Kontext-Auswahl)
- ContractForm (Vorgänger-Vertrag-Select)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-07-06 00:26:42 +02:00
co-authored by Claude Opus 4.7
parent 0b78323c7b
commit d14db3de2f
7 changed files with 187 additions and 11 deletions
+108
View File
@@ -0,0 +1,108 @@
// Einheitliches Label für Vertragsauswahl-Listen (Assign-Modals, Neue-
// Aufgabe, Neue-Support-Anfrage, Vorgänger-Vertrag, PDF-Vorlage-Test).
//
// User-Wunsch 2026-07-04: überall, wo man einen Vertrag aus einer Liste
// wählt, sollen zusätzlich zur Vertragsnummer folgende Infos sichtbar
// sein, sofern vorhanden:
// - Kundennummer (interne CRM-Nummer des Kunden)
// - Vertragsnummer beim Anbieter (contractNumberAtProvider)
// - Zählernummer (Strom/Gas, aus energyDetails.meter)
// - Mobilfunknummer (main SIM) bei Mobilfunk
// - Erste Festnetznummer bei Internet-Verträgen
//
// Der Helper liefert entweder eine flache Textzeile
// (`formatContractLabel`) oder ein strukturiertes Objekt mit Bestandteilen
// (`buildContractLabelParts`), damit UI-Views mit mehreren Zeilen /
// Badges das gleiche Modell teilen.
import type { Contract } from '../types';
export interface ContractLabelParts {
/** Interne Vertragsnummer (immer vorhanden). */
contractNumber: string;
/** Anbietername oder null, wenn keiner gesetzt ist. */
providerName: string | null;
/** Tarifname oder null. */
tariffName: string | null;
/**
* Kurze Zusatzinfos, jede nur wenn Daten existieren z.B.
* `Kdnr. 12345`, `Anbieter-Vtr. VG-2026`, `Zähler 1EMH…`,
* `Mobil +49 …`, `Festnetz +49 …`.
*/
extras: string[];
}
/**
* Fischt die relevanten Zusatzfelder aus dem Contract raus. Fehlende
* Felder werden übersprungen das Ergebnis passt sich automatisch dem
* Vertragstyp an (Zählernummer nur bei Strom/Gas, Mobilfunknr nur bei
* MOBILE, Festnetznr nur bei INTERNET etc.).
*/
export function buildContractLabelParts(contract: Contract): ContractLabelParts {
const providerName =
contract.provider?.name ??
(contract.providerName ? contract.providerName : null);
const tariffName =
contract.tariff?.name ??
(contract.tariffName ? contract.tariffName : null);
const extras: string[] = [];
const customerNumber = contract.customer?.customerNumber;
if (customerNumber) {
extras.push(`Kdnr. ${customerNumber}`);
}
const providerContractNumber = contract.contractNumberAtProvider;
if (providerContractNumber) {
extras.push(`Anbieter-Vtr. ${providerContractNumber}`);
}
const meterNumber = contract.energyDetails?.meter?.meterNumber;
if (meterNumber) {
extras.push(`Zähler ${meterNumber}`);
}
// Mobilfunk: Main-SIM-Nummer bevorzugt, sonst erste vorhandene.
const simCards = contract.mobileDetails?.simCards ?? [];
if (simCards.length > 0) {
const mainSim = simCards.find((s) => s.isMain && s.phoneNumber) ?? simCards.find((s) => !!s.phoneNumber);
if (mainSim?.phoneNumber) {
extras.push(`Mobil ${mainSim.phoneNumber}`);
} else if (contract.mobileDetails?.phoneNumber) {
extras.push(`Mobil ${contract.mobileDetails.phoneNumber}`);
}
} else if (contract.mobileDetails?.phoneNumber) {
extras.push(`Mobil ${contract.mobileDetails.phoneNumber}`);
}
// Festnetz: Main-Nummer bevorzugt, sonst erste vorhandene.
const phones = contract.internetDetails?.phoneNumbers ?? [];
if (phones.length > 0) {
const mainPhone = phones.find((p) => p.isMain && p.phoneNumber) ?? phones.find((p) => !!p.phoneNumber);
if (mainPhone?.phoneNumber) {
extras.push(`Festnetz ${mainPhone.phoneNumber}`);
}
}
return {
contractNumber: contract.contractNumber,
providerName,
tariffName,
extras,
};
}
/**
* Flach-String-Version für <Select>-Options:
* `GAS-XYZ · Anbieter · Tarif · Kdnr. 123 · Zähler 1EMH…`
* Trenner: ` · ` (schmale Bullets ohne Sonderzeichen im URL/DOM).
*/
export function formatContractLabel(contract: Contract): string {
const parts = buildContractLabelParts(contract);
const chunks: string[] = [parts.contractNumber];
if (parts.providerName) chunks.push(parts.providerName);
if (parts.tariffName) chunks.push(parts.tariffName);
chunks.push(...parts.extras);
return chunks.join(' · ');
}