eletrotupi / tcc/ commit / 2ab1b14

api: allow to disable a medicine regimen

Pedro Lucas Porcellis porcellis@eletrotupi.com 1 month ago 2ab1b144925b43a39d19edf4dbf40bf863addc7f
Parents: afb7b64
5 file(s) changed
  • api/src/controllers/medicineRegimens.ts +35 -0
  • api/src/routes/medicineRegimens.ts +2 -0
  • api/src/schemas/medicineRegimen.schema.ts +6 -0
  • api/src/services/careAction.service.ts +15 -0
  • api/src/services/medicineRegimen.service.ts +32 -0
api/src/controllers/medicineRegimens.ts
1 1
import { Response, NextFunction } from 'express';
2 2
import { AuthenticatedRequest } from '@app/middleware/auth';
3 3
import { CreateMedicineRegimenSchema, UpdateMedicineRegimenSchema } from '@app/schemas';
4 +
import { ToggleMedicineRegimenSchema } from '@app/schemas/medicineRegimen.schema';
4 5
import {
5 6
  getMedicineRegimensByUserId,
7 +
  getMedicineRegimenById,
6 8
  createMedicineRegimen,
7 9
  updateMedicineRegimen,
8 10
  deactivateMedicineRegimen,
9 11
  getTodayMedicineRegimens,
12 +
  toggleMedicineRegimen,
10 13
} from '@app/services/medicineRegimen.service';
11 14

12 15
export const MedicineRegimensController = {
13 16
  index: async (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
14 17
    try {
▸ 13 unchanged lines
28 31
    } catch (err) {
29 32
      next(err);
30 33
    }
31 34
  },
32 35

36 +
  show: async (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
37 +
    try {
38 +
      const regimen = await getMedicineRegimenById(req.userId!, Number(req.params.id));
39 +

40 +
      if (!regimen) return res.status(404).json({ error: 'Not found' });
41 +

42 +
      return res.status(200).json({ regimen });
43 +
    } catch (err) {
44 +
      next(err);
45 +
    }
46 +
  },
47 +

33 48
  create: async (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
34 49
    try {
35 50
      const parsed = CreateMedicineRegimenSchema.safeParse(req.body.regimen);
36 51

37 52
      if (!parsed.success) {
▸ 18 unchanged lines
56 71

57 72
      const regimen = await updateMedicineRegimen(
58 73
        req.userId!,
59 74
        Number(req.params.id),
60 75
        parsed.data,
76 +
      );
77 +

78 +
      return res.status(200).json({ regimen });
79 +
    } catch (err) {
80 +
      next(err);
81 +
    }
82 +
  },
83 +

84 +
  toggle: async (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
85 +
    try {
86 +
      const parsed = ToggleMedicineRegimenSchema.safeParse(req.body);
87 +

88 +
      if (!parsed.success) {
89 +
        return res.status(400).json({ errors: parsed.error!.issues });
90 +
      }
91 +

92 +
      const regimen = await toggleMedicineRegimen(
93 +
        req.userId!,
94 +
        Number(req.params.id),
95 +
        parsed.data.active,
61 96
      );
62 97

63 98
      return res.status(200).json({ regimen });
64 99
    } catch (err) {
65 100
      next(err);
▸ 8 unchanged lines
74 109
    } catch (err) {
75 110
      next(err);
76 111
    }
77 112
  },
78 113
};
api/src/routes/medicineRegimens.ts
1 1
import { Router } from 'express';
2 2
import { MedicineRegimensController } from '@app/controllers/medicineRegimens';
3 3
import { requireAuth } from '@app/middleware/auth';
4 4

5 5
const router = Router();
6 6

7 7
router.get('/', requireAuth, MedicineRegimensController.index);
8 8
router.get('/today', requireAuth, MedicineRegimensController.today);
9 9
router.post('/', requireAuth, MedicineRegimensController.create);
10 +
router.get('/:id', requireAuth, MedicineRegimensController.show);
11 +
router.patch('/:id/active', requireAuth, MedicineRegimensController.toggle);
10 12
router.patch('/:id', requireAuth, MedicineRegimensController.update);
11 13
router.delete('/:id', requireAuth, MedicineRegimensController.destroy);
12 14

13 15
export default router;
api/src/schemas/medicineRegimen.schema.ts
1 1
import { z } from 'zod';
2 2
import { MedicinePeriodicity } from '@prisma/client';
3 3

4 4
export const CreateMedicineRegimenSchema = z.object({
5 5
  name: z.string().min(1),
▸ 11 unchanged lines
17 17
  scheduledAt: z.array(z.string()).optional().default([]),
18 18
  active: z.boolean().optional(),
19 19
});
20 20

21 21
export type UpdateMedicineRegimenInput = z.infer<typeof UpdateMedicineRegimenSchema>;
22 +

23 +
export const ToggleMedicineRegimenSchema = z.object({
24 +
  active: z.boolean(),
25 +
});
26 +

27 +
export type ToggleMedicineRegimenInput = z.infer<typeof ToggleMedicineRegimenSchema>;
api/src/services/careAction.service.ts
1 1
import { prisma } from '@app/lib/prisma';
2 2
import { CareAction, CareActionType } from '@prisma/client';
3 3
import { CreateCareActionInput, PatchCareActionInput } from '@app/schemas';
4 +
import { syncMedicineReminderJobs } from '@app/services/medicineReminder.sync';
4 5

5 6
const careActionIncludes = {
6 7
  medicineLog: { include: { regimen: true } },
7 8
  appointment: true,
8 9
  activity: true,
▸ 32 unchanged lines
41 42
      include: careActionIncludes,
42 43
      orderBy: { moment: 'desc' },
43 44
      take: limit,
44 45
      skip,
45 46
    }),
