import { desc, eq, type Database } from "@pkg/db"; import { customerInfo, order } from "@pkg/db/schema"; import { getError, Logger } from "@pkg/logger"; import { ERROR_CODES, type Result } from "@pkg/result"; import { customerInfoModel, type CreateCustomerInfoPayload, type CustomerInfoModel, type UpdateCustomerInfoPayload, } from "./data"; export class CustomerInfoRepository { private db: Database; constructor(db: Database) { this.db = db; } async getAllCustomerInfo(): Promise> { try { const results = await this.db.query.customerInfo.findMany({ orderBy: [desc(customerInfo.createdAt)], }); const out = [] as CustomerInfoModel[]; for (const result of results) { const parsed = customerInfoModel.safeParse(result); if (!parsed.success) { Logger.error("Failed to parse customer info"); Logger.error(parsed.error); continue; } out.push(parsed.data); } return { data: out }; } catch (e) { return { error: getError( { code: ERROR_CODES.DATABASE_ERROR, message: "Failed to fetch customer information", detail: "An error occurred while retrieving customer information from the database", userHint: "Please try refreshing the page", actionable: false, }, e, ), }; } } async getCustomerInfoById(id: number): Promise> { try { const result = await this.db.query.customerInfo.findFirst({ where: eq(customerInfo.id, id), }); if (!result) { return { error: getError({ code: ERROR_CODES.NOT_FOUND_ERROR, message: "Customer information not found", detail: "No customer information exists with the provided ID", userHint: "Please check the customer ID and try again", actionable: true, }), }; } const parsed = customerInfoModel.safeParse(result); if (!parsed.success) { Logger.error("Failed to parse customer info", result); return { error: getError({ code: ERROR_CODES.INTERNAL_SERVER_ERROR, message: "Failed to parse customer information", userHint: "Please try again", detail: "Failed to parse customer information", }), }; } return { data: parsed.data }; } catch (e) { return { error: getError( { code: ERROR_CODES.DATABASE_ERROR, message: "Failed to fetch customer information", detail: "An error occurred while retrieving the customer information from the database", userHint: "Please try refreshing the page", actionable: false, }, e, ), }; } } async getCustomerInfoByOrderId( oid: number, ): Promise> { try { const result = await this.db.query.order.findFirst({ where: eq(order.id, oid), columns: { id: true }, with: { customerInfo: true }, }); const parsed = customerInfoModel.safeParse(result?.customerInfo); if (!parsed.success) { Logger.error("Failed to parse customer info", result); return { error: getError({ code: ERROR_CODES.INTERNAL_SERVER_ERROR, message: "Failed to parse customer information", userHint: "Please try again", detail: "Failed to parse customer information", }), }; } return { data: parsed.data }; } catch (e) { return { error: getError( { code: ERROR_CODES.DATABASE_ERROR, message: "Failed to fetch customer information", detail: "An error occurred while retrieving the customer information from the database", userHint: "Please try refreshing the page", actionable: false, }, e, ), }; } } async createCustomerInfo( payload: CreateCustomerInfoPayload, ): Promise> { try { const result = await this.db .insert(customerInfo) .values({ firstName: payload.firstName, middleName: payload.middleName || "", lastName: payload.lastName, email: payload.email, phoneCountryCode: payload.phoneCountryCode, phoneNumber: payload.phoneNumber, country: payload.country, state: payload.state, city: payload.city, zipCode: payload.zipCode, address: payload.address, address2: payload.address2 || null, }) .returning({ id: customerInfo.id }) .execute(); if (!result || result.length === 0) { throw new Error("Failed to create customer info record"); } return { data: result[0].id }; } catch (e) { return { error: getError( { code: ERROR_CODES.DATABASE_ERROR, message: "Failed to create customer information", detail: "An error occurred while creating the customer information", userHint: "Please try again", actionable: false, }, e, ), }; } } async updateCustomerInfo( payload: UpdateCustomerInfoPayload, ): Promise> { try { if (!payload.id) { return { error: getError({ code: ERROR_CODES.VALIDATION_ERROR, message: "Invalid customer ID", detail: "No customer ID was provided for the update operation", userHint: "Please provide a valid customer ID", actionable: true, }), }; } // Check if customer info exists const existing = await this.db.query.customerInfo.findFirst({ where: eq(customerInfo.id, payload.id), }); if (!existing) { return { error: getError({ code: ERROR_CODES.NOT_FOUND_ERROR, message: "Customer information not found", detail: "No customer information exists with the provided ID", userHint: "Please check the customer ID and try again", actionable: true, }), }; } // Build the update object with only the fields that are provided const updateValues: Record = {}; if (payload.firstName !== undefined) updateValues.firstName = payload.firstName; if (payload.middleName !== undefined) updateValues.middleName = payload.middleName; if (payload.lastName !== undefined) updateValues.lastName = payload.lastName; if (payload.email !== undefined) updateValues.email = payload.email; if (payload.phoneCountryCode !== undefined) updateValues.phoneCountryCode = payload.phoneCountryCode; if (payload.phoneNumber !== undefined) updateValues.phoneNumber = payload.phoneNumber; if (payload.country !== undefined) updateValues.country = payload.country; if (payload.state !== undefined) updateValues.state = payload.state; if (payload.city !== undefined) updateValues.city = payload.city; if (payload.zipCode !== undefined) updateValues.zipCode = payload.zipCode; if (payload.address !== undefined) updateValues.address = payload.address; if (payload.address2 !== undefined) updateValues.address2 = payload.address2; updateValues.updatedAt = new Date(); await this.db .update(customerInfo) .set(updateValues) .where(eq(customerInfo.id, payload.id)) .execute(); return { data: true }; } catch (e) { return { error: getError( { code: ERROR_CODES.DATABASE_ERROR, message: "Failed to update customer information", detail: "An error occurred while updating the customer information", userHint: "Please try again", actionable: false, }, e, ), }; } } async deleteCustomerInfo(id: number): Promise> { try { // Check if customer info exists const existing = await this.db.query.customerInfo.findFirst({ where: eq(customerInfo.id, id), }); if (!existing) { return { error: getError({ code: ERROR_CODES.NOT_FOUND_ERROR, message: "Customer information not found", detail: "No customer information exists with the provided ID", userHint: "Please check the customer ID and try again", actionable: true, }), }; } await this.db .delete(customerInfo) .where(eq(customerInfo.id, id)) .execute(); return { data: true }; } catch (e) { return { error: getError( { code: ERROR_CODES.DATABASE_ERROR, message: "Failed to delete customer information", detail: "An error occurred while deleting the customer information", userHint: "Please try again", actionable: false, }, e, ), }; } } }