import { prisma as db } from "@repo/db/client"; import { AppointmentUncheckedCreateInputObjectSchema, PatientUncheckedCreateInputObjectSchema, UserUncheckedCreateInputObjectSchema, StaffUncheckedCreateInputObjectSchema, ClaimUncheckedCreateInputObjectSchema, InsuranceCredentialUncheckedCreateInputObjectSchema, ClaimPdfUncheckedCreateInputObjectSchema, } from "@repo/db/usedSchemas"; import { z } from "zod"; //creating types out of schema auto generated. type Appointment = z.infer; const insertAppointmentSchema = ( AppointmentUncheckedCreateInputObjectSchema as unknown as z.ZodObject ).omit({ id: true, createdAt: true, }); type InsertAppointment = z.infer; const updateAppointmentSchema = ( AppointmentUncheckedCreateInputObjectSchema as unknown as z.ZodObject ) .omit({ id: true, createdAt: true, }) .partial(); type UpdateAppointment = z.infer; //patient types const PatientSchema = ( PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject ).omit({ appointments: true, }); type Patient = z.infer; type Patient2 = z.infer; const insertPatientSchema = ( PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject ).omit({ id: true, createdAt: true, }); type InsertPatient = z.infer; const updatePatientSchema = ( PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject ) .omit({ id: true, createdAt: true, userId: true, }) .partial(); type UpdatePatient = z.infer; //user types type User = z.infer; const insertUserSchema = ( UserUncheckedCreateInputObjectSchema as unknown as z.ZodObject ).pick({ username: true, password: true, }); const loginSchema = (insertUserSchema as unknown as z.ZodObject).extend({ rememberMe: z.boolean().optional(), }); const registerSchema = (insertUserSchema as unknown as z.ZodObject) .extend({ confirmPassword: z.string().min(6, { message: "Password must be at least 6 characters long", }), agreeTerms: z.literal(true, { errorMap: () => ({ message: "You must agree to the terms and conditions", }), }), }) .refine((data: any) => data.password === data.confirmPassword, { message: "Passwords don't match", path: ["confirmPassword"], }); type InsertUser = z.infer; type LoginFormValues = z.infer; type RegisterFormValues = z.infer; // staff types: type Staff = z.infer; // Claim typse: const insertClaimSchema = ( ClaimUncheckedCreateInputObjectSchema as unknown as z.ZodObject ).omit({ id: true, createdAt: true, updatedAt: true, }); type InsertClaim = z.infer; const updateClaimSchema = ( ClaimUncheckedCreateInputObjectSchema as unknown as z.ZodObject ) .omit({ id: true, createdAt: true, updatedAt: true, }) .partial(); type UpdateClaim = z.infer; type Claim = z.infer; // InsuraneCreds types: type InsuranceCredential = z.infer< typeof InsuranceCredentialUncheckedCreateInputObjectSchema >; const insertInsuranceCredentialSchema = ( InsuranceCredentialUncheckedCreateInputObjectSchema as unknown as z.ZodObject ).omit({ id: true }); type InsertInsuranceCredential = z.infer< typeof insertInsuranceCredentialSchema >; type ClaimWithServiceLines = Claim & { serviceLines: { id: number; claimId: number; procedureCode: string; procedureDate: Date; oralCavityArea: string | null; toothNumber: string | null; toothSurface: string | null; billedAmount: number; }[]; }; // claim types: type ClaimPdf = z.infer; export interface ClaimPdfMetadata { id: number; filename: string; uploadedAt: Date; } export interface IStorage { // User methods getUser(id: number): Promise; getUserByUsername(username: string): Promise; createUser(user: InsertUser): Promise; updateUser(id: number, updates: Partial): Promise; deleteUser(id: number): Promise; // Patient methods getPatient(id: number): Promise; getPatientsByUserId(userId: number): Promise; getRecentPatients(limit: number, offset: number): Promise; getTotalPatientCount(): Promise; createPatient(patient: InsertPatient): Promise; updatePatient(id: number, patient: UpdatePatient): Promise; deletePatient(id: number): Promise; // Appointment methods getAppointment(id: number): Promise; getAllAppointments(): Promise; getAppointmentsByUserId(userId: number): Promise; getAppointmentsByPatientId(patientId: number): Promise; getRecentAppointments(limit: number, offset: number): Promise; getAppointmentsOn(date: Date): Promise; createAppointment(appointment: InsertAppointment): Promise; updateAppointment( id: number, appointment: UpdateAppointment ): Promise; deleteAppointment(id: number): Promise; // Staff methods getStaff(id: number): Promise; getAllStaff(): Promise; createStaff(staff: Staff): Promise; updateStaff(id: number, updates: Partial): Promise; deleteStaff(id: number): Promise; // Claim methods getClaim(id: number): Promise; getClaimsByUserId(userId: number): Promise; getClaimsByPatientId(patientId: number): Promise; getClaimsByAppointmentId(appointmentId: number): Promise; getClaimsPaginated( userId: number, offset: number, limit: number ): Promise; countClaimsByUserId(userId: number): Promise; getClaimsMetadataByUser( userId: number ): Promise<{ id: number; createdAt: Date; status: string }[]>; createClaim(claim: InsertClaim): Promise; updateClaim(id: number, updates: UpdateClaim): Promise; deleteClaim(id: number): Promise; // InsuranceCredential methods getInsuranceCredentialsByUser(userId: number): Promise; createInsuranceCredential( data: InsertInsuranceCredential ): Promise; updateInsuranceCredential( id: number, updates: Partial ): Promise; deleteInsuranceCredential(id: number): Promise; getInsuranceCredentialByUserAndSiteKey( userId: number, siteKey: string ): Promise; // Claim PDF Methods createClaimPdf( patientId: number, claimId: number, filename: string, pdfData: Buffer ): Promise; getClaimPdfById(id: number): Promise; getAllClaimPdfs(): Promise; getRecentClaimPdfs( limit: number, offset: number ): Promise; deleteClaimPdf(id: number): Promise; updateClaimPdf( id: number, updates: Partial> ): Promise; } export const storage: IStorage = { // User methods async getUser(id: number): Promise { const user = await db.user.findUnique({ where: { id } }); return user ?? undefined; }, async getUserByUsername(username: string): Promise { const user = await db.user.findUnique({ where: { username } }); return user ?? undefined; }, async createUser(user: InsertUser): Promise { return await db.user.create({ data: user as User }); }, async updateUser( id: number, updates: Partial ): Promise { try { return await db.user.update({ where: { id }, data: updates }); } catch { return undefined; } }, async deleteUser(id: number): Promise { try { await db.user.delete({ where: { id } }); return true; } catch { return false; } }, // Patient methods async getPatient(id: number): Promise { const patient = await db.patient.findUnique({ where: { id } }); return patient ?? undefined; }, async getPatientsByUserId(userId: number): Promise { return await db.patient.findMany({ where: { userId } }); }, async getRecentPatients(limit: number, offset: number): Promise { return db.patient.findMany({ skip: offset, take: limit, orderBy: { createdAt: "desc" }, }); }, async getTotalPatientCount(): Promise { return db.patient.count(); }, async createPatient(patient: InsertPatient): Promise { return await db.patient.create({ data: patient as Patient }); }, async updatePatient(id: number, updateData: UpdatePatient): Promise { try { return await db.patient.update({ where: { id }, data: updateData, }); } catch (err) { throw new Error(`Patient with ID ${id} not found`); } }, async deletePatient(id: number): Promise { try { await db.patient.delete({ where: { id } }); } catch (err) { console.error("Error deleting patient:", err); throw new Error(`Failed to delete patient: ${err}`); } }, // Appointment methods async getAppointment(id: number): Promise { const appointment = await db.appointment.findUnique({ where: { id } }); return appointment ?? undefined; }, async getAllAppointments(): Promise { return await db.appointment.findMany(); }, async getAppointmentsByUserId(userId: number): Promise { return await db.appointment.findMany({ where: { userId } }); }, async getAppointmentsByPatientId(patientId: number): Promise { return await db.appointment.findMany({ where: { patientId } }); }, async getAppointmentsOn(date: Date): Promise { const start = new Date(date); start.setHours(0, 0, 0, 0); const end = new Date(date); end.setHours(23, 59, 59, 999); return db.appointment.findMany({ where: { date: { gte: start, lte: end, }, }, orderBy: { date: "asc" }, }); }, async getRecentAppointments( limit: number, offset: number ): Promise { return db.appointment.findMany({ skip: offset, take: limit, orderBy: { date: "desc" }, }); }, async createAppointment( appointment: InsertAppointment ): Promise { return await db.appointment.create({ data: appointment as Appointment }); }, async updateAppointment( id: number, updateData: UpdateAppointment ): Promise { try { return await db.appointment.update({ where: { id }, data: updateData, }); } catch (err) { throw new Error(`Appointment with ID ${id} not found`); } }, async deleteAppointment(id: number): Promise { try { await db.appointment.delete({ where: { id } }); } catch (err) { throw new Error(`Appointment with ID ${id} not found`); } }, async getStaff(id: number): Promise { const staff = await db.staff.findUnique({ where: { id } }); return staff ?? undefined; }, async getAllStaff(): Promise { const staff = await db.staff.findMany(); return staff; }, async createStaff(staff: Staff): Promise { const createdStaff = await db.staff.create({ data: staff, }); return createdStaff; }, async updateStaff( id: number, updates: Partial ): Promise { const updatedStaff = await db.staff.update({ where: { id }, data: updates, }); return updatedStaff ?? undefined; }, async deleteStaff(id: number): Promise { try { await db.staff.delete({ where: { id } }); return true; } catch (error) { console.error("Error deleting staff:", error); return false; } }, // Claim methods implementation async getClaim(id: number): Promise { const claim = await db.claim.findUnique({ where: { id } }); return claim ?? undefined; }, async getClaimsByUserId(userId: number): Promise { return await db.claim.findMany({ where: { userId } }); }, async getClaimsByPatientId(patientId: number): Promise { return await db.claim.findMany({ where: { patientId } }); }, async getClaimsByAppointmentId(appointmentId: number): Promise { return await db.claim.findMany({ where: { appointmentId } }); }, async createClaim(claim: InsertClaim): Promise { return await db.claim.create({ data: claim as Claim }); }, async updateClaim(id: number, updates: UpdateClaim): Promise { try { return await db.claim.update({ where: { id }, data: updates, }); } catch (err) { throw new Error(`Claim with ID ${id} not found`); } }, async deleteClaim(id: number): Promise { try { await db.claim.delete({ where: { id } }); } catch (err) { throw new Error(`Claim with ID ${id} not found`); } }, async getClaimsPaginated( userId: number, offset: number, limit: number ): Promise { return db.claim.findMany({ where: { userId }, orderBy: { createdAt: "desc" }, skip: offset, take: limit, include: { serviceLines: true }, }); }, async countClaimsByUserId(userId: number): Promise { return db.claim.count({ where: { userId } }); }, async getClaimsMetadataByUser( userId: number ): Promise<{ id: number; createdAt: Date; status: string }[]> { return db.claim.findMany({ where: { userId }, orderBy: { createdAt: "desc" }, select: { id: true, createdAt: true, status: true, }, }); }, // Insurance Creds async getInsuranceCredentialsByUser(userId: number) { return await db.insuranceCredential.findMany({ where: { userId } }); }, async createInsuranceCredential(data: InsertInsuranceCredential) { return await db.insuranceCredential.create({ data: data as InsuranceCredential, }); }, async updateInsuranceCredential( id: number, updates: Partial ) { return await db.insuranceCredential.update({ where: { id }, data: updates, }); }, async deleteInsuranceCredential(id: number) { await db.insuranceCredential.delete({ where: { id } }); }, async getInsuranceCredentialByUserAndSiteKey( userId: number, siteKey: string ): Promise { return await db.insuranceCredential.findFirst({ where: { userId, siteKey }, }); }, // pdf claims async createClaimPdf( patientId, claimId, filename, pdfData ): Promise { return db.claimPdf.create({ data: { patientId, claimId, filename, pdfData, }, }); }, async getClaimPdfById(id: number): Promise { const pdf = await db.claimPdf.findUnique({ where: { id } }); return pdf ?? undefined; }, async getAllClaimPdfs(): Promise { return db.claimPdf.findMany({ select: { id: true, filename: true, uploadedAt: true }, orderBy: { uploadedAt: "desc" }, }); }, async getRecentClaimPdfs( limit: number, offset: number ): Promise { return db.claimPdf.findMany({ skip: offset, take: limit, orderBy: { uploadedAt: "desc" }, select: { id: true, filename: true, uploadedAt: true, patient: true, }, }); }, async deleteClaimPdf(id: number): Promise { try { await db.claimPdf.delete({ where: { id } }); return true; } catch { return false; } }, async updateClaimPdf( id: number, updates: Partial> ): Promise { try { const updated = await db.claimPdf.update({ where: { id }, data: updates, }); return updated; } catch { return undefined; } }, };