47 +

46 48
    prisma.careAction.count({ where }),
47 49
  ]);
48 50

49 51
  const totalPages = Math.ceil(total / limit);
50 52

▸ 38 unchanged lines
89 91
  input: CreateCareActionInput,
90 92
) => {
91 93
  if (input.type === CareActionType.MEDICINE) {
92 94
    if (input.regimenId) {
93 95
      const regimenId = input.regimenId;
96 +

94 97
      const [careAction] = await prisma.$transaction([
95 98
        prisma.careAction.create({
96 99
          data: {
97 100
            userId,
98 101
            type: input.type,
▸ 5 unchanged lines
104 107
            },
105 108
          },
106 109
          include: careActionIncludes,
107 110
        }),
108 111
      ]);
112 +

109 113
      return careAction;
110 114
    }
111 115

112 116
    if (input.medicine) {
113 117
      const med = input.medicine;
118 +

114 119
      const [careAction] = await prisma.$transaction([
115 120
        prisma.careAction.create({
116 121
          data: {
117 122
            userId,
118 123
            type: input.type,
▸ 15 unchanged lines
134 139
            },
135 140
          },
136 141
          include: careActionIncludes,
137 142
        }),
138 143
      ]);
144 +

145 +
      if (careAction.medicineLog?.regimen) {
146 +
        await syncMedicineReminderJobs(careAction.medicineLog.regimen as any);
147 +
      }
148 +

139 149
      return careAction;
140 150
    }
141 151

142 152
    // MEDICINE with no regimen info: create action without log
143 153
    const [careAction] = await prisma.$transaction([
▸ 6 unchanged lines
150 160
          moodId: input.moodId,
151 161
        },
152 162
        include: careActionIncludes,
153 163
      }),
154 164
    ]);
165 +

155 166
    return careAction;
156 167
  }
157 168

158 169
  if (input.type === CareActionType.APPOINTMENT && input.appointment) {
159 170
    const appt = input.appointment;
171 +

160 172
    const [careAction] = await prisma.$transaction([
161 173
      prisma.careAction.create({
162 174
        data: {
163 175
          userId,
164 176
          type: input.type,
▸ 9 unchanged lines
174 186
          },
175 187
        },
176 188
        include: careActionIncludes,
177 189
      }),
178 190
    ]);
191 +

179 192
    return careAction;
180 193
  }
181 194

