diff --git a/backend/src/services/customer.service.ts b/backend/src/services/customer.service.ts index 918f02d5..45ec1d82 100644 --- a/backend/src/services/customer.service.ts +++ b/backend/src/services/customer.service.ts @@ -87,6 +87,24 @@ export async function getCustomerById(id: number) { readings: { orderBy: { readingDate: 'desc' }, }, + // Verträge, die diesen Zähler aktuell als Hauptzähler nutzen + // (energyDetails.meterId === meter.id) + energyDetails: { + include: { + contract: { select: { id: true, contractNumber: true, status: true, type: true, providerName: true } }, + }, + }, + // Verträge, in denen der Zähler in der ContractMeter-Kette steht + // (Vorgänger oder Nachfolger über Zählerwechsel) + contractMeters: { + include: { + energyContractDetails: { + include: { + contract: { select: { id: true, contractNumber: true, status: true, type: true, providerName: true } }, + }, + }, + }, + }, }, }, stressfreiEmails: { orderBy: { isActive: 'desc' } }, diff --git a/frontend/src/pages/customers/CustomerDetail.tsx b/frontend/src/pages/customers/CustomerDetail.tsx index 85524f4a..50f56505 100644 --- a/frontend/src/pages/customers/CustomerDetail.tsx +++ b/frontend/src/pages/customers/CustomerDetail.tsx @@ -1267,6 +1267,7 @@ function MetersTab({ const hasDeliveryAddress = addresses.some((a) => a.type === 'DELIVERY_RESIDENCE'); const [showReadingModal, setShowReadingModal] = useState<{ meterId: number; meterType: 'ELECTRICITY' | 'GAS'; tariffModel?: string } | null>(null); const [expandedMeter, setExpandedMeter] = useState(null); + const [expandedContractsForMeter, setExpandedContractsForMeter] = useState>(new Set()); const [editingReading, setEditingReading] = useState<{ meterId: number; meterType: 'ELECTRICITY' | 'GAS'; tariffModel?: string; reading: any } | null>(null); const queryClient = useQueryClient(); @@ -1441,6 +1442,77 @@ function MetersTab({

)} + {(() => { + // Zugeordnete Verträge zusammenstellen: zum einen über + // energyDetails (aktueller Hauptzähler), zum anderen über + // contractMeters (Folgezähler-Kette). Dedupliziert auf + // contractId, da ein Zähler über beide Wege auftauchen kann. + const seen = new Set(); + const linkedContracts: Array<{ id: number; contractNumber: string; status: string; type: string; providerName?: string; via: 'main' | 'chain' }> = []; + for (const ed of meter.energyDetails || []) { + if (ed.contract && !seen.has(ed.contract.id)) { + seen.add(ed.contract.id); + linkedContracts.push({ ...ed.contract, via: 'main' }); + } + } + for (const cm of meter.contractMeters || []) { + const ct = cm.energyContractDetails?.contract; + if (ct && !seen.has(ct.id)) { + seen.add(ct.id); + linkedContracts.push({ ...ct, via: 'chain' }); + } + } + if (linkedContracts.length === 0) return null; + const isContractsExpanded = expandedContractsForMeter.has(meter.id); + return ( +
+ + {isContractsExpanded && ( +
+ {linkedContracts.map((ct) => ( + + + {ct.contractNumber} + {ct.providerName && ( + – {ct.providerName} + )} + {ct.status} + {ct.via === 'chain' && ( + (über Folgezähler-Kette) + )} + + ))} +
+ )} +
+ ); + })()} + {sortedReadings.length > 0 && (
diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts index e0f45c48..67045355 100644 --- a/frontend/src/types/index.ts +++ b/frontend/src/types/index.ts @@ -221,6 +221,38 @@ export interface Meter { addressId?: number | null; address?: Address; readings?: MeterReading[]; + // Verträge, die diesen Zähler aktuell als Hauptzähler nutzen + energyDetails?: Array<{ + id: number; + contractId: number; + contract?: { + id: number; + contractNumber: string; + status: ContractStatus; + type: string; + providerName?: string; + }; + }>; + // Verträge, in denen der Zähler in der ContractMeter-Kette steht + // (Vorgänger oder Nachfolger über Zählerwechsel) + contractMeters?: Array<{ + id: number; + energyContractDetailsId: number; + position: number; + installedAt?: string; + removedAt?: string; + energyContractDetails?: { + id: number; + contractId: number; + contract?: { + id: number; + contractNumber: string; + status: ContractStatus; + type: string; + providerName?: string; + }; + }; + }>; } export interface ContractMeter {