From 0fa97c53b17631744084290ce53cb9b67aa4a81a Mon Sep 17 00:00:00 2001 From: Marcel Arndt Date: Thu, 12 Jun 2025 17:14:51 +0200 Subject: [PATCH] feat: implement new costTypes Grundpreis auf Zeit, sowie Privat Versicherung --- .../migration.sql | 8 +++++ .../migration.sql | 2 ++ .../prisma/migrations/migration_lock.toml | 4 +-- .../data-connector/prisma/schema.prisma | 2 ++ .../prisma/seed/tariffs/btw-aok.ts | 12 ++++---- .../prisma/seed/tariffs/ktw-aok.ts | 6 ++-- .../prisma/seed/tariffs/ktw-privat.ts | 6 ++-- .../prisma/seed/tariffs/tsw-aok.ts | 22 +++++++------- .../prisma/seed/tariffs/tsw-dak-vdek.ts | 5 ++-- .../data-connector/src/core/database/types.ts | 4 ++- .../feat-calculation/calculation.service.ts | 29 ++++++++++--------- .../cost-type-calculations.ts | 10 +++++++ 12 files changed, 69 insertions(+), 41 deletions(-) create mode 100644 service/data-hub/data-connector/prisma/migrations/20250606084334_add_grundpreis_zeit/migration.sql create mode 100644 service/data-hub/data-connector/prisma/migrations/20250606101116_add_privatversicherung/migration.sql diff --git a/service/data-hub/data-connector/prisma/migrations/20250606084334_add_grundpreis_zeit/migration.sql b/service/data-hub/data-connector/prisma/migrations/20250606084334_add_grundpreis_zeit/migration.sql new file mode 100644 index 0000000..623f1a5 --- /dev/null +++ b/service/data-hub/data-connector/prisma/migrations/20250606084334_add_grundpreis_zeit/migration.sql @@ -0,0 +1,8 @@ +-- AlterEnum +ALTER TYPE "CostTypeVariant" ADD VALUE 'GRUNDPREIS_ZEIT'; + +-- AlterTable +ALTER TABLE "_AvicennaTenantToTariffGroup" ADD CONSTRAINT "_AvicennaTenantToTariffGroup_AB_pkey" PRIMARY KEY ("A", "B"); + +-- DropIndex +DROP INDEX "_AvicennaTenantToTariffGroup_AB_unique"; diff --git a/service/data-hub/data-connector/prisma/migrations/20250606101116_add_privatversicherung/migration.sql b/service/data-hub/data-connector/prisma/migrations/20250606101116_add_privatversicherung/migration.sql new file mode 100644 index 0000000..e89d026 --- /dev/null +++ b/service/data-hub/data-connector/prisma/migrations/20250606101116_add_privatversicherung/migration.sql @@ -0,0 +1,2 @@ +-- AlterEnum +ALTER TYPE "CostTypeVariant" ADD VALUE 'PRIVATVERSICHERUNG'; diff --git a/service/data-hub/data-connector/prisma/migrations/migration_lock.toml b/service/data-hub/data-connector/prisma/migrations/migration_lock.toml index fbffa92..044d57c 100644 --- a/service/data-hub/data-connector/prisma/migrations/migration_lock.toml +++ b/service/data-hub/data-connector/prisma/migrations/migration_lock.toml @@ -1,3 +1,3 @@ # Please do not edit this file manually -# It should be added in your version-control system (i.e. Git) -provider = "postgresql" \ No newline at end of file +# It should be added in your version-control system (e.g., Git) +provider = "postgresql" diff --git a/service/data-hub/data-connector/prisma/schema.prisma b/service/data-hub/data-connector/prisma/schema.prisma index a95975b..d4b2619 100644 --- a/service/data-hub/data-connector/prisma/schema.prisma +++ b/service/data-hub/data-connector/prisma/schema.prisma @@ -526,6 +526,8 @@ enum CostTypeVariant { FAHRZEUGZUSCHLAG TSWDIFFERENZIERUNG GRUNDPREIS + GRUNDPREIS_ZEIT + PRIVATVERSICHERUNG } model AvicennaTenant { diff --git a/service/data-hub/data-connector/prisma/seed/tariffs/btw-aok.ts b/service/data-hub/data-connector/prisma/seed/tariffs/btw-aok.ts index 87983f6..d5ee6d8 100644 --- a/service/data-hub/data-connector/prisma/seed/tariffs/btw-aok.ts +++ b/service/data-hub/data-connector/prisma/seed/tariffs/btw-aok.ts @@ -192,19 +192,19 @@ export const BTW_AOK_TARIFFS = [ costTypes: [ { description: 'Grundpauschale je Fahrt', - variant: CostTypeVariant.NACHTZUSCHLAG, + variant: CostTypeVariant.GRUNDPREIS_ZEIT, costAmount: 4250, timeRange: '00:00-14:29', }, { description: 'Grundpauschale je Fahrt', - variant: CostTypeVariant.NACHTZUSCHLAG, + variant: CostTypeVariant.GRUNDPREIS_ZEIT, costAmount: 4250, timeRange: '18:01-23:59', }, { description: 'Grundpauschale je Fahrt (14:30-18:00)', - variant: CostTypeVariant.NACHTZUSCHLAG, + variant: CostTypeVariant.GRUNDPREIS_ZEIT, costAmount: 5000, timeRange: '14:30-18:00', }, @@ -239,19 +239,19 @@ export const BTW_AOK_TARIFFS = [ costTypes: [ { description: 'Grundpauschale je Fahrt', - variant: CostTypeVariant.NACHTZUSCHLAG, + variant: CostTypeVariant.GRUNDPREIS_ZEIT, costAmount: 4500, timeRange: '00:00-14:29', }, { description: 'Grundpauschale je Fahrt', - variant: CostTypeVariant.NACHTZUSCHLAG, + variant: CostTypeVariant.GRUNDPREIS_ZEIT, costAmount: 4500, timeRange: '18:01-23:59', }, { description: 'Grundpauschale je Fahrt (14:30-18:00)', - variant: CostTypeVariant.NACHTZUSCHLAG, + variant: CostTypeVariant.GRUNDPREIS_ZEIT, costAmount: 5000, timeRange: '14:30-18:00', }, diff --git a/service/data-hub/data-connector/prisma/seed/tariffs/ktw-aok.ts b/service/data-hub/data-connector/prisma/seed/tariffs/ktw-aok.ts index ae2158f..0372925 100644 --- a/service/data-hub/data-connector/prisma/seed/tariffs/ktw-aok.ts +++ b/service/data-hub/data-connector/prisma/seed/tariffs/ktw-aok.ts @@ -358,7 +358,7 @@ export const KTW_AOK_TARIFFS = [ costAmount: 940, }, { - description: 'Desinfektionszuschlag pauschal', + description: 'Desinfektionpauschale', variant: CostTypeVariant.GRUNDPREIS, costAmount: 2610, }, @@ -369,10 +369,10 @@ export const KTW_AOK_TARIFFS = [ kmInclusive: 18, }, { - description: 'Nachtzuschlag 19:00-07:00', + description: 'Nachtzuschlag 18:30-06:30', variant: CostTypeVariant.NACHTZUSCHLAG, costAmount: 8875, - timeRange: '19:00-07:00', + timeRange: '18:30-06:30', }, { description: 'Wochenendzuschlag', diff --git a/service/data-hub/data-connector/prisma/seed/tariffs/ktw-privat.ts b/service/data-hub/data-connector/prisma/seed/tariffs/ktw-privat.ts index 89a6796..8112d9c 100644 --- a/service/data-hub/data-connector/prisma/seed/tariffs/ktw-privat.ts +++ b/service/data-hub/data-connector/prisma/seed/tariffs/ktw-privat.ts @@ -77,13 +77,13 @@ export const KTW_PRIVAT_TARIFFS = [ }, { description: 'QMS Zuschlag', - variant: CostTypeVariant.GRUNDPREIS, + variant: CostTypeVariant.PRIVATVERSICHERUNG, costAmount: 3300, }, { description: 'Hygienemaßnahmen', - variant: CostTypeVariant.GRUNDPREIS, - costAmount: 1500, + variant: CostTypeVariant.PRIVATVERSICHERUNG, + costAmount: 2000, }, { description: 'ab dem 16. km', diff --git a/service/data-hub/data-connector/prisma/seed/tariffs/tsw-aok.ts b/service/data-hub/data-connector/prisma/seed/tariffs/tsw-aok.ts index ac6f398..d6c35b1 100644 --- a/service/data-hub/data-connector/prisma/seed/tariffs/tsw-aok.ts +++ b/service/data-hub/data-connector/prisma/seed/tariffs/tsw-aok.ts @@ -185,19 +185,19 @@ export const TSW_AOK_TARIFFS = [ costTypes: [ { description: 'Grundpauschale je Fahrt', - variant: CostTypeVariant.NACHTZUSCHLAG, + variant: CostTypeVariant.GRUNDPREIS_ZEIT, costAmount: 6250, timeRange: '00:00-14:29', }, { description: 'Grundpauschale je Fahrt', - variant: CostTypeVariant.NACHTZUSCHLAG, + variant: CostTypeVariant.GRUNDPREIS_ZEIT, costAmount: 6250, timeRange: '18:01-23:59', }, { description: 'Nachmittagspauschale 14:30-18:00', - variant: CostTypeVariant.NACHTZUSCHLAG, + variant: CostTypeVariant.GRUNDPREIS_ZEIT, costAmount: 7500, timeRange: '14:30-18:00', }, @@ -232,13 +232,19 @@ export const TSW_AOK_TARIFFS = [ costTypes: [ { description: 'Grundpauschale je Fahrt', - variant: CostTypeVariant.NACHTZUSCHLAG, + variant: CostTypeVariant.GRUNDPREIS_ZEIT, costAmount: 6500, timeRange: '00:00-14:29', }, + { + description: 'Nachmittagspauschale 14:30-18:00', + variant: CostTypeVariant.GRUNDPREIS_ZEIT, + costAmount: 7500, + timeRange: '14:30-18:00', + }, { description: 'Grundpauschale je Fahrt', - variant: CostTypeVariant.NACHTZUSCHLAG, + variant: CostTypeVariant.GRUNDPREIS_ZEIT, costAmount: 6500, timeRange: '18:01-23:59', }, @@ -248,12 +254,6 @@ export const TSW_AOK_TARIFFS = [ costAmount: 200, kmInclusive: 20, }, - { - description: 'Nachmittagszuschlag 14:30-18:00', - variant: CostTypeVariant.NACHTZUSCHLAG, - costAmount: 7500, - timeRange: '14:30-18:00', - }, { description: 'Nachtzuschlag 18:00-07:30', variant: CostTypeVariant.NACHTZUSCHLAG, diff --git a/service/data-hub/data-connector/prisma/seed/tariffs/tsw-dak-vdek.ts b/service/data-hub/data-connector/prisma/seed/tariffs/tsw-dak-vdek.ts index 8888c95..d55c395 100644 --- a/service/data-hub/data-connector/prisma/seed/tariffs/tsw-dak-vdek.ts +++ b/service/data-hub/data-connector/prisma/seed/tariffs/tsw-dak-vdek.ts @@ -77,13 +77,14 @@ export const TSW_DAK_VDEK_TARIFFS = [ }, { description: 'Fallmanagementzuschlag', - variant: CostTypeVariant.GRUNDPREIS, + variant: CostTypeVariant.NACHTZUSCHLAG, costAmount: 750, + timeRange: '14:30-18:00', }, { description: 'Morgenzuschlag 05:00-07:00', variant: CostTypeVariant.NACHTZUSCHLAG, - costAmount: 450, + costAmount: 445, timeRange: '05:00-07:00', }, { diff --git a/service/data-hub/data-connector/src/core/database/types.ts b/service/data-hub/data-connector/src/core/database/types.ts index ec7880c..42a4f66 100644 --- a/service/data-hub/data-connector/src/core/database/types.ts +++ b/service/data-hub/data-connector/src/core/database/types.ts @@ -37,7 +37,9 @@ export const CostTypeVariant = { KILOMETERZUSCHLAG: "KILOMETERZUSCHLAG", FAHRZEUGZUSCHLAG: "FAHRZEUGZUSCHLAG", TSWDIFFERENZIERUNG: "TSWDIFFERENZIERUNG", - GRUNDPREIS: "GRUNDPREIS" + GRUNDPREIS: "GRUNDPREIS", + GRUNDPREIS_ZEIT: "GRUNDPREIS_ZEIT", + PRIVATVERSICHERUNG: "PRIVATVERSICHERUNG" } as const; export type CostTypeVariant = (typeof CostTypeVariant)[keyof typeof CostTypeVariant]; export type Anomaly = { diff --git a/service/data-hub/data-connector/src/modules/feat-calculation/calculation.service.ts b/service/data-hub/data-connector/src/modules/feat-calculation/calculation.service.ts index 4448182..84b994a 100644 --- a/service/data-hub/data-connector/src/modules/feat-calculation/calculation.service.ts +++ b/service/data-hub/data-connector/src/modules/feat-calculation/calculation.service.ts @@ -17,6 +17,7 @@ import { calculateFeiertagszuschlag, calculateKilometerzuschlag, calculateNachtzuschlag, + calculatePrivatVersicherung, calculateTSW, calculateWochenendzuschlag, } from './cost-type-calculations'; @@ -51,7 +52,7 @@ export class CalculationService { ); if (!tariff) { this.logger.warn( - `No tariff found for tour ${tour.operationId} (${tour.healthInsurance})`, + `No tariff found for tour ${tour.operationId} (${healthInsurance}, ${ordinanceType})`, ); return 0; } @@ -78,7 +79,7 @@ export class CalculationService { ); if (!tariff) { this.logger.warn( - `No tariff found for tour ${tour.operationId} (${healthInsurance}, ${ordinanceType}, ${startDate})`, + `No tariff found for tour ${tour.operationId} (${healthInsurance}, ${ordinanceType})`, ); return { tariff: undefined, servicePositions: [] }; } @@ -206,20 +207,17 @@ export class CalculationService { ): [CostType, number][] { const highestZuschlag = this.getHighestZuschlag(tour, tariff); // if TariffGroup is VDEK KTW, sum up costTypes - const isVdek = tariff.tariffGroup?.description?.indexOf('VDEK KTW') > -1; + const sumZuschlaege = + tariff.tariffGroup?.description?.indexOf('VDEK KTW') > -1 || + tariff.tariffGroup?.description?.indexOf('Privat') > -1; return tariff.costTypes .map((costType) => { switch (costType.variant) { case CostTypeVariant.GRUNDPREIS: - // TODO: decide if you need a CostTypeVariant for QMS Zuschlag and exclude the category there - if ( - costType.description.indexOf('QMS') > -1 && - tour.category === 'Privatfahrt Rechnung' - ) { - return [costType, 0]; - } return [costType, costType.costAmount]; + case CostTypeVariant.PRIVATVERSICHERUNG: + return [costType, calculatePrivatVersicherung(tour, costType)]; case CostTypeVariant.TSWDIFFERENZIERUNG: return [costType, calculateTSW(tour, costType)]; case CostTypeVariant.DESINFEKTIONSZUSCHLAG: @@ -228,15 +226,20 @@ export class CalculationService { return [costType, calculateKilometerzuschlag(tour, costType)]; case CostTypeVariant.FAHRZEUGZUSCHLAG: return [costType, calculateFahrzeugzuschlag(tour, costType)]; + case CostTypeVariant.GRUNDPREIS_ZEIT: case CostTypeVariant.NACHTZUSCHLAG: - if (highestZuschlag === CostTypeVariant.NACHTZUSCHLAG || isVdek) { + if ( + sumZuschlaege || + highestZuschlag === CostTypeVariant.NACHTZUSCHLAG || + costType.variant !== CostTypeVariant.NACHTZUSCHLAG + ) { return [costType, calculateNachtzuschlag(tour, costType)]; } return [costType, 0]; case CostTypeVariant.WOCHENENDZUSCHLAG: if ( highestZuschlag === CostTypeVariant.WOCHENENDZUSCHLAG || - isVdek + sumZuschlaege ) { return [costType, calculateWochenendzuschlag(tour, costType)]; } @@ -244,7 +247,7 @@ export class CalculationService { case CostTypeVariant.FEIERTAGSZUSCHLAG: if ( highestZuschlag === CostTypeVariant.FEIERTAGSZUSCHLAG || - isVdek + sumZuschlaege ) { return [costType, calculateFeiertagszuschlag(tour, costType)]; } diff --git a/service/data-hub/data-connector/src/modules/feat-calculation/cost-type-calculations.ts b/service/data-hub/data-connector/src/modules/feat-calculation/cost-type-calculations.ts index 5bf8153..fe9b5ca 100644 --- a/service/data-hub/data-connector/src/modules/feat-calculation/cost-type-calculations.ts +++ b/service/data-hub/data-connector/src/modules/feat-calculation/cost-type-calculations.ts @@ -5,6 +5,16 @@ import { generateIntervalForTimeRange } from 'src/utils'; import { INFECTION_TYPES } from './infection-types'; import { PUBLIC_HOLIDAYS_HH } from './public-holidays'; +export function calculatePrivatVersicherung(tour: Tour, costType: CostType): number { + if(tour.category?.indexOf('Privatfahrt Rechnung') === -1 && tour.category?.indexOf('Barzahlung') === -1) { + if(costType.description === 'Hygienemaßnahmen' && tour.hasInfection) { + return 0; + } + return costType.costAmount; + } + return 0; +} + export function calculateDesinfektionszuschlag( tour: Tour, costType: CostType,