182 195
  if (input.type === CareActionType.ACTIVITY && input.activity) {
183 196
    const act = input.activity;
197 +

184 198
    const [careAction] = await prisma.$transaction([
185 199
      prisma.careAction.create({
186 200
        data: {
187 201
          userId,
188 202
          type: input.type,
▸ 8 unchanged lines
197 211
          },
198 212
        },
199 213
        include: careActionIncludes,
200 214
      }),
201 215
    ]);
216 +

202 217
    return careAction;
203 218
  }
204 219

205 220
  // Fallback: create without subtype
206 221
  return prisma.careAction.create({
▸ 5 unchanged lines
212 227
      moodId: input.moodId,
213 228
    },
214 229
    include: careActionIncludes,
215 230
  });
216 231
};
api/src/services/medicineRegimen.service.ts
1 1
import { prisma } from '@app/lib/prisma';
2 2
import { MedicineRegimen } from '@prisma/client';
3 3
import { CreateMedicineRegimenInput, UpdateMedicineRegimenInput } from '@app/schemas';
4 4
import { syncMedicineReminderJobs } from '@app/services/medicineReminder.sync';
5 5

6 +
export const toggleMedicineRegimen = async (
7 +
  userId: number,
8 +
  id: number,
9 +
  active: boolean,
10 +
): Promise<MedicineRegimen> => {
11 +
  const regimen = await prisma.medicineRegimen.update({
12 +
    where: { id, userId },
13 +
    data: { active },
14 +
  });
15 +

16 +
  await syncMedicineReminderJobs(regimen);
17 +

18 +
  return regimen;
19 +
};
20 +

6 21
type TodayEntry = {
7 22
  regimen: Pick<MedicineRegimen, 'id' | 'name' | 'dosage' | 'scheduledAt'>;
8 23
  logs: { id: number; takenAt: Date }[];
9 24
};
10 25

26 +
export const getMedicineRegimenById = async (
27 +
  userId: number,
28 +
  id: number,
29 +
): Promise<MedicineRegimen | null> => {
30 +
  return prisma.medicineRegimen.findUnique({
31 +
    where: { id, userId },
32 +
  });
33 +
};
34 +

11 35
export const getMedicineRegimensByUserId = async (
12 36
  userId: number,
13 37
): Promise<MedicineRegimen[]> => {
14 38
  return prisma.medicineRegimen.findMany({
15 39
    where: { userId },
▸ 6 unchanged lines
22 46
  input: CreateMedicineRegimenInput,
23 47
): Promise<MedicineRegimen> => {
24 48
  const regimen = await prisma.medicineRegimen.create({
25 49
    data: { ...input, userId },
26 50
  });
51 +

27 52
  await syncMedicineReminderJobs(regimen);
53 +

28 54
  return regimen;
29 55
};
30 56

31 57
export const updateMedicineRegimen = async (
32 58
  userId: number,
▸ 2 unchanged lines
35 61
): Promise<MedicineRegimen> => {
36 62
  const regimen = await prisma.medicineRegimen.update({
37 63
    where: { id, userId },
38 64
    data: input,
39 65
  });
66 +

40 67
  await syncMedicineReminderJobs(regimen);
68 +

41 69
  return regimen;
42 70
};
43 71

44 72
export const getTodayMedicineRegimens = async (
45 73
  userId: number,
46 74
): Promise<TodayEntry[]> => {
47 75
  const now = new Date();
76 +

48 77
  const startOfDay = new Date(now);
49 78
  startOfDay.setUTCHours(0, 0, 0, 0);
79 +

50 80
  const endOfDay = new Date(now);
51 81
  endOfDay.setUTCHours(23, 59, 59, 999);
52 82

53 83
  const regimens = await prisma.medicineRegimen.findMany({
54 84
    where: { userId, active: true },
▸ 21 unchanged lines
76 106
): Promise<MedicineRegimen> => {
77 107
  const regimen = await prisma.medicineRegimen.update({
78 108
    where: { id, userId },
79 109
    data: { active: false },
80 110
  });
111 +

81 112
  await syncMedicineReminderJobs(regimen);
113 +

82 114
  return regimen;
83 115
};