added extra field kwh at m3, expand cost field to 10 komma, added maloid,counter add dialog, auto set unit
This commit is contained in:
@@ -9,7 +9,6 @@ import Card from '../../components/ui/Card';
|
||||
import Button from '../../components/ui/Button';
|
||||
import Badge from '../../components/ui/Badge';
|
||||
import Input from '../../components/ui/Input';
|
||||
import Select from '../../components/ui/Select';
|
||||
import Modal from '../../components/ui/Modal';
|
||||
import FileUpload from '../../components/ui/FileUpload';
|
||||
import { Edit, Trash2, Copy, Eye, EyeOff, ArrowLeft, ArrowRight, Download, ExternalLink, Plus, ChevronDown, ChevronUp, Gauge, CheckCircle, Circle, ClipboardList, MessageSquare } from 'lucide-react';
|
||||
@@ -320,7 +319,6 @@ function MeterReadingModal({
|
||||
? new Date(reading.readingDate).toISOString().split('T')[0]
|
||||
: new Date().toISOString().split('T')[0],
|
||||
value: reading?.value?.toString() || '',
|
||||
unit: reading?.unit || defaultUnit,
|
||||
notes: reading?.notes || '',
|
||||
});
|
||||
|
||||
@@ -345,7 +343,7 @@ function MeterReadingModal({
|
||||
const data = {
|
||||
readingDate: new Date(formData.readingDate),
|
||||
value: parseFloat(formData.value),
|
||||
unit: formData.unit,
|
||||
unit: defaultUnit,
|
||||
notes: formData.notes || undefined,
|
||||
};
|
||||
if (isEditing) {
|
||||
@@ -379,15 +377,12 @@ function MeterReadingModal({
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<Select
|
||||
label="Einheit"
|
||||
value={formData.unit}
|
||||
onChange={(e) => setFormData({ ...formData, unit: e.target.value })}
|
||||
options={[
|
||||
{ value: 'kWh', label: 'kWh' },
|
||||
{ value: 'm³', label: 'm³' },
|
||||
]}
|
||||
/>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Einheit</label>
|
||||
<div className="h-10 flex items-center px-3 bg-gray-100 border border-gray-300 rounded-md text-gray-700">
|
||||
{defaultUnit}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Input
|
||||
@@ -1931,27 +1926,43 @@ export default function ContractDetail() {
|
||||
</dd>
|
||||
</div>
|
||||
)}
|
||||
{c.energyDetails.maloId && (
|
||||
<div>
|
||||
<dt className="text-sm text-gray-500">MaLo-ID</dt>
|
||||
<dd className="font-mono flex items-center gap-1">
|
||||
{c.energyDetails.maloId}
|
||||
<CopyButton value={c.energyDetails.maloId} />
|
||||
</dd>
|
||||
</div>
|
||||
)}
|
||||
{c.energyDetails.annualConsumption && (
|
||||
<div>
|
||||
<dt className="text-sm text-gray-500">Jahresverbrauch</dt>
|
||||
<dt className="text-sm text-gray-500">
|
||||
Jahresverbrauch {c.type === 'ELECTRICITY' ? '' : '(m³)'}
|
||||
</dt>
|
||||
<dd>
|
||||
{c.energyDetails.annualConsumption.toLocaleString('de-DE')}{' '}
|
||||
{c.type === 'ELECTRICITY' ? 'kWh' : 'm³'}
|
||||
</dd>
|
||||
</div>
|
||||
)}
|
||||
{c.energyDetails.basePrice && (
|
||||
{c.type === 'GAS' && c.energyDetails.annualConsumptionKwh && (
|
||||
<div>
|
||||
<dt className="text-sm text-gray-500">Grundpreis</dt>
|
||||
<dd>{c.energyDetails.basePrice.toLocaleString('de-DE')} €/Monat</dd>
|
||||
<dt className="text-sm text-gray-500">Jahresverbrauch (kWh)</dt>
|
||||
<dd>{c.energyDetails.annualConsumptionKwh.toLocaleString('de-DE')} kWh</dd>
|
||||
</div>
|
||||
)}
|
||||
{c.energyDetails.unitPrice && (
|
||||
{c.energyDetails.basePrice != null && (
|
||||
<div>
|
||||
<dt className="text-sm text-gray-500">Grundpreis</dt>
|
||||
<dd>{c.energyDetails.basePrice.toLocaleString('de-DE', { minimumFractionDigits: 2, maximumFractionDigits: 10 })} €/Monat</dd>
|
||||
</div>
|
||||
)}
|
||||
{c.energyDetails.unitPrice != null && (
|
||||
<div>
|
||||
<dt className="text-sm text-gray-500">Arbeitspreis</dt>
|
||||
<dd>
|
||||
{c.energyDetails.unitPrice.toLocaleString('de-DE')} ct/
|
||||
{c.type === 'ELECTRICITY' ? 'kWh' : 'm³'}
|
||||
{c.energyDetails.unitPrice.toLocaleString('de-DE', { minimumFractionDigits: 2, maximumFractionDigits: 10 })} €/kWh
|
||||
</dd>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -228,7 +228,9 @@ export default function ContractForm() {
|
||||
notes: c.notes || '',
|
||||
// Energy details
|
||||
meterId: c.energyDetails?.meterId?.toString() || '',
|
||||
maloId: c.energyDetails?.maloId || '',
|
||||
annualConsumption: c.energyDetails?.annualConsumption || '',
|
||||
annualConsumptionKwh: c.energyDetails?.annualConsumptionKwh || '',
|
||||
basePrice: c.energyDetails?.basePrice || '',
|
||||
unitPrice: c.energyDetails?.unitPrice || '',
|
||||
bonus: c.energyDetails?.bonus || '',
|
||||
@@ -455,7 +457,9 @@ export default function ContractForm() {
|
||||
if (['ELECTRICITY', 'GAS'].includes(data.type)) {
|
||||
contractData.energyDetails = {
|
||||
meterId: safeParseInt(data.meterId) ?? null,
|
||||
maloId: emptyToNull(data.maloId),
|
||||
annualConsumption: data.annualConsumption ? parseFloat(data.annualConsumption) : null,
|
||||
annualConsumptionKwh: data.annualConsumptionKwh ? parseFloat(data.annualConsumptionKwh) : null,
|
||||
basePrice: data.basePrice ? parseFloat(data.basePrice) : null,
|
||||
unitPrice: data.unitPrice ? parseFloat(data.unitPrice) : null,
|
||||
bonus: data.bonus ? parseFloat(data.bonus) : null,
|
||||
@@ -864,16 +868,27 @@ export default function ContractForm() {
|
||||
label: `${m.meterNumber}${m.location ? ` (${m.location})` : ''}`,
|
||||
}))}
|
||||
/>
|
||||
<Input
|
||||
label="MaLo-ID (Marktlokations-ID)"
|
||||
{...register('maloId')}
|
||||
/>
|
||||
<Input
|
||||
label={`Jahresverbrauch (${contractType === 'ELECTRICITY' ? 'kWh' : 'm³'})`}
|
||||
type="number"
|
||||
{...register('annualConsumption')}
|
||||
/>
|
||||
<Input label="Grundpreis (€/Monat)" type="number" step="0.01" {...register('basePrice')} />
|
||||
{contractType === 'GAS' && (
|
||||
<Input
|
||||
label="Jahresverbrauch (kWh)"
|
||||
type="number"
|
||||
{...register('annualConsumptionKwh')}
|
||||
/>
|
||||
)}
|
||||
<Input label="Grundpreis (€/Monat)" type="number" step="any" {...register('basePrice')} />
|
||||
<Input
|
||||
label={`Arbeitspreis (ct/${contractType === 'ELECTRICITY' ? 'kWh' : 'm³'})`}
|
||||
label="Arbeitspreis (€/kWh)"
|
||||
type="number"
|
||||
step="0.01"
|
||||
step="any"
|
||||
{...register('unitPrice')}
|
||||
/>
|
||||
<Input label="Bonus (€)" type="number" step="0.01" {...register('bonus')} />
|
||||
|
||||
@@ -1256,9 +1256,9 @@ function MetersTab({
|
||||
onAdd: () => void;
|
||||
onEdit: (meter: Meter) => void;
|
||||
}) {
|
||||
const [showReadingModal, setShowReadingModal] = useState<number | null>(null);
|
||||
const [showReadingModal, setShowReadingModal] = useState<{ meterId: number; meterType: 'ELECTRICITY' | 'GAS' } | null>(null);
|
||||
const [expandedMeter, setExpandedMeter] = useState<number | null>(null);
|
||||
const [editingReading, setEditingReading] = useState<{ meterId: number; reading: any } | null>(null);
|
||||
const [editingReading, setEditingReading] = useState<{ meterId: number; meterType: 'ELECTRICITY' | 'GAS'; reading: any } | null>(null);
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const updateMutation = useMutation({
|
||||
@@ -1333,7 +1333,7 @@ function MetersTab({
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setShowReadingModal(meter.id)}
|
||||
onClick={() => setShowReadingModal({ meterId: meter.id, meterType: meter.type })}
|
||||
title="Zählerstand hinzufügen"
|
||||
>
|
||||
<Plus className="w-4 h-4" />
|
||||
@@ -1430,7 +1430,7 @@ function MetersTab({
|
||||
{canEdit && (
|
||||
<div className="opacity-0 group-hover:opacity-100 flex gap-1">
|
||||
<button
|
||||
onClick={() => setEditingReading({ meterId: meter.id, reading })}
|
||||
onClick={() => setEditingReading({ meterId: meter.id, meterType: meter.type, reading })}
|
||||
className="text-gray-400 hover:text-blue-600"
|
||||
title="Bearbeiten"
|
||||
>
|
||||
@@ -1467,7 +1467,8 @@ function MetersTab({
|
||||
<MeterReadingModal
|
||||
isOpen={true}
|
||||
onClose={() => setShowReadingModal(null)}
|
||||
meterId={showReadingModal}
|
||||
meterId={showReadingModal.meterId}
|
||||
meterType={showReadingModal.meterType}
|
||||
customerId={customerId}
|
||||
/>
|
||||
)}
|
||||
@@ -1477,6 +1478,7 @@ function MetersTab({
|
||||
isOpen={true}
|
||||
onClose={() => setEditingReading(null)}
|
||||
meterId={editingReading.meterId}
|
||||
meterType={editingReading.meterType}
|
||||
customerId={customerId}
|
||||
reading={editingReading.reading}
|
||||
/>
|
||||
@@ -2601,24 +2603,26 @@ function MeterReadingModal({
|
||||
isOpen,
|
||||
onClose,
|
||||
meterId,
|
||||
meterType,
|
||||
customerId,
|
||||
reading,
|
||||
}: {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
meterId: number;
|
||||
meterType: 'ELECTRICITY' | 'GAS';
|
||||
customerId: number;
|
||||
reading?: { id: number; readingDate: string; value: number; unit: string; notes?: string } | null;
|
||||
}) {
|
||||
const queryClient = useQueryClient();
|
||||
const isEditing = !!reading;
|
||||
const defaultUnit = meterType === 'ELECTRICITY' ? 'kWh' : 'm³';
|
||||
|
||||
const getInitialFormData = () => ({
|
||||
readingDate: reading?.readingDate
|
||||
? new Date(reading.readingDate).toISOString().split('T')[0]
|
||||
: new Date().toISOString().split('T')[0],
|
||||
value: reading?.value?.toString() || '',
|
||||
unit: reading?.unit || 'kWh',
|
||||
notes: reading?.notes || '',
|
||||
});
|
||||
|
||||
@@ -2645,7 +2649,7 @@ function MeterReadingModal({
|
||||
const data = {
|
||||
readingDate: new Date(formData.readingDate),
|
||||
value: parseFloat(formData.value),
|
||||
unit: formData.unit,
|
||||
unit: defaultUnit,
|
||||
notes: formData.notes || undefined,
|
||||
};
|
||||
if (isEditing) {
|
||||
@@ -2684,15 +2688,12 @@ function MeterReadingModal({
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<Select
|
||||
label="Einheit"
|
||||
value={formData.unit}
|
||||
onChange={(e) => setFormData({ ...formData, unit: e.target.value })}
|
||||
options={[
|
||||
{ value: 'kWh', label: 'kWh' },
|
||||
{ value: 'm³', label: 'm³' },
|
||||
]}
|
||||
/>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Einheit</label>
|
||||
<div className="h-10 flex items-center px-3 bg-gray-100 border border-gray-300 rounded-md text-gray-700">
|
||||
{defaultUnit}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Input
|
||||
|
||||
@@ -336,9 +336,11 @@ export interface EnergyContractDetails {
|
||||
contractId: number;
|
||||
meterId?: number;
|
||||
meter?: Meter;
|
||||
annualConsumption?: number;
|
||||
basePrice?: number;
|
||||
unitPrice?: number;
|
||||
maloId?: string; // Marktlokations-ID
|
||||
annualConsumption?: number; // kWh für Strom, m³ für Gas
|
||||
annualConsumptionKwh?: number; // kWh für Gas (zusätzlich zu m³)
|
||||
basePrice?: number; // €/Monat
|
||||
unitPrice?: number; // €/kWh (Arbeitspreis)
|
||||
bonus?: number;
|
||||
previousProviderName?: string;
|
||||
previousCustomerNumber?: string;
|
||||
|
||||
Reference in New Issue
Block a user