219 lines
5.4 KiB
TypeScript
219 lines
5.4 KiB
TypeScript
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<T extends string>(
|
|
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<CampaignCreatePayload, "status" | "recurrence">
|
|
> & {
|
|
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;
|
|
}
|
|
|