154 lines
5.1 KiB
TypeScript
154 lines
5.1 KiB
TypeScript
import { router, protectedProcedure } from '@/src/trpc/trpc-index'
|
|
import { z } from 'zod';
|
|
import { db } from '@/src/db/db_index'
|
|
import { productAvailabilitySchedules } from '@/src/db/schema'
|
|
import { eq } from 'drizzle-orm';
|
|
import { refreshScheduleJobs } from '@/src/lib/automatedJobs';
|
|
|
|
const createScheduleSchema = z.object({
|
|
scheduleName: z.string().min(1, "Schedule name is required"),
|
|
time: z.string().min(1, "Time is required").regex(/^([01]?[0-9]|2[0-3]):[0-5][0-9]$/, "Invalid time format. Use HH:MM"),
|
|
action: z.enum(['in', 'out']),
|
|
productIds: z.array(z.number().int().positive()).min(1, "At least one product is required"),
|
|
groupIds: z.array(z.number().int().positive()).default([]),
|
|
});
|
|
|
|
const updateScheduleSchema = z.object({
|
|
id: z.number().int().positive(),
|
|
updates: createScheduleSchema.partial().extend({
|
|
scheduleName: z.string().min(1).optional(),
|
|
productIds: z.array(z.number().int().positive()).optional(),
|
|
groupIds: z.array(z.number().int().positive()).optional(),
|
|
}),
|
|
});
|
|
|
|
export const productAvailabilitySchedulesRouter = router({
|
|
create: protectedProcedure
|
|
.input(createScheduleSchema)
|
|
.mutation(async ({ input, ctx }) => {
|
|
const { scheduleName, time, action, productIds, groupIds } = input;
|
|
|
|
// Get staff user ID from auth middleware
|
|
const staffUserId = ctx.staffUser?.id;
|
|
if (!staffUserId) {
|
|
throw new Error("Unauthorized");
|
|
}
|
|
|
|
// Check if schedule name already exists
|
|
const existingSchedule = await db.query.productAvailabilitySchedules.findFirst({
|
|
where: eq(productAvailabilitySchedules.scheduleName, scheduleName),
|
|
});
|
|
if (existingSchedule) {
|
|
throw new Error("Schedule name already exists");
|
|
}
|
|
|
|
// Create schedule with arrays
|
|
const scheduleResult = await db.insert(productAvailabilitySchedules).values({
|
|
scheduleName,
|
|
time,
|
|
action,
|
|
productIds,
|
|
groupIds,
|
|
}).returning();
|
|
|
|
// Refresh cron jobs to include new schedule
|
|
await refreshScheduleJobs();
|
|
|
|
return scheduleResult[0];
|
|
}),
|
|
|
|
getAll: protectedProcedure
|
|
.query(async () => {
|
|
const schedules = await db.query.productAvailabilitySchedules.findMany({
|
|
orderBy: (productAvailabilitySchedules, { desc }) => [desc(productAvailabilitySchedules.createdAt)],
|
|
});
|
|
|
|
return schedules.map(schedule => ({
|
|
...schedule,
|
|
productCount: schedule.productIds.length,
|
|
groupCount: schedule.groupIds.length,
|
|
}));
|
|
}),
|
|
|
|
getById: protectedProcedure
|
|
.input(z.object({ id: z.number().int().positive() }))
|
|
.query(async ({ input }) => {
|
|
const { id } = input;
|
|
|
|
const schedule = await db.query.productAvailabilitySchedules.findFirst({
|
|
where: eq(productAvailabilitySchedules.id, id),
|
|
});
|
|
|
|
if (!schedule) {
|
|
throw new Error("Schedule not found");
|
|
}
|
|
|
|
return schedule;
|
|
}),
|
|
|
|
update: protectedProcedure
|
|
.input(updateScheduleSchema)
|
|
.mutation(async ({ input }) => {
|
|
const { id, updates } = input;
|
|
|
|
// Check if schedule exists
|
|
const existingSchedule = await db.query.productAvailabilitySchedules.findFirst({
|
|
where: eq(productAvailabilitySchedules.id, id),
|
|
});
|
|
if (!existingSchedule) {
|
|
throw new Error("Schedule not found");
|
|
}
|
|
|
|
// Check schedule name uniqueness if being updated
|
|
if (updates.scheduleName && updates.scheduleName !== existingSchedule.scheduleName) {
|
|
const duplicateSchedule = await db.query.productAvailabilitySchedules.findFirst({
|
|
where: eq(productAvailabilitySchedules.scheduleName, updates.scheduleName),
|
|
});
|
|
if (duplicateSchedule) {
|
|
throw new Error("Schedule name already exists");
|
|
}
|
|
}
|
|
|
|
// Update schedule
|
|
const updateData: any = {};
|
|
if (updates.scheduleName !== undefined) updateData.scheduleName = updates.scheduleName;
|
|
if (updates.time !== undefined) updateData.time = updates.time;
|
|
if (updates.action !== undefined) updateData.action = updates.action;
|
|
if (updates.productIds !== undefined) updateData.productIds = updates.productIds;
|
|
if (updates.groupIds !== undefined) updateData.groupIds = updates.groupIds;
|
|
updateData.lastUpdated = new Date();
|
|
|
|
const result = await db.update(productAvailabilitySchedules)
|
|
.set(updateData)
|
|
.where(eq(productAvailabilitySchedules.id, id))
|
|
.returning();
|
|
|
|
if (result.length === 0) {
|
|
throw new Error("Failed to update schedule");
|
|
}
|
|
|
|
// Refresh cron jobs to reflect changes
|
|
await refreshScheduleJobs();
|
|
|
|
return result[0];
|
|
}),
|
|
|
|
delete: protectedProcedure
|
|
.input(z.object({ id: z.number().int().positive() }))
|
|
.mutation(async ({ input }) => {
|
|
const { id } = input;
|
|
|
|
const result = await db.delete(productAvailabilitySchedules)
|
|
.where(eq(productAvailabilitySchedules.id, id))
|
|
.returning();
|
|
|
|
if (result.length === 0) {
|
|
throw new Error("Schedule not found");
|
|
}
|
|
|
|
// Refresh cron jobs to remove deleted schedule
|
|
await refreshScheduleJobs();
|
|
|
|
return { message: "Schedule deleted successfully" };
|
|
}),
|
|
});
|