ScheduleVisitationService.ts 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. import ScheduleVisitationRepository from '../../repository/admin/ScheduleVisitationRepository';
  2. import { HttpException } from '../../utils/HttpException';
  3. import { SearchFilter } from '../../utils/SearchFilter';
  4. import { now } from '../../utils/TimeLocal';
  5. import { createLog, updateLog, deleteLog } from '../../utils/LogActivity';
  6. import prisma from '../../prisma/PrismaClient';
  7. import { Prisma } from '@prisma/client';
  8. import { CustomRequest } from '../../types/token/CustomRequest';
  9. import { ScheduleVisitationRequestDTO } from '../../types/admin/schedule_visitation/ScheduleVisitationDTO';
  10. import HospitalRepository from '../../repository/admin/HospitalRepository';
  11. import { startOfMonth, endOfMonth, startOfDay, endOfDay } from "date-fns";
  12. interface PaginationParams {
  13. page: number;
  14. limit: number;
  15. search?: string;
  16. sortBy: string;
  17. orderBy: 'asc' | 'desc';
  18. province?: string;
  19. city?: string;
  20. date_visit?: Date;
  21. hospital?: string;
  22. sales?: string;
  23. }
  24. export const getAllScheduleVisitationService = async ({ page, limit, search, sortBy, orderBy, province, city, date_visit, hospital, sales }: PaginationParams) => {
  25. const skip = (page - 1) * limit;
  26. let dateFilter: Prisma.ScheduleVisitationWhereInput = {};
  27. let dateStr: string | null = null;
  28. if (date_visit) {
  29. // Accept both Date and string
  30. dateStr = typeof date_visit === "string"
  31. ? date_visit
  32. : date_visit.toISOString().slice(0, 10);
  33. } else {
  34. const today = new Date();
  35. dateStr = today.toISOString().slice(0, 7); // "YYYY-MM"
  36. }
  37. // Apply filter
  38. if (/^\d{4}-\d{2}$/.test(dateStr)) {
  39. // Format: YYYY-MM (month filter)
  40. const startDate = startOfMonth(new Date(`${dateStr}-01`));
  41. const endDate = endOfMonth(startDate);
  42. dateFilter = {
  43. date_visit: {
  44. gte: startDate,
  45. lte: endDate,
  46. },
  47. };
  48. } else if (/^\d{4}-\d{2}-\d{2}$/.test(dateStr)) {
  49. // Format: YYYY-MM-DD (day filter)
  50. const startDate = startOfDay(new Date(dateStr));
  51. const endDate = endOfDay(startDate);
  52. dateFilter = {
  53. date_visit: {
  54. gte: startDate,
  55. lte: endDate,
  56. },
  57. };
  58. }
  59. const where: Prisma.ScheduleVisitationWhereInput = {
  60. ...SearchFilter(search, ['hospital.name']),
  61. ...(province ? { province_id: province } : {}),
  62. ...(city ? { city_id: city } : {}),
  63. ...(sales ? { sales_visit: { id: sales } } : {}),
  64. ...dateFilter,
  65. deletedAt: null,
  66. };
  67. const [scheduleVisitations, total] = await Promise.all([
  68. ScheduleVisitationRepository.findAll({
  69. skip,
  70. take: limit,
  71. where,
  72. orderBy: { [sortBy]: orderBy },
  73. }),
  74. ScheduleVisitationRepository.countAll(where),
  75. ]);
  76. return { scheduleVisitations, total };
  77. };
  78. export const storeScheduleVisitationService = async (validateData: ScheduleVisitationRequestDTO, req: CustomRequest) => {
  79. const creatorId = req.tokenData.sub;
  80. const sales = await prisma.userKeycloak.findFirst({
  81. where: {
  82. id: validateData.sales_id,
  83. }
  84. });
  85. if (!sales) {
  86. throw new HttpException('Sales user not found', 404);
  87. }
  88. const hospital = await HospitalRepository.findById(validateData.hospital_id);
  89. if (!hospital) {
  90. throw new HttpException('Hospital not found', 404);
  91. }
  92. const provinceId = hospital.province?.id;
  93. const cityId = hospital.city?.id;
  94. if (!provinceId || !cityId) {
  95. throw new HttpException('Hospital does not have province or city assigned', 400);
  96. }
  97. const payload = {
  98. date_visit: new Date(validateData.date_visit),
  99. notes: validateData.notes ?? '',
  100. province_id: provinceId,
  101. city_id: cityId,
  102. hospital: { connect: { id: validateData.hospital_id } },
  103. sales_visit: { connect: { id: validateData.sales_id } },
  104. user_created: { connect: { id: creatorId } },
  105. };
  106. const data = await ScheduleVisitationRepository.create(payload);
  107. await createLog(req, data);
  108. };
  109. export const showScheduleVisitationService = async (id: string) => {
  110. const schedule_visitation = await ScheduleVisitationRepository.findById(id);
  111. if (!schedule_visitation) {
  112. throw new HttpException('Data schedule visitation not found', 404);
  113. }
  114. return schedule_visitation;
  115. };
  116. export const updateScheduleVisitationService = async (validateData: Partial<ScheduleVisitationRequestDTO>, id: string, req: CustomRequest) => {
  117. const visitation = await ScheduleVisitationRepository.findById(id);
  118. if (!visitation) throw new HttpException("Schedule visitation not found", 404);
  119. const payload: Prisma.ScheduleVisitationUpdateInput = {};
  120. if (validateData.date_visit) {
  121. payload.date_visit = new Date(validateData.date_visit);
  122. }
  123. if (typeof validateData.notes !== "undefined") {
  124. payload.notes = validateData.notes;
  125. }
  126. if (validateData.sales_id) {
  127. const sales = await prisma.userKeycloak.findFirst({ where: { id: validateData.sales_id } });
  128. if (!sales) throw new HttpException("Sales user not found", 404);
  129. payload.sales_visit = { connect: { id: validateData.sales_id } };
  130. }
  131. if (validateData.hospital_id) {
  132. const hospital = await HospitalRepository.findById(validateData.hospital_id);
  133. if (!hospital) throw new HttpException("Hospital not found", 404);
  134. const provinceId = hospital.province?.id;
  135. const cityId = hospital.city?.id;
  136. if (!provinceId || !cityId) {
  137. throw new HttpException("Hospital does not have province or city assigned", 400);
  138. }
  139. payload.hospital = { connect: { id: validateData.hospital_id } };
  140. payload.province_id = provinceId;
  141. payload.city_id = cityId;
  142. }
  143. const data = await ScheduleVisitationRepository.update(id, payload);
  144. await updateLog(req, data);
  145. };
  146. export const deleteScheduleVisitationService = async (id: string, req: CustomRequest) => {
  147. const schedule_visitation = await ScheduleVisitationRepository.findById(id);
  148. if (!schedule_visitation) throw new HttpException('Schedule visitation not found', 404);
  149. const data = await ScheduleVisitationRepository.update(id, {
  150. deletedAt: now().toDate()
  151. });
  152. await deleteLog(req, data);
  153. };