import ScheduleVisitationRepository from '../../repository/admin/ScheduleVisitationRepository'; import { HttpException } from '../../utils/HttpException'; import { SearchFilter } from '../../utils/SearchFilter'; import { now } from '../../utils/TimeLocal'; import { createLog, updateLog, deleteLog } from '../../utils/LogActivity'; import prisma from '../../prisma/PrismaClient'; import { Prisma } from '@prisma/client'; import { CustomRequest } from '../../types/token/CustomRequest'; import { ScheduleVisitationRequestDTO } from '../../types/admin/schedule_visitation/ScheduleVisitationDTO'; import HospitalRepository from '../../repository/admin/HospitalRepository'; import { startOfMonth, endOfMonth, startOfDay, endOfDay } from "date-fns"; interface PaginationParams { page: number; limit: number; search?: string; sortBy: string; orderBy: 'asc' | 'desc'; province?: string; city?: string; date_visit?: Date; hospital?: string; sales?: string; } export const getAllScheduleVisitationService = async ({ page, limit, search, sortBy, orderBy, province, city, date_visit, hospital, sales }: PaginationParams) => { const skip = (page - 1) * limit; let dateFilter: Prisma.ScheduleVisitationWhereInput = {}; let dateStr: string | null = null; if (date_visit) { // Accept both Date and string dateStr = typeof date_visit === "string" ? date_visit : date_visit.toISOString().slice(0, 10); } else { const today = new Date(); dateStr = today.toISOString().slice(0, 7); // "YYYY-MM" } // Apply filter if (/^\d{4}-\d{2}$/.test(dateStr)) { // Format: YYYY-MM (month filter) const startDate = startOfMonth(new Date(`${dateStr}-01`)); const endDate = endOfMonth(startDate); dateFilter = { date_visit: { gte: startDate, lte: endDate, }, }; } else if (/^\d{4}-\d{2}-\d{2}$/.test(dateStr)) { // Format: YYYY-MM-DD (day filter) const startDate = startOfDay(new Date(dateStr)); const endDate = endOfDay(startDate); dateFilter = { date_visit: { gte: startDate, lte: endDate, }, }; } const where: Prisma.ScheduleVisitationWhereInput = { ...SearchFilter(search, ['hospital.name']), ...(province ? { province_id: province } : {}), ...(city ? { city_id: city } : {}), ...(sales ? { sales_visit: { id: sales } } : {}), ...dateFilter, deletedAt: null, }; const [scheduleVisitations, total] = await Promise.all([ ScheduleVisitationRepository.findAll({ skip, take: limit, where, orderBy: { [sortBy]: orderBy }, }), ScheduleVisitationRepository.countAll(where), ]); return { scheduleVisitations, total }; }; export const storeScheduleVisitationService = async (validateData: ScheduleVisitationRequestDTO, req: CustomRequest) => { const creatorId = req.tokenData.sub; const sales = await prisma.userKeycloak.findFirst({ where: { id: validateData.sales_id, } }); if (!sales) { throw new HttpException('Sales user not found', 404); } const hospital = await HospitalRepository.findById(validateData.hospital_id); if (!hospital) { throw new HttpException('Hospital not found', 404); } const provinceId = hospital.province?.id; const cityId = hospital.city?.id; if (!provinceId || !cityId) { throw new HttpException('Hospital does not have province or city assigned', 400); } const payload = { date_visit: new Date(validateData.date_visit), notes: validateData.notes ?? '', province_id: provinceId, city_id: cityId, hospital: { connect: { id: validateData.hospital_id } }, sales_visit: { connect: { id: validateData.sales_id } }, user_created: { connect: { id: creatorId } }, }; const data = await ScheduleVisitationRepository.create(payload); await createLog(req, data); }; export const showScheduleVisitationService = async (id: string) => { const schedule_visitation = await ScheduleVisitationRepository.findById(id); if (!schedule_visitation) { throw new HttpException('Data schedule visitation not found', 404); } return schedule_visitation; }; export const updateScheduleVisitationService = async (validateData: Partial, id: string, req: CustomRequest) => { const visitation = await ScheduleVisitationRepository.findById(id); if (!visitation) throw new HttpException("Schedule visitation not found", 404); const payload: Prisma.ScheduleVisitationUpdateInput = {}; if (validateData.date_visit) { payload.date_visit = new Date(validateData.date_visit); } if (typeof validateData.notes !== "undefined") { payload.notes = validateData.notes; } if (validateData.sales_id) { const sales = await prisma.userKeycloak.findFirst({ where: { id: validateData.sales_id } }); if (!sales) throw new HttpException("Sales user not found", 404); payload.sales_visit = { connect: { id: validateData.sales_id } }; } if (validateData.hospital_id) { const hospital = await HospitalRepository.findById(validateData.hospital_id); if (!hospital) throw new HttpException("Hospital not found", 404); const provinceId = hospital.province?.id; const cityId = hospital.city?.id; if (!provinceId || !cityId) { throw new HttpException("Hospital does not have province or city assigned", 400); } payload.hospital = { connect: { id: validateData.hospital_id } }; payload.province_id = provinceId; payload.city_id = cityId; } const data = await ScheduleVisitationRepository.update(id, payload); await updateLog(req, data); }; export const deleteScheduleVisitationService = async (id: string, req: CustomRequest) => { const schedule_visitation = await ScheduleVisitationRepository.findById(id); if (!schedule_visitation) throw new HttpException('Schedule visitation not found', 404); const data = await ScheduleVisitationRepository.update(id, { deletedAt: now().toDate() }); await deleteLog(req, data); };