import { classes, users } from "@db/schema"; import { eq, sql } from "drizzle-orm"; import { DrizzleClient } from "@shared/db/DrizzleClient"; import { UserError } from "@shared/lib/errors"; import { withTransaction } from "@/lib/db"; import type { Transaction } from "@shared/lib/types"; export const classService = { getAllClasses: async () => { return await DrizzleClient.query.classes.findMany(); }, assignClass: async (userId: string, classId: bigint, tx?: Transaction) => { return await withTransaction(async (txFn) => { const cls = await txFn.query.classes.findFirst({ where: eq(classes.id, classId), }); if (!cls) throw new UserError("Class not found"); const [user] = await txFn.update(users) .set({ classId: classId }) .where(eq(users.id, BigInt(userId))) .returning(); return user; }, tx); }, getClassBalance: async (classId: bigint) => { const cls = await DrizzleClient.query.classes.findFirst({ where: eq(classes.id, classId), }); return cls?.balance || 0n; }, modifyClassBalance: async (classId: bigint, amount: bigint, tx?: Transaction) => { return await withTransaction(async (txFn) => { const cls = await txFn.query.classes.findFirst({ where: eq(classes.id, classId), }); if (!cls) throw new UserError("Class not found"); if ((cls.balance ?? 0n) + amount < 0n) { throw new UserError("Insufficient class funds"); } const [updatedClass] = await txFn.update(classes) .set({ balance: sql`${classes.balance} + ${amount} `, }) .where(eq(classes.id, classId)) .returning(); return updatedClass; }, tx); }, updateClass: async (id: bigint, data: Partial, tx?: Transaction) => { return await withTransaction(async (txFn) => { const [updatedClass] = await txFn.update(classes) .set(data) .where(eq(classes.id, id)) .returning(); return updatedClass; }, tx); }, createClass: async (data: typeof classes.$inferInsert, tx?: Transaction) => { return await withTransaction(async (txFn) => { const [newClass] = await txFn.insert(classes) .values(data) .returning(); return newClass; }, tx); }, deleteClass: async (id: bigint, tx?: Transaction) => { return await withTransaction(async (txFn) => { await txFn.delete(classes).where(eq(classes.id, id)); }, tx); } };