import { CreateHolidayCalendarEntrySchema, CreateHolidayCalendarSchema, UpdateHolidayCalendarEntrySchema, UpdateHolidayCalendarSchema, } from "@capakraken/shared"; import { z } from "zod"; import { findUniqueOrThrow } from "../db/helpers.js"; import { makeAuditLogger } from "../lib/audit-helpers.js"; import type { TRPCContext } from "../trpc.js"; import { asHolidayCalendarDb } from "./holiday-calendar-shared.js"; import { buildHolidayCalendarCreateData, buildHolidayCalendarEntryCreateData, buildHolidayCalendarEntryUpdateData, buildHolidayCalendarUpdateData, holidayCalendarDetailInclude, } from "./holiday-calendar-support.js"; import { assertHolidayCalendarEntryDateAvailable, assertHolidayCalendarScopeConsistency, clampHolidayCalendarDate, normalizeHolidayCalendarScopeInput, resolveHolidayCalendarUpdateScope, } from "./holiday-calendar-write-support.js"; type HolidayCalendarProcedureContext = Pick; export const holidayCalendarIdInputSchema = z.object({ id: z.string(), }); export const holidayCalendarUpdateInputSchema = z.object({ id: z.string(), data: UpdateHolidayCalendarSchema, }); export const holidayCalendarEntryUpdateInputSchema = z.object({ id: z.string(), data: UpdateHolidayCalendarEntrySchema, }); type HolidayCalendarIdInput = z.infer; type HolidayCalendarCreateInput = z.infer; type HolidayCalendarUpdateInput = z.infer; type HolidayCalendarEntryCreateInput = z.infer; type HolidayCalendarEntryUpdateInput = z.infer; export async function createHolidayCalendar( ctx: HolidayCalendarProcedureContext, input: HolidayCalendarCreateInput, ) { const audit = makeAuditLogger(ctx.db, ctx.dbUser?.id); const db = asHolidayCalendarDb(ctx.db); await findUniqueOrThrow( ctx.db.country.findUnique({ where: { id: input.countryId }, select: { id: true, name: true }, }), "Country", ); const normalizedScope = normalizeHolidayCalendarScopeInput({ stateCode: input.stateCode, metroCityId: input.metroCityId, }); await assertHolidayCalendarScopeConsistency(db, { scopeType: input.scopeType, countryId: input.countryId, ...normalizedScope, }); const created = await db.holidayCalendar.create({ data: buildHolidayCalendarCreateData({ ...input, normalizedScope, }), include: holidayCalendarDetailInclude, }); audit({ entityType: "HolidayCalendar", entityId: created.id, entityName: created.name, action: "CREATE", after: created as unknown as Record, }); return created; } export async function updateHolidayCalendar( ctx: HolidayCalendarProcedureContext, input: HolidayCalendarUpdateInput, ) { const audit = makeAuditLogger(ctx.db, ctx.dbUser?.id); const db = asHolidayCalendarDb(ctx.db); const existing = await findUniqueOrThrow( db.holidayCalendar.findUnique({ where: { id: input.id } }), "Holiday calendar", ); const { stateCode, metroCityId } = resolveHolidayCalendarUpdateScope({ existing, data: input.data, }); await assertHolidayCalendarScopeConsistency(db, { scopeType: existing.scopeType, countryId: existing.countryId, stateCode, metroCityId, }, existing.id); const updated = await db.holidayCalendar.update({ where: { id: input.id }, data: buildHolidayCalendarUpdateData({ data: input.data, resolvedScope: { stateCode, metroCityId, }, }), include: holidayCalendarDetailInclude, }); audit({ entityType: "HolidayCalendar", entityId: updated.id, entityName: updated.name, action: "UPDATE", before: existing as unknown as Record, after: updated as unknown as Record, }); return updated; } export async function deleteHolidayCalendar( ctx: HolidayCalendarProcedureContext, input: HolidayCalendarIdInput, ) { const audit = makeAuditLogger(ctx.db, ctx.dbUser?.id); const db = asHolidayCalendarDb(ctx.db); const existing = await findUniqueOrThrow( db.holidayCalendar.findUnique({ where: { id: input.id }, include: { entries: true }, }), "Holiday calendar", ); await db.holidayCalendar.delete({ where: { id: input.id } }); audit({ entityType: "HolidayCalendar", entityId: existing.id, entityName: existing.name, action: "DELETE", before: existing as unknown as Record, }); return { success: true, id: existing.id, name: existing.name }; } export async function createHolidayCalendarEntry( ctx: HolidayCalendarProcedureContext, input: HolidayCalendarEntryCreateInput, ) { const audit = makeAuditLogger(ctx.db, ctx.dbUser?.id); const db = asHolidayCalendarDb(ctx.db); await findUniqueOrThrow( db.holidayCalendar.findUnique({ where: { id: input.holidayCalendarId }, select: { id: true, name: true }, }), "Holiday calendar", ); await assertHolidayCalendarEntryDateAvailable(db, { holidayCalendarId: input.holidayCalendarId, date: input.date, }); const created = await db.holidayCalendarEntry.create({ data: buildHolidayCalendarEntryCreateData({ data: input, date: clampHolidayCalendarDate(input.date), }), }); audit({ entityType: "HolidayCalendarEntry", entityId: created.id, entityName: created.name, action: "CREATE", after: created as unknown as Record, }); return created; } export async function updateHolidayCalendarEntry( ctx: HolidayCalendarProcedureContext, input: HolidayCalendarEntryUpdateInput, ) { const audit = makeAuditLogger(ctx.db, ctx.dbUser?.id); const db = asHolidayCalendarDb(ctx.db); const existing = await findUniqueOrThrow( db.holidayCalendarEntry.findUnique({ where: { id: input.id } }), "Holiday calendar entry", ); const nextDate = input.data.date !== undefined ? clampHolidayCalendarDate(input.data.date) : existing.date; await assertHolidayCalendarEntryDateAvailable(db, { holidayCalendarId: existing.holidayCalendarId, date: nextDate, }, existing.id); const updated = await db.holidayCalendarEntry.update({ where: { id: input.id }, data: buildHolidayCalendarEntryUpdateData({ data: input.data, date: nextDate, }), }); audit({ entityType: "HolidayCalendarEntry", entityId: updated.id, entityName: updated.name, action: "UPDATE", before: existing as unknown as Record, after: updated as unknown as Record, }); return updated; } export async function deleteHolidayCalendarEntry( ctx: HolidayCalendarProcedureContext, input: HolidayCalendarIdInput, ) { const audit = makeAuditLogger(ctx.db, ctx.dbUser?.id); const db = asHolidayCalendarDb(ctx.db); const existing = await findUniqueOrThrow( db.holidayCalendarEntry.findUnique({ where: { id: input.id } }), "Holiday calendar entry", ); await db.holidayCalendarEntry.delete({ where: { id: input.id } }); audit({ entityType: "HolidayCalendarEntry", entityId: existing.id, entityName: existing.name, action: "DELETE", before: existing as unknown as Record, }); return { success: true, id: existing.id, name: existing.name }; }