import { CAMPAIGN_COUNTRY_CODE, CAMPAIGN_COUNTRY_NAME, CAMPAIGN_RECURRENCES, CAMPAIGN_STATUSES, ORTHODOX_POSTAL_CODE_MESSAGE } from "./campaign-form"; import { CampaignRecurrence, CampaignStatus } from "./campaign-scheduling"; const CAMPAIGN_POSTAL_CODE_REGEX = /^\d{5}$/; const MIN_RADIUS_KM = 1; const MAX_RADIUS_KM = 5000; const MIN_LEADS_PER_RUN = 1; const MAX_LEADS_PER_RUN = 9999; const MIN_AUDITS_PER_RUN = 1; const MAX_AUDITS_PER_RUN = 9999; function assert(condition: boolean, message: string): asserts condition { if (!condition) { throw new Error(message); } } function assertFiniteInteger( value: number, fieldLabel: string, min: number, max: number, ) { assert(Number.isFinite(value), `${fieldLabel} muss eine Zahl sein.`); assert(Number.isInteger(value), `${fieldLabel} muss eine ganze Zahl sein.`); assert( value >= min, `${fieldLabel} muss mindestens ${min} sein.`, ); assert( value <= max, `${fieldLabel} darf höchstens ${max} sein.`, ); } function assertAllowed( value: string, allowed: readonly T[], errorMessage: string, ): T { assert(allowed.includes(value as T), errorMessage); return value as T; } function assertCountryContext(countryCode?: string, country?: string) { const hasCountryCode = countryCode !== undefined; const hasCountry = country !== undefined; assert( !(hasCountryCode || hasCountry) || (hasCountryCode && hasCountry), "Deutschland-Kontext muss vollständig gesetzt oder ausgelassen werden.", ); if (hasCountryCode || hasCountry) { assert( countryCode === CAMPAIGN_COUNTRY_CODE && country === CAMPAIGN_COUNTRY_NAME, "Nur Deutschland-Context ist erlaubt.", ); } } export type CampaignCreatePayload = { status: CampaignStatus; recurrence: CampaignRecurrence; postalCode: string; radiusKm: number; maxNewLeadsPerRun: number; maxAuditsPerRun: number; countryCode: string; country: string; }; export type CampaignUpdatePayload = Partial< Omit > & { status?: CampaignStatus; recurrence?: CampaignRecurrence; countryCode: string; country: string; }; type CampaignCreateInput = { status: string; recurrence: string; postalCode: string; radiusKm: number; maxNewLeadsPerRun: number; maxAuditsPerRun: number; countryCode?: string; country?: string; }; type CampaignUpdateInput = { postalCode?: string; radiusKm?: number; maxNewLeadsPerRun?: number; maxAuditsPerRun?: number; status?: string; recurrence?: string; countryCode?: string; country?: string; }; export function validateCampaignCreateInput( input: CampaignCreateInput, ): CampaignCreatePayload { assertCountryContext(input.countryCode, input.country); const status = assertAllowed( input.status, CAMPAIGN_STATUSES, "Status ist ungültig.", ); const recurrence = assertAllowed( input.recurrence, CAMPAIGN_RECURRENCES, "Frequenz ist ungültig.", ); assert( CAMPAIGN_POSTAL_CODE_REGEX.test(input.postalCode), ORTHODOX_POSTAL_CODE_MESSAGE, ); assertFiniteInteger(input.radiusKm, "Radius", MIN_RADIUS_KM, MAX_RADIUS_KM); assertFiniteInteger( input.maxNewLeadsPerRun, "Max. neue Leads", MIN_LEADS_PER_RUN, MAX_LEADS_PER_RUN, ); assertFiniteInteger( input.maxAuditsPerRun, "Max. Audits", MIN_AUDITS_PER_RUN, MAX_AUDITS_PER_RUN, ); return { status, recurrence, postalCode: input.postalCode, radiusKm: input.radiusKm, maxNewLeadsPerRun: input.maxNewLeadsPerRun, maxAuditsPerRun: input.maxAuditsPerRun, countryCode: CAMPAIGN_COUNTRY_CODE, country: CAMPAIGN_COUNTRY_NAME, }; } export function validateCampaignUpdateInput( input: CampaignUpdateInput, ): CampaignUpdatePayload { const updates: CampaignUpdatePayload = { countryCode: CAMPAIGN_COUNTRY_CODE, country: CAMPAIGN_COUNTRY_NAME, }; assertCountryContext(input.countryCode, input.country); if (input.status !== undefined) { updates.status = assertAllowed( input.status, CAMPAIGN_STATUSES, "Status ist ungültig.", ); } if (input.recurrence !== undefined) { updates.recurrence = assertAllowed( input.recurrence, CAMPAIGN_RECURRENCES, "Frequenz ist ungültig.", ); } if (input.postalCode !== undefined) { assert( CAMPAIGN_POSTAL_CODE_REGEX.test(input.postalCode), ORTHODOX_POSTAL_CODE_MESSAGE, ); updates.postalCode = input.postalCode; } if (input.radiusKm !== undefined) { assertFiniteInteger(input.radiusKm, "Radius", MIN_RADIUS_KM, MAX_RADIUS_KM); updates.radiusKm = input.radiusKm; } if (input.maxNewLeadsPerRun !== undefined) { assertFiniteInteger( input.maxNewLeadsPerRun, "Max. neue Leads", MIN_LEADS_PER_RUN, MAX_LEADS_PER_RUN, ); updates.maxNewLeadsPerRun = input.maxNewLeadsPerRun; } if (input.maxAuditsPerRun !== undefined) { assertFiniteInteger( input.maxAuditsPerRun, "Max. Audits", MIN_AUDITS_PER_RUN, MAX_AUDITS_PER_RUN, ); updates.maxAuditsPerRun = input.maxAuditsPerRun; } if ( input.countryCode !== undefined || input.country !== undefined || input.status !== undefined || input.recurrence !== undefined || input.postalCode !== undefined || input.radiusKm !== undefined || input.maxNewLeadsPerRun !== undefined || input.maxAuditsPerRun !== undefined ) { return updates; } return updates; }