From d14db3de2fce4098dd3f0098b6f68cde20de003c Mon Sep 17 00:00:00 2001 From: duffyduck Date: Mon, 6 Jul 2026 00:26:42 +0200 Subject: [PATCH] =?UTF-8?q?Vertragsauswahl:=20Kundennr./Z=C3=A4hlernr./Tel?= =?UTF-8?q?efonnr.=20in=20allen=20Pickern?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Zentraler Helper contractLabel.ts liefert je nach Vertragstyp die sinnvollen Zusatzinfos (nur wenn Daten vorhanden): - Kdnr. (immer) - Anbieter-Vtr. - Zähler (Strom/Gas) - Mobil (Mobilfunk) - Festnetz (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 --- backend/src/services/contract.service.ts | 16 +++ .../email/AssignToContractModal.tsx | 9 ++ frontend/src/pages/Dashboard.tsx | 9 ++ frontend/src/pages/contracts/ContractForm.tsx | 14 ++- frontend/src/pages/settings/PdfTemplates.tsx | 25 ++-- frontend/src/pages/tasks/TaskList.tsx | 17 +++ frontend/src/utils/contractLabel.ts | 108 ++++++++++++++++++ 7 files changed, 187 insertions(+), 11 deletions(-) create mode 100644 frontend/src/utils/contractLabel.ts diff --git a/backend/src/services/contract.service.ts b/backend/src/services/contract.service.ts index 9afbff3f..21c07ec9 100644 --- a/backend/src/services/contract.service.ts +++ b/backend/src/services/contract.service.ts @@ -102,6 +102,22 @@ export async function getAllContracts(filters: ContractFilters) { simCards: { select: { phoneNumber: true, isMain: true } }, }, }, + // 2026-07-04: für Vertragsauswahl-Labels brauchen wir überall + // die Zählernummer (Strom/Gas) und die erste Festnetznummer + // (Internet). Beides light-select, damit das Payload klein bleibt. + energyDetails: { + select: { + meter: { select: { id: true, meterNumber: true } }, + }, + }, + internetDetails: { + select: { + phoneNumbers: { + select: { phoneNumber: true, isMain: true }, + orderBy: { id: 'asc' }, + }, + }, + }, carInsuranceDetails: { select: { licensePlate: true } }, }, }), diff --git a/frontend/src/components/email/AssignToContractModal.tsx b/frontend/src/components/email/AssignToContractModal.tsx index d56f7fb0..2344bcec 100644 --- a/frontend/src/components/email/AssignToContractModal.tsx +++ b/frontend/src/components/email/AssignToContractModal.tsx @@ -4,6 +4,7 @@ import Modal from '../ui/Modal'; import Button from '../ui/Button'; import { contractApi, cachedEmailApi, CachedEmail } from '../../services/api'; import { formatDate } from '../../utils/dateFormat'; +import { buildContractLabelParts } from '../../utils/contractLabel'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; interface AssignToContractModalProps { @@ -147,6 +148,14 @@ export default function AssignToContractModal({ {contract.contractCategory?.name} {contract.provider && ` - ${contract.provider.name}`} + {(() => { + const parts = buildContractLabelParts(contract); + return parts.extras.length > 0 ? ( +
+ {parts.extras.join(' · ')} +
+ ) : null; + })()}
Start: {formatDateOrDash(contract.startDate)}
diff --git a/frontend/src/pages/Dashboard.tsx b/frontend/src/pages/Dashboard.tsx index 4f937733..8f89df43 100644 --- a/frontend/src/pages/Dashboard.tsx +++ b/frontend/src/pages/Dashboard.tsx @@ -3,6 +3,7 @@ import { useQuery, useQueryClient } from '@tanstack/react-query'; import { Link, useNavigate } from 'react-router-dom'; import { useAuth } from '../context/AuthContext'; import { customerApi, contractApi, contractTaskApi, appSettingsApi } from '../services/api'; +import { buildContractLabelParts } from '../utils/contractLabel'; import Card from '../components/ui/Card'; import Button from '../components/ui/Button'; import Input from '../components/ui/Input'; @@ -572,6 +573,14 @@ function CreateSupportTicketModal({ {contract.providerName || 'Kein Anbieter'} {contract.tariffName && ` - ${contract.tariffName}`} + {(() => { + const parts = buildContractLabelParts(contract); + return parts.extras.length > 0 ? ( +
+ {parts.extras.join(' · ')} +
+ ) : null; + })()} )) ) : ( diff --git a/frontend/src/pages/contracts/ContractForm.tsx b/frontend/src/pages/contracts/ContractForm.tsx index 7da15343..8df2bf6a 100644 --- a/frontend/src/pages/contracts/ContractForm.tsx +++ b/frontend/src/pages/contracts/ContractForm.tsx @@ -11,6 +11,7 @@ import Input from '../../components/ui/Input'; import Select from '../../components/ui/Select'; import CopyButton from '../../components/ui/CopyButton'; import CustomerInfoModal from '../../components/contracts/CustomerInfoModal'; +import { buildContractLabelParts } from '../../utils/contractLabel'; import type { ContractType } from '../../types'; import { formatDate } from '../../utils/dateFormat'; import { useProviderSettings } from '../../hooks/useProviderSettings'; @@ -878,10 +879,15 @@ export default function ContractForm() { -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(' · '); +}