93 lines
2.8 KiB
TypeScript
93 lines
2.8 KiB
TypeScript
'use server';
|
|
|
|
import { revalidatePath } from 'next/cache';
|
|
import { prisma } from '@/lib/prisma';
|
|
import { requireAdmin } from '@/lib/requireAdmin';
|
|
import {
|
|
clampFulfillment,
|
|
deriveBookingStatus,
|
|
} from '@/lib/bookingStatus';
|
|
|
|
async function recomputeBookingStatus(bookingId: string) {
|
|
const booking = await prisma.booking.findUnique({
|
|
where: { id: bookingId },
|
|
include: { items: true },
|
|
});
|
|
if (!booking) return;
|
|
const next = deriveBookingStatus(booking.status, booking.items);
|
|
if (next !== booking.status) {
|
|
await prisma.booking.update({
|
|
where: { id: bookingId },
|
|
data: { status: next },
|
|
});
|
|
}
|
|
}
|
|
|
|
export async function setItemFulfillment(formData: FormData) {
|
|
await requireAdmin();
|
|
const bookingId = String(formData.get('bookingId') ?? '');
|
|
const itemId = String(formData.get('itemId') ?? '');
|
|
const deliveredRaw = Number(formData.get('delivered') ?? 0);
|
|
const returnedRaw = Number(formData.get('returned') ?? 0);
|
|
if (!bookingId || !itemId) return;
|
|
|
|
const item = await prisma.bookingItem.findUnique({ where: { id: itemId } });
|
|
if (!item || item.bookingId !== bookingId) return;
|
|
|
|
const { delivered, returned } = clampFulfillment(
|
|
item.quantity,
|
|
deliveredRaw,
|
|
returnedRaw,
|
|
);
|
|
|
|
await prisma.bookingItem.update({
|
|
where: { id: itemId },
|
|
data: { deliveredQuantity: delivered, returnedQuantity: returned },
|
|
});
|
|
|
|
await recomputeBookingStatus(bookingId);
|
|
revalidatePath(`/admin/bookings/${bookingId}`);
|
|
revalidatePath('/admin');
|
|
}
|
|
|
|
export async function markAllDelivered(formData: FormData) {
|
|
await requireAdmin();
|
|
const bookingId = String(formData.get('bookingId') ?? '');
|
|
if (!bookingId) return;
|
|
|
|
const items = await prisma.bookingItem.findMany({ where: { bookingId } });
|
|
await prisma.$transaction(
|
|
items.map((it) =>
|
|
prisma.bookingItem.update({
|
|
where: { id: it.id },
|
|
data: { deliveredQuantity: it.quantity },
|
|
}),
|
|
),
|
|
);
|
|
await recomputeBookingStatus(bookingId);
|
|
revalidatePath(`/admin/bookings/${bookingId}`);
|
|
revalidatePath('/admin');
|
|
}
|
|
|
|
export async function markAllReturned(formData: FormData) {
|
|
await requireAdmin();
|
|
const bookingId = String(formData.get('bookingId') ?? '');
|
|
if (!bookingId) return;
|
|
|
|
const items = await prisma.bookingItem.findMany({ where: { bookingId } });
|
|
// "Return all" means: everything that was handed out comes back. If nothing
|
|
// was marked delivered we treat it as a full handout + return cycle.
|
|
await prisma.$transaction(
|
|
items.map((it) => {
|
|
const delivered = it.deliveredQuantity > 0 ? it.deliveredQuantity : it.quantity;
|
|
return prisma.bookingItem.update({
|
|
where: { id: it.id },
|
|
data: { deliveredQuantity: delivered, returnedQuantity: delivered },
|
|
});
|
|
}),
|
|
);
|
|
await recomputeBookingStatus(bookingId);
|
|
revalidatePath(`/admin/bookings/${bookingId}`);
|
|
revalidatePath('/admin');
|
|
}
|