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;
meterId: number | null;
contractId: number;
maloId: string | null;
annualConsumption: number | null;
annualConsumptionKwh: number | null;
basePrice: number | null;
unitPrice: number | null;
bonus: number | null;
@ -423,7 +425,9 @@ export declare function getContractById(id: number, decryptPassword?: boolean):
id: number;
meterId: number | null;
contractId: number;
maloId: string | null;
annualConsumption: number | null;
annualConsumptionKwh: number | null;
basePrice: number | null;
unitPrice: number | null;
bonus: number | null;
@ -738,7 +742,9 @@ export declare function createContract(data: ContractCreateData): Promise<{
id: number;
meterId: number | null;
contractId: number;
maloId: string | null;
annualConsumption: number | null;
annualConsumptionKwh: number | null;
basePrice: number | null;
unitPrice: number | null;
bonus: number | null;
@ -972,7 +978,9 @@ export declare function updateContract(id: number, data: Partial<ContractCreateD
id: number;
meterId: number | null;
contractId: number;
maloId: string | null;
annualConsumption: number | null;
annualConsumptionKwh: number | null;
basePrice: number | null;
unitPrice: number | null;
bonus: number | null;
@ -1149,7 +1157,9 @@ export declare function updateContract(id: number, data: Partial<ContractCreateD
id: number;
meterId: number | null;
contractId: number;
maloId: string | null;
annualConsumption: number | null;
annualConsumptionKwh: number | null;
basePrice: number | null;
unitPrice: number | null;
bonus: number | null;
@ -1406,7 +1416,9 @@ export declare function createFollowUpContract(previousContractId: number): Prom
id: number;
meterId: number | null;
contractId: number;
maloId: string | null;
annualConsumption: number | null;
annualConsumptionKwh: number | null;
basePrice: number | null;
unitPrice: 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++;
}
// 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) {
issues.push({
type: 'missing_bank',
label: 'Bankverbindung fehlt',
urgency: 'warning',
urgency: requiresBankAndId ? 'critical' : 'warning',
details: 'Keine Bankverbindung verknüpft',
});
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
if (['ELECTRICITY', 'GAS'].includes(contract.type) && contract.energyDetails) {
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',
contractId: 'contractId',
meterId: 'meterId',
maloId: 'maloId',
annualConsumption: 'annualConsumption',
annualConsumptionKwh: 'annualConsumptionKwh',
basePrice: 'basePrice',
unitPrice: 'unitPrice',
bonus: 'bonus',

View File

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

View File

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

View File

@ -466,7 +466,9 @@ exports.Prisma.EnergyContractDetailsScalarFieldEnum = {
id: 'id',
contractId: 'contractId',
meterId: 'meterId',
maloId: 'maloId',
annualConsumption: 'annualConsumption',
annualConsumptionKwh: 'annualConsumptionKwh',
basePrice: 'basePrice',
unitPrice: 'unitPrice',
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

@ -597,16 +597,18 @@ model ContractTaskSubtask {
// ==================== ENERGY CONTRACT DETAILS ====================
model EnergyContractDetails {
id Int @id @default(autoincrement())
contractId Int @unique
contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)
meterId Int?
meter Meter? @relation(fields: [meterId], references: [id])
annualConsumption Float?
basePrice Float?
unitPrice Float?
bonus Float?
previousProviderName String?
id Int @id @default(autoincrement())
contractId Int @unique
contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)
meterId Int?
meter Meter? @relation(fields: [meterId], references: [id])
maloId String? // Marktlokations-ID
annualConsumption Float? // kWh für Strom, m³ für Gas
annualConsumptionKwh Float? // kWh für Gas (zusätzlich zu m³)
basePrice Float? // €/Monat
unitPrice Float? // €/kWh (Arbeitspreis)
bonus Float?
previousProviderName String?
previousCustomerNumber String?
}

View File

@ -344,16 +344,29 @@ export async function getCockpitData(): Promise<CockpitResult> {
}
// 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) {
issues.push({
type: 'missing_bank',
label: 'Bankverbindung fehlt',
urgency: 'warning',
urgency: requiresBankAndId ? 'critical' : 'warning',
details: 'Keine Bankverbindung verknüpft',
});
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
if (['ELECTRICITY', 'GAS'].includes(contract.type) && contract.energyDetails) {
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" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<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">
</head>
<body>

View File

@ -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>
)}

View File

@ -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')} />

View File

@ -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

View File

@ -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;