import type { Prisma } from "@prisma/client"; import type { CalendarViewValue, SessionDatePresetValue } from "@/lib/constants"; import { getCalendarRange, getSessionRangeForPreset, parseCairoDateTimeInput } from "@/lib/date-time"; import { trimOrUndefined } from "@/lib/utils"; import { getCourtByGovernorateAndName } from "@/server/courts/service"; import { requireCaseByIdForOwner } from "@/server/cases/service"; import { requireCustomerByIdForOwner } from "@/server/customers/service"; import { db } from "@/server/db"; import { AppError } from "@/server/errors"; import type { CourtSessionCreateInput, CourtSessionListQueryInput, CourtSessionUpdateInput, } from "@/server/validation/case"; export type CourtSessionFilters = { preset: SessionDatePresetValue; selectedSessionId?: string; }; export function normalizeCourtSessionFilters( input: CourtSessionListQueryInput, ): CourtSessionFilters { return { preset: input.sessionPreset, selectedSessionId: trimOrUndefined(input.sessionId), }; } function buildCourtSessionWhere({ ownerId, customerId, caseId, preset, }: { ownerId: string; customerId?: string; caseId?: string; preset: SessionDatePresetValue; }): Prisma.CourtSessionWhereInput { const range = getSessionRangeForPreset(preset); return { ownerId, ...(customerId ? { customerId } : {}), ...(caseId ? { caseId } : {}), ...(range ? { scheduledAt: range, } : {}), }; } export async function createCourtSessionForCase( ownerId: string, customerId: string, caseId: string, input: CourtSessionCreateInput, ) { await requireCaseByIdForOwner(ownerId, customerId, caseId); const court = getCourtByGovernorateAndName(input.governorate, input.courtName); return db.courtSession.create({ data: { ownerId, customerId, caseId, governorate: court.governorate, courtName: court.courtName, courtLocation: court.courtLocation, locationDetails: trimOrUndefined(input.locationDetails), scheduledAt: parseCairoDateTimeInput(input.scheduledAt), }, include: { case: true, customer: true, }, }); } export async function listCaseSessionsForOwner( ownerId: string, customerId: string, caseId: string, preset: SessionDatePresetValue, ) { await requireCaseByIdForOwner(ownerId, customerId, caseId); return db.courtSession.findMany({ where: buildCourtSessionWhere({ ownerId, customerId, caseId, preset, }), include: { case: true, customer: true, }, orderBy: { scheduledAt: "asc", }, }); } export async function listCustomerSessionsForOwner( ownerId: string, customerId: string, preset: SessionDatePresetValue, ) { await requireCustomerByIdForOwner(customerId, ownerId); return db.courtSession.findMany({ where: buildCourtSessionWhere({ ownerId, customerId, preset, }), include: { case: true, customer: true, }, orderBy: { scheduledAt: "asc", }, }); } export async function getCourtSessionByIdForOwner( ownerId: string, customerId: string, caseId: string, sessionId: string, ) { return db.courtSession.findFirst({ where: { id: sessionId, ownerId, customerId, caseId, }, include: { case: true, customer: true, }, }); } export async function requireCourtSessionByIdForOwner( ownerId: string, customerId: string, caseId: string, sessionId: string, ) { const session = await getCourtSessionByIdForOwner( ownerId, customerId, caseId, sessionId, ); if (!session) { throw new AppError("الجلسة دي مش موجودة.", 404); } return session; } export async function updateCourtSessionTimeForOwner( ownerId: string, customerId: string, caseId: string, sessionId: string, input: CourtSessionUpdateInput, ) { await requireCourtSessionByIdForOwner(ownerId, customerId, caseId, sessionId); return db.courtSession.update({ where: { id: sessionId, }, data: { scheduledAt: parseCairoDateTimeInput(input.scheduledAt), }, include: { case: true, customer: true, }, }); } export async function deleteCourtSessionForOwner( ownerId: string, customerId: string, caseId: string, sessionId: string, ) { await requireCourtSessionByIdForOwner(ownerId, customerId, caseId, sessionId); await db.courtSession.delete({ where: { id: sessionId, }, }); } export async function listCalendarSessionsForOwner( ownerId: string, view: CalendarViewValue, anchor?: string, ) { const range = getCalendarRange(view, anchor); const items = await db.courtSession.findMany({ where: { ownerId, scheduledAt: { gte: range.gte, lt: range.lt, }, }, include: { case: { include: { customer: true, }, }, customer: true, }, orderBy: { scheduledAt: "asc", }, }); return { items, count: items.length, range, }; }