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:
duffyduck 2026-02-05 20:34:45 +01:00
parent af2f444a24
commit b281801cdb
22 changed files with 329 additions and 165 deletions

View File

@ -246,7 +246,9 @@ export declare function getContractById(id: number, decryptPassword?: boolean):
id: number; id: number;
meterId: number | null; meterId: number | null;
contractId: number; contractId: number;
maloId: string | null;
annualConsumption: number | null; annualConsumption: number | null;
annualConsumptionKwh: number | null;
basePrice: number | null; basePrice: number | null;
unitPrice: number | null; unitPrice: number | null;
bonus: number | null; bonus: number | null;
@ -423,7 +425,9 @@ export declare function getContractById(id: number, decryptPassword?: boolean):
id: number; id: number;
meterId: number | null; meterId: number | null;
contractId: number; contractId: number;
maloId: string | null;
annualConsumption: number | null; annualConsumption: number | null;
annualConsumptionKwh: number | null;
basePrice: number | null; basePrice: number | null;
unitPrice: number | null; unitPrice: number | null;
bonus: number | null; bonus: number | null;
@ -738,7 +742,9 @@ export declare function createContract(data: ContractCreateData): Promise<{
id: number; id: number;
meterId: number | null; meterId: number | null;
contractId: number; contractId: number;
maloId: string | null;
annualConsumption: number | null; annualConsumption: number | null;
annualConsumptionKwh: number | null;
basePrice: number | null; basePrice: number | null;
unitPrice: number | null; unitPrice: number | null;
bonus: number | null; bonus: number | null;
@ -972,7 +978,9 @@ export declare function updateContract(id: number, data: Partial<ContractCreateD
id: number; id: number;
meterId: number | null; meterId: number | null;
contractId: number; contractId: number;
maloId: string | null;
annualConsumption: number | null; annualConsumption: number | null;
annualConsumptionKwh: number | null;
basePrice: number | null; basePrice: number | null;
unitPrice: number | null; unitPrice: number | null;
bonus: number | null; bonus: number | null;
@ -1149,7 +1157,9 @@ export declare function updateContract(id: number, data: Partial<ContractCreateD
id: number; id: number;
meterId: number | null; meterId: number | null;
contractId: number; contractId: number;
maloId: string | null;
annualConsumption: number | null; annualConsumption: number | null;
annualConsumptionKwh: number | null;
basePrice: number | null; basePrice: number | null;
unitPrice: number | null; unitPrice: number | null;
bonus: number | null; bonus: number | null;
@ -1406,7 +1416,9 @@ export declare function createFollowUpContract(previousContractId: number): Prom
id: number; id: number;
meterId: number | null; meterId: number | null;
contractId: number; contractId: number;
maloId: string | null;
annualConsumption: number | null; annualConsumption: number | null;
annualConsumptionKwh: number | null;
basePrice: number | null; basePrice: number | null;
unitPrice: number | null; unitPrice: number | null;
bonus: number | null; bonus: number | null;

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
{"version":3,"file":"contractCockpit.service.d.ts","sourceRoot":"","sources":["../../src/services/contractCockpit.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,cAAc,EACpC,MAAM,gBAAgB,CAAC;AAMxB,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,CAAC;AAElE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,YAAY,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE;QACR,EAAE,EAAE,MAAM,CAAC;QACX,cAAc,EAAE,MAAM,CAAC;QACvB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,QAAQ,CAAC,EAAE;QACT,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,MAAM,CAAC,EAAE;QACP,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,cAAc,EAAE,YAAY,CAAC;CAC9B;AAED,MAAM,WAAW,cAAc;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE;QACV,qBAAqB,EAAE,MAAM,CAAC;QAC9B,cAAc,EAAE,MAAM,CAAC;QACvB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,gBAAgB,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,OAAO,EAAE,cAAc,CAAC;IACxB,UAAU,EAAE;QACV,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAyED,wBAAsB,cAAc,IAAI,OAAO,CAAC,aAAa,CAAC,CAiV7D"} {"version":3,"file":"contractCockpit.service.d.ts","sourceRoot":"","sources":["../../src/services/contractCockpit.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,cAAc,EACpC,MAAM,gBAAgB,CAAC;AAMxB,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,CAAC;AAElE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,YAAY,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE;QACR,EAAE,EAAE,MAAM,CAAC;QACX,cAAc,EAAE,MAAM,CAAC;QACvB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,QAAQ,CAAC,EAAE;QACT,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,MAAM,CAAC,EAAE;QACP,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,cAAc,EAAE,YAAY,CAAC;CAC9B;AAED,MAAM,WAAW,cAAc;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE;QACV,qBAAqB,EAAE,MAAM,CAAC;QAC9B,cAAc,EAAE,MAAM,CAAC;QACvB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,gBAAgB,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,OAAO,EAAE,cAAc,CAAC;IACxB,UAAU,EAAE;QACV,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAyED,wBAAsB,cAAc,IAAI,OAAO,CAAC,aAAa,CAAC,CA8V7D"}

View File

@ -292,15 +292,27 @@ async function getCockpitData() {
summary.byCategory.missingData++; summary.byCategory.missingData++;
} }
// 7. KEINE BANKVERBINDUNG // 7. KEINE BANKVERBINDUNG
// Für DSL, FIBER, CABLE, MOBILE ist dies ein kritisches Problem
const requiresBankAndId = ['DSL', 'FIBER', 'CABLE', 'MOBILE'].includes(contract.type);
if (!contract.bankCardId) { if (!contract.bankCardId) {
issues.push({ issues.push({
type: 'missing_bank', type: 'missing_bank',
label: 'Bankverbindung fehlt', label: 'Bankverbindung fehlt',
urgency: 'warning', urgency: requiresBankAndId ? 'critical' : 'warning',
details: 'Keine Bankverbindung verknüpft', details: 'Keine Bankverbindung verknüpft',
}); });
summary.byCategory.missingData++; summary.byCategory.missingData++;
} }
// 7b. KEIN AUSWEIS (für DSL, FIBER, CABLE, MOBILE ist dies ein kritisches Problem)
if (!contract.identityDocumentId) {
issues.push({
type: 'missing_identity_document',
label: 'Ausweis fehlt',
urgency: requiresBankAndId ? 'critical' : 'warning',
details: 'Kein Ausweisdokument verknüpft',
});
summary.byCategory.missingData++;
}
// 8. ENERGIE-SPEZIFISCH: KEIN ZÄHLER // 8. ENERGIE-SPEZIFISCH: KEIN ZÄHLER
if (['ELECTRICITY', 'GAS'].includes(contract.type) && contract.energyDetails) { if (['ELECTRICITY', 'GAS'].includes(contract.type) && contract.energyDetails) {
if (!contract.energyDetails.meterId) { if (!contract.energyDetails.meterId) {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -466,7 +466,9 @@ exports.Prisma.EnergyContractDetailsScalarFieldEnum = {
id: 'id', id: 'id',
contractId: 'contractId', contractId: 'contractId',
meterId: 'meterId', meterId: 'meterId',
maloId: 'maloId',
annualConsumption: 'annualConsumption', annualConsumption: 'annualConsumption',
annualConsumptionKwh: 'annualConsumptionKwh',
basePrice: 'basePrice', basePrice: 'basePrice',
unitPrice: 'unitPrice', unitPrice: 'unitPrice',
bonus: 'bonus', bonus: 'bonus',

View File

@ -29799,6 +29799,7 @@ export namespace Prisma {
contractId: number | null contractId: number | null
meterId: number | null meterId: number | null
annualConsumption: number | null annualConsumption: number | null
annualConsumptionKwh: number | null
basePrice: number | null basePrice: number | null
unitPrice: number | null unitPrice: number | null
bonus: number | null bonus: number | null
@ -29809,6 +29810,7 @@ export namespace Prisma {
contractId: number | null contractId: number | null
meterId: number | null meterId: number | null
annualConsumption: number | null annualConsumption: number | null
annualConsumptionKwh: number | null
basePrice: number | null basePrice: number | null
unitPrice: number | null unitPrice: number | null
bonus: number | null bonus: number | null
@ -29818,7 +29820,9 @@ export namespace Prisma {
id: number | null id: number | null
contractId: number | null contractId: number | null
meterId: number | null meterId: number | null
maloId: string | null
annualConsumption: number | null annualConsumption: number | null
annualConsumptionKwh: number | null
basePrice: number | null basePrice: number | null
unitPrice: number | null unitPrice: number | null
bonus: number | null bonus: number | null
@ -29830,7 +29834,9 @@ export namespace Prisma {
id: number | null id: number | null
contractId: number | null contractId: number | null
meterId: number | null meterId: number | null
maloId: string | null
annualConsumption: number | null annualConsumption: number | null
annualConsumptionKwh: number | null
basePrice: number | null basePrice: number | null
unitPrice: number | null unitPrice: number | null
bonus: number | null bonus: number | null
@ -29842,7 +29848,9 @@ export namespace Prisma {
id: number id: number
contractId: number contractId: number
meterId: number meterId: number
maloId: number
annualConsumption: number annualConsumption: number
annualConsumptionKwh: number
basePrice: number basePrice: number
unitPrice: number unitPrice: number
bonus: number bonus: number
@ -29857,6 +29865,7 @@ export namespace Prisma {
contractId?: true contractId?: true
meterId?: true meterId?: true
annualConsumption?: true annualConsumption?: true
annualConsumptionKwh?: true
basePrice?: true basePrice?: true
unitPrice?: true unitPrice?: true
bonus?: true bonus?: true
@ -29867,6 +29876,7 @@ export namespace Prisma {
contractId?: true contractId?: true
meterId?: true meterId?: true
annualConsumption?: true annualConsumption?: true
annualConsumptionKwh?: true
basePrice?: true basePrice?: true
unitPrice?: true unitPrice?: true
bonus?: true bonus?: true
@ -29876,7 +29886,9 @@ export namespace Prisma {
id?: true id?: true
contractId?: true contractId?: true
meterId?: true meterId?: true
maloId?: true
annualConsumption?: true annualConsumption?: true
annualConsumptionKwh?: true
basePrice?: true basePrice?: true
unitPrice?: true unitPrice?: true
bonus?: true bonus?: true
@ -29888,7 +29900,9 @@ export namespace Prisma {
id?: true id?: true
contractId?: true contractId?: true
meterId?: true meterId?: true
maloId?: true
annualConsumption?: true annualConsumption?: true
annualConsumptionKwh?: true
basePrice?: true basePrice?: true
unitPrice?: true unitPrice?: true
bonus?: true bonus?: true
@ -29900,7 +29914,9 @@ export namespace Prisma {
id?: true id?: true
contractId?: true contractId?: true
meterId?: true meterId?: true
maloId?: true
annualConsumption?: true annualConsumption?: true
annualConsumptionKwh?: true
basePrice?: true basePrice?: true
unitPrice?: true unitPrice?: true
bonus?: true bonus?: true
@ -29999,7 +30015,9 @@ export namespace Prisma {
id: number id: number
contractId: number contractId: number
meterId: number | null meterId: number | null
maloId: string | null
annualConsumption: number | null annualConsumption: number | null
annualConsumptionKwh: number | null
basePrice: number | null basePrice: number | null
unitPrice: number | null unitPrice: number | null
bonus: number | null bonus: number | null
@ -30030,7 +30048,9 @@ export namespace Prisma {
id?: boolean id?: boolean
contractId?: boolean contractId?: boolean
meterId?: boolean meterId?: boolean
maloId?: boolean
annualConsumption?: boolean annualConsumption?: boolean
annualConsumptionKwh?: boolean
basePrice?: boolean basePrice?: boolean
unitPrice?: boolean unitPrice?: boolean
bonus?: boolean bonus?: boolean
@ -30045,7 +30065,9 @@ export namespace Prisma {
id?: boolean id?: boolean
contractId?: boolean contractId?: boolean
meterId?: boolean meterId?: boolean
maloId?: boolean
annualConsumption?: boolean annualConsumption?: boolean
annualConsumptionKwh?: boolean
basePrice?: boolean basePrice?: boolean
unitPrice?: boolean unitPrice?: boolean
bonus?: boolean bonus?: boolean
@ -30068,7 +30090,9 @@ export namespace Prisma {
id: number id: number
contractId: number contractId: number
meterId: number | null meterId: number | null
maloId: string | null
annualConsumption: number | null annualConsumption: number | null
annualConsumptionKwh: number | null
basePrice: number | null basePrice: number | null
unitPrice: number | null unitPrice: number | null
bonus: number | null bonus: number | null
@ -30448,7 +30472,9 @@ export namespace Prisma {
readonly id: FieldRef<"EnergyContractDetails", 'Int'> readonly id: FieldRef<"EnergyContractDetails", 'Int'>
readonly contractId: FieldRef<"EnergyContractDetails", 'Int'> readonly contractId: FieldRef<"EnergyContractDetails", 'Int'>
readonly meterId: FieldRef<"EnergyContractDetails", 'Int'> readonly meterId: FieldRef<"EnergyContractDetails", 'Int'>
readonly maloId: FieldRef<"EnergyContractDetails", 'String'>
readonly annualConsumption: FieldRef<"EnergyContractDetails", 'Float'> readonly annualConsumption: FieldRef<"EnergyContractDetails", 'Float'>
readonly annualConsumptionKwh: FieldRef<"EnergyContractDetails", 'Float'>
readonly basePrice: FieldRef<"EnergyContractDetails", 'Float'> readonly basePrice: FieldRef<"EnergyContractDetails", 'Float'>
readonly unitPrice: FieldRef<"EnergyContractDetails", 'Float'> readonly unitPrice: FieldRef<"EnergyContractDetails", 'Float'>
readonly bonus: FieldRef<"EnergyContractDetails", 'Float'> readonly bonus: FieldRef<"EnergyContractDetails", 'Float'>
@ -37094,7 +37120,9 @@ export namespace Prisma {
id: 'id', id: 'id',
contractId: 'contractId', contractId: 'contractId',
meterId: 'meterId', meterId: 'meterId',
maloId: 'maloId',
annualConsumption: 'annualConsumption', annualConsumption: 'annualConsumption',
annualConsumptionKwh: 'annualConsumptionKwh',
basePrice: 'basePrice', basePrice: 'basePrice',
unitPrice: 'unitPrice', unitPrice: 'unitPrice',
bonus: 'bonus', bonus: 'bonus',
@ -39601,7 +39629,9 @@ export namespace Prisma {
id?: IntFilter<"EnergyContractDetails"> | number id?: IntFilter<"EnergyContractDetails"> | number
contractId?: IntFilter<"EnergyContractDetails"> | number contractId?: IntFilter<"EnergyContractDetails"> | number
meterId?: IntNullableFilter<"EnergyContractDetails"> | number | null meterId?: IntNullableFilter<"EnergyContractDetails"> | number | null
maloId?: StringNullableFilter<"EnergyContractDetails"> | string | null
annualConsumption?: FloatNullableFilter<"EnergyContractDetails"> | number | null annualConsumption?: FloatNullableFilter<"EnergyContractDetails"> | number | null
annualConsumptionKwh?: FloatNullableFilter<"EnergyContractDetails"> | number | null
basePrice?: FloatNullableFilter<"EnergyContractDetails"> | number | null basePrice?: FloatNullableFilter<"EnergyContractDetails"> | number | null
unitPrice?: FloatNullableFilter<"EnergyContractDetails"> | number | null unitPrice?: FloatNullableFilter<"EnergyContractDetails"> | number | null
bonus?: FloatNullableFilter<"EnergyContractDetails"> | number | null bonus?: FloatNullableFilter<"EnergyContractDetails"> | number | null
@ -39615,7 +39645,9 @@ export namespace Prisma {
id?: SortOrder id?: SortOrder
contractId?: SortOrder contractId?: SortOrder
meterId?: SortOrderInput | SortOrder meterId?: SortOrderInput | SortOrder
maloId?: SortOrderInput | SortOrder
annualConsumption?: SortOrderInput | SortOrder annualConsumption?: SortOrderInput | SortOrder
annualConsumptionKwh?: SortOrderInput | SortOrder
basePrice?: SortOrderInput | SortOrder basePrice?: SortOrderInput | SortOrder
unitPrice?: SortOrderInput | SortOrder unitPrice?: SortOrderInput | SortOrder
bonus?: SortOrderInput | SortOrder bonus?: SortOrderInput | SortOrder
@ -39632,7 +39664,9 @@ export namespace Prisma {
OR?: EnergyContractDetailsWhereInput[] OR?: EnergyContractDetailsWhereInput[]
NOT?: EnergyContractDetailsWhereInput | EnergyContractDetailsWhereInput[] NOT?: EnergyContractDetailsWhereInput | EnergyContractDetailsWhereInput[]
meterId?: IntNullableFilter<"EnergyContractDetails"> | number | null meterId?: IntNullableFilter<"EnergyContractDetails"> | number | null
maloId?: StringNullableFilter<"EnergyContractDetails"> | string | null
annualConsumption?: FloatNullableFilter<"EnergyContractDetails"> | number | null annualConsumption?: FloatNullableFilter<"EnergyContractDetails"> | number | null
annualConsumptionKwh?: FloatNullableFilter<"EnergyContractDetails"> | number | null
basePrice?: FloatNullableFilter<"EnergyContractDetails"> | number | null basePrice?: FloatNullableFilter<"EnergyContractDetails"> | number | null
unitPrice?: FloatNullableFilter<"EnergyContractDetails"> | number | null unitPrice?: FloatNullableFilter<"EnergyContractDetails"> | number | null
bonus?: FloatNullableFilter<"EnergyContractDetails"> | number | null bonus?: FloatNullableFilter<"EnergyContractDetails"> | number | null
@ -39646,7 +39680,9 @@ export namespace Prisma {
id?: SortOrder id?: SortOrder
contractId?: SortOrder contractId?: SortOrder
meterId?: SortOrderInput | SortOrder meterId?: SortOrderInput | SortOrder
maloId?: SortOrderInput | SortOrder
annualConsumption?: SortOrderInput | SortOrder annualConsumption?: SortOrderInput | SortOrder
annualConsumptionKwh?: SortOrderInput | SortOrder
basePrice?: SortOrderInput | SortOrder basePrice?: SortOrderInput | SortOrder
unitPrice?: SortOrderInput | SortOrder unitPrice?: SortOrderInput | SortOrder
bonus?: SortOrderInput | SortOrder bonus?: SortOrderInput | SortOrder
@ -39666,7 +39702,9 @@ export namespace Prisma {
id?: IntWithAggregatesFilter<"EnergyContractDetails"> | number id?: IntWithAggregatesFilter<"EnergyContractDetails"> | number
contractId?: IntWithAggregatesFilter<"EnergyContractDetails"> | number contractId?: IntWithAggregatesFilter<"EnergyContractDetails"> | number
meterId?: IntNullableWithAggregatesFilter<"EnergyContractDetails"> | number | null meterId?: IntNullableWithAggregatesFilter<"EnergyContractDetails"> | number | null
maloId?: StringNullableWithAggregatesFilter<"EnergyContractDetails"> | string | null
annualConsumption?: FloatNullableWithAggregatesFilter<"EnergyContractDetails"> | number | null annualConsumption?: FloatNullableWithAggregatesFilter<"EnergyContractDetails"> | number | null
annualConsumptionKwh?: FloatNullableWithAggregatesFilter<"EnergyContractDetails"> | number | null
basePrice?: FloatNullableWithAggregatesFilter<"EnergyContractDetails"> | number | null basePrice?: FloatNullableWithAggregatesFilter<"EnergyContractDetails"> | number | null
unitPrice?: FloatNullableWithAggregatesFilter<"EnergyContractDetails"> | number | null unitPrice?: FloatNullableWithAggregatesFilter<"EnergyContractDetails"> | number | null
bonus?: FloatNullableWithAggregatesFilter<"EnergyContractDetails"> | number | null bonus?: FloatNullableWithAggregatesFilter<"EnergyContractDetails"> | number | null
@ -42588,7 +42626,9 @@ export namespace Prisma {
} }
export type EnergyContractDetailsCreateInput = { export type EnergyContractDetailsCreateInput = {
maloId?: string | null
annualConsumption?: number | null annualConsumption?: number | null
annualConsumptionKwh?: number | null
basePrice?: number | null basePrice?: number | null
unitPrice?: number | null unitPrice?: number | null
bonus?: number | null bonus?: number | null
@ -42602,7 +42642,9 @@ export namespace Prisma {
id?: number id?: number
contractId: number contractId: number
meterId?: number | null meterId?: number | null
maloId?: string | null
annualConsumption?: number | null annualConsumption?: number | null
annualConsumptionKwh?: number | null
basePrice?: number | null basePrice?: number | null
unitPrice?: number | null unitPrice?: number | null
bonus?: number | null bonus?: number | null
@ -42611,7 +42653,9 @@ export namespace Prisma {
} }
export type EnergyContractDetailsUpdateInput = { export type EnergyContractDetailsUpdateInput = {
maloId?: NullableStringFieldUpdateOperationsInput | string | null
annualConsumption?: NullableFloatFieldUpdateOperationsInput | number | null annualConsumption?: NullableFloatFieldUpdateOperationsInput | number | null
annualConsumptionKwh?: NullableFloatFieldUpdateOperationsInput | number | null
basePrice?: NullableFloatFieldUpdateOperationsInput | number | null basePrice?: NullableFloatFieldUpdateOperationsInput | number | null
unitPrice?: NullableFloatFieldUpdateOperationsInput | number | null unitPrice?: NullableFloatFieldUpdateOperationsInput | number | null
bonus?: NullableFloatFieldUpdateOperationsInput | number | null bonus?: NullableFloatFieldUpdateOperationsInput | number | null
@ -42625,7 +42669,9 @@ export namespace Prisma {
id?: IntFieldUpdateOperationsInput | number id?: IntFieldUpdateOperationsInput | number
contractId?: IntFieldUpdateOperationsInput | number contractId?: IntFieldUpdateOperationsInput | number
meterId?: NullableIntFieldUpdateOperationsInput | number | null meterId?: NullableIntFieldUpdateOperationsInput | number | null
maloId?: NullableStringFieldUpdateOperationsInput | string | null
annualConsumption?: NullableFloatFieldUpdateOperationsInput | number | null annualConsumption?: NullableFloatFieldUpdateOperationsInput | number | null
annualConsumptionKwh?: NullableFloatFieldUpdateOperationsInput | number | null
basePrice?: NullableFloatFieldUpdateOperationsInput | number | null basePrice?: NullableFloatFieldUpdateOperationsInput | number | null
unitPrice?: NullableFloatFieldUpdateOperationsInput | number | null unitPrice?: NullableFloatFieldUpdateOperationsInput | number | null
bonus?: NullableFloatFieldUpdateOperationsInput | number | null bonus?: NullableFloatFieldUpdateOperationsInput | number | null
@ -42637,7 +42683,9 @@ export namespace Prisma {
id?: number id?: number
contractId: number contractId: number
meterId?: number | null meterId?: number | null
maloId?: string | null
annualConsumption?: number | null annualConsumption?: number | null
annualConsumptionKwh?: number | null
basePrice?: number | null basePrice?: number | null
unitPrice?: number | null unitPrice?: number | null
bonus?: number | null bonus?: number | null
@ -42646,7 +42694,9 @@ export namespace Prisma {
} }
export type EnergyContractDetailsUpdateManyMutationInput = { export type EnergyContractDetailsUpdateManyMutationInput = {
maloId?: NullableStringFieldUpdateOperationsInput | string | null
annualConsumption?: NullableFloatFieldUpdateOperationsInput | number | null annualConsumption?: NullableFloatFieldUpdateOperationsInput | number | null
annualConsumptionKwh?: NullableFloatFieldUpdateOperationsInput | number | null
basePrice?: NullableFloatFieldUpdateOperationsInput | number | null basePrice?: NullableFloatFieldUpdateOperationsInput | number | null
unitPrice?: NullableFloatFieldUpdateOperationsInput | number | null unitPrice?: NullableFloatFieldUpdateOperationsInput | number | null
bonus?: NullableFloatFieldUpdateOperationsInput | number | null bonus?: NullableFloatFieldUpdateOperationsInput | number | null
@ -42658,7 +42708,9 @@ export namespace Prisma {
id?: IntFieldUpdateOperationsInput | number id?: IntFieldUpdateOperationsInput | number
contractId?: IntFieldUpdateOperationsInput | number contractId?: IntFieldUpdateOperationsInput | number
meterId?: NullableIntFieldUpdateOperationsInput | number | null meterId?: NullableIntFieldUpdateOperationsInput | number | null
maloId?: NullableStringFieldUpdateOperationsInput | string | null
annualConsumption?: NullableFloatFieldUpdateOperationsInput | number | null annualConsumption?: NullableFloatFieldUpdateOperationsInput | number | null
annualConsumptionKwh?: NullableFloatFieldUpdateOperationsInput | number | null
basePrice?: NullableFloatFieldUpdateOperationsInput | number | null basePrice?: NullableFloatFieldUpdateOperationsInput | number | null
unitPrice?: NullableFloatFieldUpdateOperationsInput | number | null unitPrice?: NullableFloatFieldUpdateOperationsInput | number | null
bonus?: NullableFloatFieldUpdateOperationsInput | number | null bonus?: NullableFloatFieldUpdateOperationsInput | number | null
@ -45200,7 +45252,9 @@ export namespace Prisma {
id?: SortOrder id?: SortOrder
contractId?: SortOrder contractId?: SortOrder
meterId?: SortOrder meterId?: SortOrder
maloId?: SortOrder
annualConsumption?: SortOrder annualConsumption?: SortOrder
annualConsumptionKwh?: SortOrder
basePrice?: SortOrder basePrice?: SortOrder
unitPrice?: SortOrder unitPrice?: SortOrder
bonus?: SortOrder bonus?: SortOrder
@ -45213,6 +45267,7 @@ export namespace Prisma {
contractId?: SortOrder contractId?: SortOrder
meterId?: SortOrder meterId?: SortOrder
annualConsumption?: SortOrder annualConsumption?: SortOrder
annualConsumptionKwh?: SortOrder
basePrice?: SortOrder basePrice?: SortOrder
unitPrice?: SortOrder unitPrice?: SortOrder
bonus?: SortOrder bonus?: SortOrder
@ -45222,7 +45277,9 @@ export namespace Prisma {
id?: SortOrder id?: SortOrder
contractId?: SortOrder contractId?: SortOrder
meterId?: SortOrder meterId?: SortOrder
maloId?: SortOrder
annualConsumption?: SortOrder annualConsumption?: SortOrder
annualConsumptionKwh?: SortOrder
basePrice?: SortOrder basePrice?: SortOrder
unitPrice?: SortOrder unitPrice?: SortOrder
bonus?: SortOrder bonus?: SortOrder
@ -45234,7 +45291,9 @@ export namespace Prisma {
id?: SortOrder id?: SortOrder
contractId?: SortOrder contractId?: SortOrder
meterId?: SortOrder meterId?: SortOrder
maloId?: SortOrder
annualConsumption?: SortOrder annualConsumption?: SortOrder
annualConsumptionKwh?: SortOrder
basePrice?: SortOrder basePrice?: SortOrder
unitPrice?: SortOrder unitPrice?: SortOrder
bonus?: SortOrder bonus?: SortOrder
@ -45247,6 +45306,7 @@ export namespace Prisma {
contractId?: SortOrder contractId?: SortOrder
meterId?: SortOrder meterId?: SortOrder
annualConsumption?: SortOrder annualConsumption?: SortOrder
annualConsumptionKwh?: SortOrder
basePrice?: SortOrder basePrice?: SortOrder
unitPrice?: SortOrder unitPrice?: SortOrder
bonus?: SortOrder bonus?: SortOrder
@ -51546,7 +51606,9 @@ export namespace Prisma {
} }
export type EnergyContractDetailsCreateWithoutMeterInput = { export type EnergyContractDetailsCreateWithoutMeterInput = {
maloId?: string | null
annualConsumption?: number | null annualConsumption?: number | null
annualConsumptionKwh?: number | null
basePrice?: number | null basePrice?: number | null
unitPrice?: number | null unitPrice?: number | null
bonus?: number | null bonus?: number | null
@ -51558,7 +51620,9 @@ export namespace Prisma {
export type EnergyContractDetailsUncheckedCreateWithoutMeterInput = { export type EnergyContractDetailsUncheckedCreateWithoutMeterInput = {
id?: number id?: number
contractId: number contractId: number
maloId?: string | null
annualConsumption?: number | null annualConsumption?: number | null
annualConsumptionKwh?: number | null
basePrice?: number | null basePrice?: number | null
unitPrice?: number | null unitPrice?: number | null
bonus?: number | null bonus?: number | null
@ -51712,7 +51776,9 @@ export namespace Prisma {
id?: IntFilter<"EnergyContractDetails"> | number id?: IntFilter<"EnergyContractDetails"> | number
contractId?: IntFilter<"EnergyContractDetails"> | number contractId?: IntFilter<"EnergyContractDetails"> | number
meterId?: IntNullableFilter<"EnergyContractDetails"> | number | null meterId?: IntNullableFilter<"EnergyContractDetails"> | number | null
maloId?: StringNullableFilter<"EnergyContractDetails"> | string | null
annualConsumption?: FloatNullableFilter<"EnergyContractDetails"> | number | null annualConsumption?: FloatNullableFilter<"EnergyContractDetails"> | number | null
annualConsumptionKwh?: FloatNullableFilter<"EnergyContractDetails"> | number | null
basePrice?: FloatNullableFilter<"EnergyContractDetails"> | number | null basePrice?: FloatNullableFilter<"EnergyContractDetails"> | number | null
unitPrice?: FloatNullableFilter<"EnergyContractDetails"> | number | null unitPrice?: FloatNullableFilter<"EnergyContractDetails"> | number | null
bonus?: FloatNullableFilter<"EnergyContractDetails"> | number | null bonus?: FloatNullableFilter<"EnergyContractDetails"> | number | null
@ -53222,7 +53288,9 @@ export namespace Prisma {
} }
export type EnergyContractDetailsCreateWithoutContractInput = { export type EnergyContractDetailsCreateWithoutContractInput = {
maloId?: string | null
annualConsumption?: number | null annualConsumption?: number | null
annualConsumptionKwh?: number | null
basePrice?: number | null basePrice?: number | null
unitPrice?: number | null unitPrice?: number | null
bonus?: number | null bonus?: number | null
@ -53234,7 +53302,9 @@ export namespace Prisma {
export type EnergyContractDetailsUncheckedCreateWithoutContractInput = { export type EnergyContractDetailsUncheckedCreateWithoutContractInput = {
id?: number id?: number
meterId?: number | null meterId?: number | null
maloId?: string | null
annualConsumption?: number | null annualConsumption?: number | null
annualConsumptionKwh?: number | null
basePrice?: number | null basePrice?: number | null
unitPrice?: number | null unitPrice?: number | null
bonus?: number | null bonus?: number | null
@ -54153,7 +54223,9 @@ export namespace Prisma {
} }
export type EnergyContractDetailsUpdateWithoutContractInput = { export type EnergyContractDetailsUpdateWithoutContractInput = {
maloId?: NullableStringFieldUpdateOperationsInput | string | null
annualConsumption?: NullableFloatFieldUpdateOperationsInput | number | null annualConsumption?: NullableFloatFieldUpdateOperationsInput | number | null
annualConsumptionKwh?: NullableFloatFieldUpdateOperationsInput | number | null
basePrice?: NullableFloatFieldUpdateOperationsInput | number | null basePrice?: NullableFloatFieldUpdateOperationsInput | number | null
unitPrice?: NullableFloatFieldUpdateOperationsInput | number | null unitPrice?: NullableFloatFieldUpdateOperationsInput | number | null
bonus?: NullableFloatFieldUpdateOperationsInput | number | null bonus?: NullableFloatFieldUpdateOperationsInput | number | null
@ -54165,7 +54237,9 @@ export namespace Prisma {
export type EnergyContractDetailsUncheckedUpdateWithoutContractInput = { export type EnergyContractDetailsUncheckedUpdateWithoutContractInput = {
id?: IntFieldUpdateOperationsInput | number id?: IntFieldUpdateOperationsInput | number
meterId?: NullableIntFieldUpdateOperationsInput | number | null meterId?: NullableIntFieldUpdateOperationsInput | number | null
maloId?: NullableStringFieldUpdateOperationsInput | string | null
annualConsumption?: NullableFloatFieldUpdateOperationsInput | number | null annualConsumption?: NullableFloatFieldUpdateOperationsInput | number | null
annualConsumptionKwh?: NullableFloatFieldUpdateOperationsInput | number | null
basePrice?: NullableFloatFieldUpdateOperationsInput | number | null basePrice?: NullableFloatFieldUpdateOperationsInput | number | null
unitPrice?: NullableFloatFieldUpdateOperationsInput | number | null unitPrice?: NullableFloatFieldUpdateOperationsInput | number | null
bonus?: NullableFloatFieldUpdateOperationsInput | number | null bonus?: NullableFloatFieldUpdateOperationsInput | number | null
@ -57619,7 +57693,9 @@ export namespace Prisma {
export type EnergyContractDetailsCreateManyMeterInput = { export type EnergyContractDetailsCreateManyMeterInput = {
id?: number id?: number
contractId: number contractId: number
maloId?: string | null
annualConsumption?: number | null annualConsumption?: number | null
annualConsumptionKwh?: number | null
basePrice?: number | null basePrice?: number | null
unitPrice?: number | null unitPrice?: number | null
bonus?: number | null bonus?: number | null
@ -57654,7 +57730,9 @@ export namespace Prisma {
} }
export type EnergyContractDetailsUpdateWithoutMeterInput = { export type EnergyContractDetailsUpdateWithoutMeterInput = {
maloId?: NullableStringFieldUpdateOperationsInput | string | null
annualConsumption?: NullableFloatFieldUpdateOperationsInput | number | null annualConsumption?: NullableFloatFieldUpdateOperationsInput | number | null
annualConsumptionKwh?: NullableFloatFieldUpdateOperationsInput | number | null
basePrice?: NullableFloatFieldUpdateOperationsInput | number | null basePrice?: NullableFloatFieldUpdateOperationsInput | number | null
unitPrice?: NullableFloatFieldUpdateOperationsInput | number | null unitPrice?: NullableFloatFieldUpdateOperationsInput | number | null
bonus?: NullableFloatFieldUpdateOperationsInput | number | null bonus?: NullableFloatFieldUpdateOperationsInput | number | null
@ -57666,7 +57744,9 @@ export namespace Prisma {
export type EnergyContractDetailsUncheckedUpdateWithoutMeterInput = { export type EnergyContractDetailsUncheckedUpdateWithoutMeterInput = {
id?: IntFieldUpdateOperationsInput | number id?: IntFieldUpdateOperationsInput | number
contractId?: IntFieldUpdateOperationsInput | number contractId?: IntFieldUpdateOperationsInput | number
maloId?: NullableStringFieldUpdateOperationsInput | string | null
annualConsumption?: NullableFloatFieldUpdateOperationsInput | number | null annualConsumption?: NullableFloatFieldUpdateOperationsInput | number | null
annualConsumptionKwh?: NullableFloatFieldUpdateOperationsInput | number | null
basePrice?: NullableFloatFieldUpdateOperationsInput | number | null basePrice?: NullableFloatFieldUpdateOperationsInput | number | null
unitPrice?: NullableFloatFieldUpdateOperationsInput | number | null unitPrice?: NullableFloatFieldUpdateOperationsInput | number | null
bonus?: NullableFloatFieldUpdateOperationsInput | number | null bonus?: NullableFloatFieldUpdateOperationsInput | number | null
@ -57677,7 +57757,9 @@ export namespace Prisma {
export type EnergyContractDetailsUncheckedUpdateManyWithoutMeterInput = { export type EnergyContractDetailsUncheckedUpdateManyWithoutMeterInput = {
id?: IntFieldUpdateOperationsInput | number id?: IntFieldUpdateOperationsInput | number
contractId?: IntFieldUpdateOperationsInput | number contractId?: IntFieldUpdateOperationsInput | number
maloId?: NullableStringFieldUpdateOperationsInput | string | null
annualConsumption?: NullableFloatFieldUpdateOperationsInput | number | null annualConsumption?: NullableFloatFieldUpdateOperationsInput | number | null
annualConsumptionKwh?: NullableFloatFieldUpdateOperationsInput | number | null
basePrice?: NullableFloatFieldUpdateOperationsInput | number | null basePrice?: NullableFloatFieldUpdateOperationsInput | number | null
unitPrice?: NullableFloatFieldUpdateOperationsInput | number | null unitPrice?: NullableFloatFieldUpdateOperationsInput | number | null
bonus?: NullableFloatFieldUpdateOperationsInput | number | null bonus?: NullableFloatFieldUpdateOperationsInput | number | null

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
{ {
"name": "prisma-client-5918fcf1a24d6a26f6b4fad7137d1ae3a684231bfa7340820c473996737deea6", "name": "prisma-client-86f9a11dd446473e587830adde1df64246ce246e4602839fa2ced48c6aa2f902",
"main": "index.js", "main": "index.js",
"types": "index.d.ts", "types": "index.d.ts",
"browser": "index-browser.js", "browser": "index-browser.js",

View File

@ -602,9 +602,11 @@ model EnergyContractDetails {
contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade) contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)
meterId Int? meterId Int?
meter Meter? @relation(fields: [meterId], references: [id]) meter Meter? @relation(fields: [meterId], references: [id])
annualConsumption Float? maloId String? // Marktlokations-ID
basePrice Float? annualConsumption Float? // kWh für Strom, m³ für Gas
unitPrice Float? annualConsumptionKwh Float? // kWh für Gas (zusätzlich zu m³)
basePrice Float? // €/Monat
unitPrice Float? // €/kWh (Arbeitspreis)
bonus Float? bonus Float?
previousProviderName String? previousProviderName String?
previousCustomerNumber String? previousCustomerNumber String?

View File

@ -466,7 +466,9 @@ exports.Prisma.EnergyContractDetailsScalarFieldEnum = {
id: 'id', id: 'id',
contractId: 'contractId', contractId: 'contractId',
meterId: 'meterId', meterId: 'meterId',
maloId: 'maloId',
annualConsumption: 'annualConsumption', annualConsumption: 'annualConsumption',
annualConsumptionKwh: 'annualConsumptionKwh',
basePrice: 'basePrice', basePrice: 'basePrice',
unitPrice: 'unitPrice', unitPrice: 'unitPrice',
bonus: 'bonus', bonus: 'bonus',

View File

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE `EnergyContractDetails` ADD COLUMN `annualConsumptionKwh` DOUBLE NULL;

View File

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE `EnergyContractDetails` ADD COLUMN `maloId` VARCHAR(191) NULL;

View File

@ -602,9 +602,11 @@ model EnergyContractDetails {
contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade) contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)
meterId Int? meterId Int?
meter Meter? @relation(fields: [meterId], references: [id]) meter Meter? @relation(fields: [meterId], references: [id])
annualConsumption Float? maloId String? // Marktlokations-ID
basePrice Float? annualConsumption Float? // kWh für Strom, m³ für Gas
unitPrice Float? annualConsumptionKwh Float? // kWh für Gas (zusätzlich zu m³)
basePrice Float? // €/Monat
unitPrice Float? // €/kWh (Arbeitspreis)
bonus Float? bonus Float?
previousProviderName String? previousProviderName String?
previousCustomerNumber String? previousCustomerNumber String?

View File

@ -344,16 +344,29 @@ export async function getCockpitData(): Promise<CockpitResult> {
} }
// 7. KEINE BANKVERBINDUNG // 7. KEINE BANKVERBINDUNG
// Für DSL, FIBER, CABLE, MOBILE ist dies ein kritisches Problem
const requiresBankAndId = ['DSL', 'FIBER', 'CABLE', 'MOBILE'].includes(contract.type);
if (!contract.bankCardId) { if (!contract.bankCardId) {
issues.push({ issues.push({
type: 'missing_bank', type: 'missing_bank',
label: 'Bankverbindung fehlt', label: 'Bankverbindung fehlt',
urgency: 'warning', urgency: requiresBankAndId ? 'critical' : 'warning',
details: 'Keine Bankverbindung verknüpft', details: 'Keine Bankverbindung verknüpft',
}); });
summary.byCategory.missingData++; summary.byCategory.missingData++;
} }
// 7b. KEIN AUSWEIS (für DSL, FIBER, CABLE, MOBILE ist dies ein kritisches Problem)
if (!contract.identityDocumentId) {
issues.push({
type: 'missing_identity_document',
label: 'Ausweis fehlt',
urgency: requiresBankAndId ? 'critical' : 'warning',
details: 'Kein Ausweisdokument verknüpft',
});
summary.byCategory.missingData++;
}
// 8. ENERGIE-SPEZIFISCH: KEIN ZÄHLER // 8. ENERGIE-SPEZIFISCH: KEIN ZÄHLER
if (['ELECTRICITY', 'GAS'].includes(contract.type) && contract.energyDetails) { if (['ELECTRICITY', 'GAS'].includes(contract.type) && contract.energyDetails) {
if (!contract.energyDetails.meterId) { if (!contract.energyDetails.meterId) {

File diff suppressed because one or more lines are too long

View File

@ -5,7 +5,7 @@
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>OpenCRM</title> <title>OpenCRM</title>
<script type="module" crossorigin src="/assets/index-BNDhEhH4.js"></script> <script type="module" crossorigin src="/assets/index-DFHCN9Vs.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-DWDTTlpk.css"> <link rel="stylesheet" crossorigin href="/assets/index-DWDTTlpk.css">
</head> </head>
<body> <body>

View File

@ -9,7 +9,6 @@ import Card from '../../components/ui/Card';
import Button from '../../components/ui/Button'; import Button from '../../components/ui/Button';
import Badge from '../../components/ui/Badge'; import Badge from '../../components/ui/Badge';
import Input from '../../components/ui/Input'; import Input from '../../components/ui/Input';
import Select from '../../components/ui/Select';
import Modal from '../../components/ui/Modal'; import Modal from '../../components/ui/Modal';
import FileUpload from '../../components/ui/FileUpload'; 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'; 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(reading.readingDate).toISOString().split('T')[0]
: new Date().toISOString().split('T')[0], : new Date().toISOString().split('T')[0],
value: reading?.value?.toString() || '', value: reading?.value?.toString() || '',
unit: reading?.unit || defaultUnit,
notes: reading?.notes || '', notes: reading?.notes || '',
}); });
@ -345,7 +343,7 @@ function MeterReadingModal({
const data = { const data = {
readingDate: new Date(formData.readingDate), readingDate: new Date(formData.readingDate),
value: parseFloat(formData.value), value: parseFloat(formData.value),
unit: formData.unit, unit: defaultUnit,
notes: formData.notes || undefined, notes: formData.notes || undefined,
}; };
if (isEditing) { if (isEditing) {
@ -379,15 +377,12 @@ function MeterReadingModal({
required required
/> />
</div> </div>
<Select <div>
label="Einheit" <label className="block text-sm font-medium text-gray-700 mb-1">Einheit</label>
value={formData.unit} <div className="h-10 flex items-center px-3 bg-gray-100 border border-gray-300 rounded-md text-gray-700">
onChange={(e) => setFormData({ ...formData, unit: e.target.value })} {defaultUnit}
options={[ </div>
{ value: 'kWh', label: 'kWh' }, </div>
{ value: 'm³', label: 'm³' },
]}
/>
</div> </div>
<Input <Input
@ -1931,27 +1926,43 @@ export default function ContractDetail() {
</dd> </dd>
</div> </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 && ( {c.energyDetails.annualConsumption && (
<div> <div>
<dt className="text-sm text-gray-500">Jahresverbrauch</dt> <dt className="text-sm text-gray-500">
Jahresverbrauch {c.type === 'ELECTRICITY' ? '' : '(m³)'}
</dt>
<dd> <dd>
{c.energyDetails.annualConsumption.toLocaleString('de-DE')}{' '} {c.energyDetails.annualConsumption.toLocaleString('de-DE')}{' '}
{c.type === 'ELECTRICITY' ? 'kWh' : 'm³'} {c.type === 'ELECTRICITY' ? 'kWh' : 'm³'}
</dd> </dd>
</div> </div>
)} )}
{c.energyDetails.basePrice && ( {c.type === 'GAS' && c.energyDetails.annualConsumptionKwh && (
<div> <div>
<dt className="text-sm text-gray-500">Grundpreis</dt> <dt className="text-sm text-gray-500">Jahresverbrauch (kWh)</dt>
<dd>{c.energyDetails.basePrice.toLocaleString('de-DE')} /Monat</dd> <dd>{c.energyDetails.annualConsumptionKwh.toLocaleString('de-DE')} kWh</dd>
</div> </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> <div>
<dt className="text-sm text-gray-500">Arbeitspreis</dt> <dt className="text-sm text-gray-500">Arbeitspreis</dt>
<dd> <dd>
{c.energyDetails.unitPrice.toLocaleString('de-DE')} ct/ {c.energyDetails.unitPrice.toLocaleString('de-DE', { minimumFractionDigits: 2, maximumFractionDigits: 10 })} /kWh
{c.type === 'ELECTRICITY' ? 'kWh' : 'm³'}
</dd> </dd>
</div> </div>
)} )}

View File

@ -228,7 +228,9 @@ export default function ContractForm() {
notes: c.notes || '', notes: c.notes || '',
// Energy details // Energy details
meterId: c.energyDetails?.meterId?.toString() || '', meterId: c.energyDetails?.meterId?.toString() || '',
maloId: c.energyDetails?.maloId || '',
annualConsumption: c.energyDetails?.annualConsumption || '', annualConsumption: c.energyDetails?.annualConsumption || '',
annualConsumptionKwh: c.energyDetails?.annualConsumptionKwh || '',
basePrice: c.energyDetails?.basePrice || '', basePrice: c.energyDetails?.basePrice || '',
unitPrice: c.energyDetails?.unitPrice || '', unitPrice: c.energyDetails?.unitPrice || '',
bonus: c.energyDetails?.bonus || '', bonus: c.energyDetails?.bonus || '',
@ -455,7 +457,9 @@ export default function ContractForm() {
if (['ELECTRICITY', 'GAS'].includes(data.type)) { if (['ELECTRICITY', 'GAS'].includes(data.type)) {
contractData.energyDetails = { contractData.energyDetails = {
meterId: safeParseInt(data.meterId) ?? null, meterId: safeParseInt(data.meterId) ?? null,
maloId: emptyToNull(data.maloId),
annualConsumption: data.annualConsumption ? parseFloat(data.annualConsumption) : null, annualConsumption: data.annualConsumption ? parseFloat(data.annualConsumption) : null,
annualConsumptionKwh: data.annualConsumptionKwh ? parseFloat(data.annualConsumptionKwh) : null,
basePrice: data.basePrice ? parseFloat(data.basePrice) : null, basePrice: data.basePrice ? parseFloat(data.basePrice) : null,
unitPrice: data.unitPrice ? parseFloat(data.unitPrice) : null, unitPrice: data.unitPrice ? parseFloat(data.unitPrice) : null,
bonus: data.bonus ? parseFloat(data.bonus) : null, bonus: data.bonus ? parseFloat(data.bonus) : null,
@ -864,16 +868,27 @@ export default function ContractForm() {
label: `${m.meterNumber}${m.location ? ` (${m.location})` : ''}`, label: `${m.meterNumber}${m.location ? ` (${m.location})` : ''}`,
}))} }))}
/> />
<Input
label="MaLo-ID (Marktlokations-ID)"
{...register('maloId')}
/>
<Input <Input
label={`Jahresverbrauch (${contractType === 'ELECTRICITY' ? 'kWh' : 'm³'})`} label={`Jahresverbrauch (${contractType === 'ELECTRICITY' ? 'kWh' : 'm³'})`}
type="number" type="number"
{...register('annualConsumption')} {...register('annualConsumption')}
/> />
<Input label="Grundpreis (€/Monat)" type="number" step="0.01" {...register('basePrice')} /> {contractType === 'GAS' && (
<Input <Input
label={`Arbeitspreis (ct/${contractType === 'ELECTRICITY' ? 'kWh' : 'm³'})`} label="Jahresverbrauch (kWh)"
type="number" type="number"
step="0.01" {...register('annualConsumptionKwh')}
/>
)}
<Input label="Grundpreis (€/Monat)" type="number" step="any" {...register('basePrice')} />
<Input
label="Arbeitspreis (€/kWh)"
type="number"
step="any"
{...register('unitPrice')} {...register('unitPrice')}
/> />
<Input label="Bonus (€)" type="number" step="0.01" {...register('bonus')} /> <Input label="Bonus (€)" type="number" step="0.01" {...register('bonus')} />

View File

@ -1256,9 +1256,9 @@ function MetersTab({
onAdd: () => void; onAdd: () => void;
onEdit: (meter: Meter) => 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 [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 queryClient = useQueryClient();
const updateMutation = useMutation({ const updateMutation = useMutation({
@ -1333,7 +1333,7 @@ function MetersTab({
<Button <Button
variant="ghost" variant="ghost"
size="sm" size="sm"
onClick={() => setShowReadingModal(meter.id)} onClick={() => setShowReadingModal({ meterId: meter.id, meterType: meter.type })}
title="Zählerstand hinzufügen" title="Zählerstand hinzufügen"
> >
<Plus className="w-4 h-4" /> <Plus className="w-4 h-4" />
@ -1430,7 +1430,7 @@ function MetersTab({
{canEdit && ( {canEdit && (
<div className="opacity-0 group-hover:opacity-100 flex gap-1"> <div className="opacity-0 group-hover:opacity-100 flex gap-1">
<button <button
onClick={() => setEditingReading({ meterId: meter.id, reading })} onClick={() => setEditingReading({ meterId: meter.id, meterType: meter.type, reading })}
className="text-gray-400 hover:text-blue-600" className="text-gray-400 hover:text-blue-600"
title="Bearbeiten" title="Bearbeiten"
> >
@ -1467,7 +1467,8 @@ function MetersTab({
<MeterReadingModal <MeterReadingModal
isOpen={true} isOpen={true}
onClose={() => setShowReadingModal(null)} onClose={() => setShowReadingModal(null)}
meterId={showReadingModal} meterId={showReadingModal.meterId}
meterType={showReadingModal.meterType}
customerId={customerId} customerId={customerId}
/> />
)} )}
@ -1477,6 +1478,7 @@ function MetersTab({
isOpen={true} isOpen={true}
onClose={() => setEditingReading(null)} onClose={() => setEditingReading(null)}
meterId={editingReading.meterId} meterId={editingReading.meterId}
meterType={editingReading.meterType}
customerId={customerId} customerId={customerId}
reading={editingReading.reading} reading={editingReading.reading}
/> />
@ -2601,24 +2603,26 @@ function MeterReadingModal({
isOpen, isOpen,
onClose, onClose,
meterId, meterId,
meterType,
customerId, customerId,
reading, reading,
}: { }: {
isOpen: boolean; isOpen: boolean;
onClose: () => void; onClose: () => void;
meterId: number; meterId: number;
meterType: 'ELECTRICITY' | 'GAS';
customerId: number; customerId: number;
reading?: { id: number; readingDate: string; value: number; unit: string; notes?: string } | null; reading?: { id: number; readingDate: string; value: number; unit: string; notes?: string } | null;
}) { }) {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const isEditing = !!reading; const isEditing = !!reading;
const defaultUnit = meterType === 'ELECTRICITY' ? 'kWh' : 'm³';
const getInitialFormData = () => ({ const getInitialFormData = () => ({
readingDate: reading?.readingDate readingDate: reading?.readingDate
? new Date(reading.readingDate).toISOString().split('T')[0] ? new Date(reading.readingDate).toISOString().split('T')[0]
: new Date().toISOString().split('T')[0], : new Date().toISOString().split('T')[0],
value: reading?.value?.toString() || '', value: reading?.value?.toString() || '',
unit: reading?.unit || 'kWh',
notes: reading?.notes || '', notes: reading?.notes || '',
}); });
@ -2645,7 +2649,7 @@ function MeterReadingModal({
const data = { const data = {
readingDate: new Date(formData.readingDate), readingDate: new Date(formData.readingDate),
value: parseFloat(formData.value), value: parseFloat(formData.value),
unit: formData.unit, unit: defaultUnit,
notes: formData.notes || undefined, notes: formData.notes || undefined,
}; };
if (isEditing) { if (isEditing) {
@ -2684,15 +2688,12 @@ function MeterReadingModal({
required required
/> />
</div> </div>
<Select <div>
label="Einheit" <label className="block text-sm font-medium text-gray-700 mb-1">Einheit</label>
value={formData.unit} <div className="h-10 flex items-center px-3 bg-gray-100 border border-gray-300 rounded-md text-gray-700">
onChange={(e) => setFormData({ ...formData, unit: e.target.value })} {defaultUnit}
options={[ </div>
{ value: 'kWh', label: 'kWh' }, </div>
{ value: 'm³', label: 'm³' },
]}
/>
</div> </div>
<Input <Input

View File

@ -336,9 +336,11 @@ export interface EnergyContractDetails {
contractId: number; contractId: number;
meterId?: number; meterId?: number;
meter?: Meter; meter?: Meter;
annualConsumption?: number; maloId?: string; // Marktlokations-ID
basePrice?: number; annualConsumption?: number; // kWh für Strom, m³ für Gas
unitPrice?: number; annualConsumptionKwh?: number; // kWh für Gas (zusätzlich zu m³)
basePrice?: number; // €/Monat
unitPrice?: number; // €/kWh (Arbeitspreis)
bonus?: number; bonus?: number;
previousProviderName?: string; previousProviderName?: string;
previousCustomerNumber?: string; previousCustomerNumber?: string;