77 lines
2.3 KiB
TypeScript
77 lines
2.3 KiB
TypeScript
import { Errors } from '@/lib/errors';
|
|
import { db } from '@/lib/prisma';
|
|
import type { Result } from '@/lib/result';
|
|
import { err, ok } from '@/lib/result';
|
|
import type { UpdateAdminBookingStatusInput } from '@repo/api-contract';
|
|
import { v7 as uuidv7 } from 'uuid';
|
|
import { mapBookingResponse } from '../../shared/helpers';
|
|
|
|
export async function updateAdminBookingStatus(
|
|
userId: string,
|
|
bookingId: string,
|
|
input: UpdateAdminBookingStatusInput
|
|
): Promise<Result<ReturnType<typeof mapBookingResponse>>> {
|
|
const booking = await db.courtBooking.findFirst({
|
|
where: {
|
|
id: bookingId,
|
|
court: {
|
|
complex: { users: { some: { userId } } },
|
|
},
|
|
},
|
|
include: {
|
|
court: {
|
|
select: {
|
|
id: true,
|
|
name: true,
|
|
sport: { select: { id: true, name: true, slug: true } },
|
|
complex: { select: { id: true, complexName: true } },
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
if (!booking) {
|
|
return err(Errors.notFound('Reserva no encontrada.'));
|
|
}
|
|
|
|
if (input.status === 'CANCELLED' && booking.status !== 'CONFIRMED') {
|
|
return err(Errors.conflict('Solo se pueden cancelar reservas en estado confirmada.'));
|
|
}
|
|
|
|
if (input.status === 'COMPLETED' && booking.status !== 'CONFIRMED') {
|
|
return err(Errors.conflict('Solo se pueden marcar como cumplidas las reservas confirmadas.'));
|
|
}
|
|
|
|
if (input.status === 'NOSHOW' && booking.status !== 'CONFIRMED') {
|
|
return err(Errors.conflict('Solo se pueden marcar como no show las reservas confirmadas.'));
|
|
}
|
|
|
|
await db.courtBookingLog.create({
|
|
data: {
|
|
id: uuidv7(),
|
|
bookingCode: booking.bookingCode,
|
|
courtId: booking.court.id,
|
|
bookingDate: booking.bookingDate,
|
|
startTime: booking.startTime,
|
|
endTime: booking.endTime,
|
|
customerName: booking.customerName,
|
|
customerPhone: booking.customerPhone,
|
|
customerEmail: booking.customerEmail,
|
|
previousStatus: booking.status,
|
|
newStatus: input.status,
|
|
changedAt: new Date(),
|
|
},
|
|
});
|
|
|
|
if (input.status === 'COMPLETED' || input.status === 'NOSHOW') {
|
|
await db.courtBooking.update({
|
|
where: { id: booking.id },
|
|
data: { status: input.status },
|
|
});
|
|
} else {
|
|
await db.courtBooking.delete({ where: { id: booking.id } });
|
|
}
|
|
|
|
return ok(mapBookingResponse({ ...booking, status: input.status }));
|
|
}
|