Zähler → Lieferadresse-Pflichtfeld + Vertragsfilter
- Meter.addressId (FK → Address, ON DELETE SET NULL) + Migration 20260530100000_meter_address mit IF NOT EXISTS - Service erzwingt beim Create: Lieferadresse vorhanden + zum Kunden gehörig + Typ DELIVERY_RESIDENCE - MeterModal: Pflicht-Dropdown "Lieferadresse"; Save disabled ohne Adresse; Hinweis-Banner. Bestandszähler ohne Adresse zeigen "nicht zugeordnet – bitte über Bearbeiten nachpflegen" - ContractForm: Zähler-Dropdown filtert auf Vertrags-Lieferadresse; deaktivierte Zähler bleiben sichtbar mit "(deaktiviert)"; bei Auswahl Toast-Warnung wegen möglichem Altvertrag Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@ import { useNavigate, useParams, useSearchParams, useLocation } from 'react-rout
|
||||
import { popHistory } from '../../utils/navigation';
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import toast from 'react-hot-toast';
|
||||
import { contractApi, customerApi, platformApi, cancellationPeriodApi, contractDurationApi, providerApi, contractCategoryApi } from '../../services/api';
|
||||
import Card from '../../components/ui/Card';
|
||||
import Button from '../../components/ui/Button';
|
||||
@@ -964,16 +965,47 @@ export default function ContractForm() {
|
||||
{['ELECTRICITY', 'GAS'].includes(contractType) && (
|
||||
<Card className="mb-6" title={contractType === 'ELECTRICITY' ? 'Strom-Details' : 'Gas-Details'}>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<Select
|
||||
label="Zähler"
|
||||
{...register('meterId')}
|
||||
options={meters
|
||||
.filter((m) => m.type === contractType && (m.isActive || m.id.toString() === watch('meterId')))
|
||||
.map((m) => ({
|
||||
value: m.id,
|
||||
label: `${m.meterNumber}${m.location ? ` (${m.location})` : ''}${!m.isActive ? ' (deaktiviert)' : ''}`,
|
||||
}))}
|
||||
/>
|
||||
{(() => {
|
||||
const selectedAddressId = watch('addressId');
|
||||
const meterRegister = register('meterId');
|
||||
// Zähler werden auf die Lieferadresse des Vertrags gefiltert. Zähler ohne
|
||||
// Lieferadresse (Bestand) bleiben für den aktuell gewählten Eintrag sichtbar,
|
||||
// damit die Auswahl nicht verschwindet, bis sie nachgepflegt sind.
|
||||
const filteredMeters = meters.filter((m) => {
|
||||
if (m.type !== contractType) return false;
|
||||
const isCurrentlySelected = m.id.toString() === watch('meterId');
|
||||
if (isCurrentlySelected) return true;
|
||||
if (!selectedAddressId) return false;
|
||||
return m.addressId != null && m.addressId.toString() === selectedAddressId;
|
||||
});
|
||||
return (
|
||||
<Select
|
||||
label="Zähler"
|
||||
{...meterRegister}
|
||||
onChange={(e) => {
|
||||
meterRegister.onChange(e);
|
||||
const m = meters.find((x) => x.id.toString() === e.target.value);
|
||||
if (m && !m.isActive) {
|
||||
toast(
|
||||
'Deaktivierter Zähler ausgewählt. Ist das gewollt? Handelt es sich um einen Altvertrag?',
|
||||
{ icon: '⚠️', duration: 6000 },
|
||||
);
|
||||
}
|
||||
}}
|
||||
options={filteredMeters.map((m) => ({
|
||||
value: m.id,
|
||||
label: `${m.meterNumber}${m.location ? ` (${m.location})` : ''}${!m.isActive ? ' (deaktiviert)' : ''}`,
|
||||
}))}
|
||||
placeholder={
|
||||
!selectedAddressId
|
||||
? 'Erst Lieferadresse wählen...'
|
||||
: filteredMeters.length === 0
|
||||
? 'Kein Zähler für diese Adresse vorhanden'
|
||||
: 'Zähler wählen...'
|
||||
}
|
||||
/>
|
||||
);
|
||||
})()}
|
||||
<Input
|
||||
label="MaLo-ID (Marktlokations-ID)"
|
||||
{...register('maloId')}
|
||||
|
||||
Reference in New Issue
Block a user