eletrotupi / tcc/ commit / ce66d00

api: fetch and create care actions/medicines

Pedro Lucas Porcellis porcellis@eletrotupi.com · 4 months ago ce66d00c4b0f0549e45ca233432cd6098e28455c Browse files
Parents b4b8847
Changed files
6
Additions
+411
Deletions
0
/dev/null → api/src/controllers/careActions.ts
1 +
import { Response, NextFunction } from 'express';
2 +
import { AuthenticatedRequest } from '@app/middleware/auth';
3 +
import { CareActionType } from '@prisma/client';
4 +
import { CreateCareActionSchema } from '@app/schemas';
5 +
import {
6 +
  getCareActionsByUserId,
7 +
  getCareActionById,
8 +
  createCareAction,
9 +
  destroyCareActionById,
10 +
} from '@app/services/careAction.service';
11 +

12 +
export const CareActionsController = {
13 +
  index: async (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
14 +
    try {
15 +
      const result = await getCareActionsByUserId(Number(req.userId), {
16 +
        type: req.query.type as CareActionType | undefined,
17 +
        from: req.query.from as string | undefined,
18 +
        to: req.query.to as string | undefined,
19 +
        limit: req.query.limit ? Number(req.query.limit) : undefined,
20 +
        page: req.query.page ? Number(req.query.page) : undefined,
21 +
      });
22 +

23 +
      return res.status(200).json(result);
24 +
    } catch (err) {
25 +
      next(err);
26 +
    }
27 +
  },
28 +

29 +
  show: async (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
30 +
    try {
31 +
      const careAction = await getCareActionById(
32 +
        Number(req.userId),
33 +
        Number(req.params.id),
34 +
      );
35 +

36 +
      if (!careAction) {
37 +
        return res.status(404).json({ errors: 'Care action was not found' });
38 +
      }
39 +

40 +
      return res.status(200).json({ careAction });
41 +
    } catch (err) {
42 +
      next(err);
43 +
    }
44 +
  },
45 +

46 +
  create: async (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
47 +
    try {
48 +
      const parsed = CreateCareActionSchema.safeParse(req.body.careAction);
49 +

50 +
      req.log.info("Params: %s", req.body.careAction)
51 +
      req.log.info("Care action: %s", parsed.error)
52 +

53 +
      if (!parsed.success) {
54 +
        return res.status(400).json({ errors: parsed.error!.issues });
55 +
      }
56 +

57 +
      const careAction = await createCareAction(req.userId!, parsed.data);
58 +

59 +
      return res.status(201).json({ careAction });
60 +
    } catch (err) {
61 +
      next(err);
62 +
    }
63 +
  },
64 +

65 +
  destroy: async (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
66 +
    try {
67 +
      await destroyCareActionById(req.userId!, Number(req.params.id));
68 +

69 +
      return res.status(200).json({});
70 +
    } catch (err) {
71 +
      next(err);
72 +
    }
73 +
  },
74 +
};
/dev/null → api/src/controllers/medicineRegimens.ts
1 +
import { Response, NextFunction } from 'express';
2 +
import { AuthenticatedRequest } from '@app/middleware/auth';
3 +
import { CreateMedicineRegimenSchema, UpdateMedicineRegimenSchema } from '@app/schemas';
4 +
import {
5 +
  getMedicineRegimensByUserId,
6 +
  createMedicineRegimen,
7 +
  updateMedicineRegimen,
8 +
  deactivateMedicineRegimen,
9 +
} from '@app/services/medicineRegimen.service';
10 +

11 +
export const MedicineRegimensController = {
12 +
  index: async (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
13 +
    try {
14 +
      const regimens = await getMedicineRegimensByUserId(Number(req.userId));
15 +

16 +
      return res.status(200).json({ regimens });
17 +
    } catch (err) {
18 +
      next(err);
19 +
    }
20 +
  },
21 +

22 +
  create: async (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
23 +
    try {
24 +
      const parsed = CreateMedicineRegimenSchema.safeParse(req.body.regimen);
25 +

26 +
      if (!parsed.success) {
27 +
        return res.status(400).json({ errors: parsed.error!.issues });
28 +
      }
29 +

30 +
      const regimen = await createMedicineRegimen(req.userId!, parsed.data);
31 +

32 +
      return res.status(201).json({ regimen });
33 +
    } catch (err) {
34 +
      next(err);
35 +
    }
36 +
  },
37 +

38 +
  update: async (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
39 +
    try {
40 +
      const parsed = UpdateMedicineRegimenSchema.safeParse(req.body.regimen);
41 +

42 +
      if (!parsed.success) {
43 +
        return res.status(400).json({ errors: parsed.error!.issues });
44 +
      }
45 +

46 +
      const regimen = await updateMedicineRegimen(
47 +
        req.userId!,
48 +
        Number(req.params.id),
49 +
        parsed.data,
50 +
      );
51 +

52 +
      return res.status(200).json({ regimen });
53 +
    } catch (err) {
54 +
      next(err);
55 +
    }
56 +
  },
57 +

58 +
  destroy: async (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
59 +
    try {
60 +
      await deactivateMedicineRegimen(req.userId!, Number(req.params.id));
61 +

62 +
      return res.status(200).json({});
63 +
    } catch (err) {
64 +
      next(err);
65 +
    }
66 +
  },
67 +
};
/dev/null → api/src/routes/careActions.ts
1 +
import { Router } from 'express';
2 +
import { CareActionsController } from '@app/controllers/careActions';
3 +
import { requireAuth } from '@app/middleware/auth';
4 +

5 +
const router = Router();
6 +

7 +
router.get('/', requireAuth, CareActionsController.index);
8 +
router.post('/', requireAuth, CareActionsController.create);
9 +
router.get('/:id', requireAuth, CareActionsController.show);
10 +
router.delete('/:id', requireAuth, CareActionsController.destroy);
11 +

12 +
export default router;
/dev/null → api/src/routes/medicineRegimens.ts
1 +
import { Router } from 'express';
2 +
import { MedicineRegimensController } from '@app/controllers/medicineRegimens';
3 +
import { requireAuth } from '@app/middleware/auth';
4 +

5 +
const router = Router();
6 +

7 +
router.get('/', requireAuth, MedicineRegimensController.index);
8 +
router.post('/', requireAuth, MedicineRegimensController.create);
9 +
router.patch('/:id', requireAuth, MedicineRegimensController.update);
10 +
router.delete('/:id', requireAuth, MedicineRegimensController.destroy);
11 +

12 +
export default router;
/dev/null → api/src/services/careAction.service.ts
1 +
import { prisma } from '@app/lib/prisma';
2 +
import { CareAction, CareActionType } from '@prisma/client';
3 +
import { CreateCareActionInput } from '@app/schemas';
4 +

5 +
const careActionIncludes = {
6 +
  medicineLog: { include: { regimen: true } },
7 +
  appointment: true,
8 +
  activity: true,
9 +
} as const;
10 +

11 +
export const getCareActionsByUserId = async (
12 +
  userId: number,
13 +
  params?: {
14 +
    type?: CareActionType;
15 +
    from?: string;
16 +
    to?: string;
17 +
    page?: number;
18 +
    limit?: number;
19 +
  },
20 +
) => {
21 +
  const page = params?.page ?? 1;
22 +
  const limit = params?.limit ?? 20;
23 +
  const skip = (page - 1) * limit;
24 +

25 +
  const where = {
26 +
    userId,
27 +
    ...(params?.type ? { type: params.type } : {}),
28 +
    ...(params?.from || params?.to
29 +
      ? {
30 +
          moment: {
31 +
            ...(params?.from && { gte: new Date(params.from) }),
32 +
            ...(params?.to && { lte: new Date(params.to) }),
33 +
          },
34 +
        }
35 +
      : {}),
36 +
  };
37 +

38 +
  const [entries, total] = await Promise.all([
39 +
    prisma.careAction.findMany({
40 +
      where,
41 +
      include: careActionIncludes,
42 +
      orderBy: { moment: 'desc' },
43 +
      take: limit,
44 +
      skip,
45 +
    }),
46 +
    prisma.careAction.count({ where }),
47 +
  ]);
48 +

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

51 +
  return {
52 +
    entries,
53 +
    total,
54 +
    page,
55 +
    nextPage: page < totalPages ? page + 1 : null,
56 +
  };
57 +
};
58 +

59 +
export const getCareActionById = async (userId: number, id: number) => {
60 +
  return prisma.careAction.findUnique({
61 +
    where: { id, userId },
62 +
    include: careActionIncludes,
63 +
  });
64 +
};
65 +

66 +
export const destroyCareActionById = async (
67 +
  userId: number,
68 +
  id: number,
69 +
): Promise<CareAction> => {
70 +
  return prisma.careAction.delete({
71 +
    where: { id, userId },
72 +
  });
73 +
};
74 +

75 +
export const createCareAction = async (
76 +
  userId: number,
77 +
  input: CreateCareActionInput,
78 +
) => {
79 +
  if (input.type === CareActionType.MEDICINE) {
80 +
    if (input.regimenId) {
81 +
      const regimenId = input.regimenId;
82 +
      const [careAction] = await prisma.$transaction([
83 +
        prisma.careAction.create({
84 +
          data: {
85 +
            userId,
86 +
            type: input.type,
87 +
            moment: input.moment,
88 +
            triggerId: input.triggerId,
89 +
            moodId: input.moodId,
90 +
            medicineLog: {
91 +
              create: { regimenId },
92 +
            },
93 +
          },
94 +
          include: careActionIncludes,
95 +
        }),
96 +
      ]);
97 +
      return careAction;
98 +
    }
99 +

100 +
    if (input.medicine) {
101 +
      const med = input.medicine;
102 +
      const [careAction] = await prisma.$transaction([
103 +
        prisma.careAction.create({
104 +
          data: {
105 +
            userId,
106 +
            type: input.type,
107 +
            moment: input.moment,
108 +
            triggerId: input.triggerId,
109 +
            moodId: input.moodId,
110 +
            medicineLog: {
111 +
              create: {
112 +
                regimen: {
113 +
                  create: {
114 +
                    name: med.name,
115 +
                    dosage: med.dosage,
116 +
                    periodicity: med.periodicity,
117 +
                    scheduledAt: med.scheduledAt,
118 +
                    userId,
119 +
                  },
120 +
                },
121 +
              },
122 +
            },
123 +
          },
124 +
          include: careActionIncludes,
125 +
        }),
126 +
      ]);
127 +
      return careAction;
128 +
    }
129 +

130 +
    // MEDICINE with no regimen info: create action without log
131 +
    const [careAction] = await prisma.$transaction([
132 +
      prisma.careAction.create({
133 +
        data: {
134 +
          userId,
135 +
          type: input.type,
136 +
          moment: input.moment,
137 +
          triggerId: input.triggerId,
138 +
          moodId: input.moodId,
139 +
        },
140 +
        include: careActionIncludes,
141 +
      }),
142 +
    ]);
143 +
    return careAction;
144 +
  }
145 +

146 +
  if (input.type === CareActionType.APPOINTMENT && input.appointment) {
147 +
    const appt = input.appointment;
148 +
    const [careAction] = await prisma.$transaction([
149 +
      prisma.careAction.create({
150 +
        data: {
151 +
          userId,
152 +
          type: input.type,
153 +
          moment: input.moment,
154 +
          triggerId: input.triggerId,
155 +
          moodId: input.moodId,
156 +
          appointment: {
157 +
            create: {
158 +
              type: appt.type,
159 +
              duration: appt.duration,
160 +
              note: appt.note,
161 +
            },
162 +
          },
163 +
        },
164 +
        include: careActionIncludes,
165 +
      }),
166 +
    ]);
167 +
    return careAction;
168 +
  }
169 +

170 +
  if (input.type === CareActionType.ACTIVITY && input.activity) {
171 +
    const act = input.activity;
172 +
    const [careAction] = await prisma.$transaction([
173 +
      prisma.careAction.create({
174 +
        data: {
175 +
          userId,
176 +
          type: input.type,
177 +
          moment: input.moment,
178 +
          triggerId: input.triggerId,
179 +
          moodId: input.moodId,
180 +
          activity: {
181 +
            create: {
182 +
              type: act.type,
183 +
              duration: act.duration,
184 +
            },
185 +
          },
186 +
        },
187 +
        include: careActionIncludes,
188 +
      }),
189 +
    ]);
190 +
    return careAction;
191 +
  }
192 +

193 +
  // Fallback: create without subtype
194 +
  return prisma.careAction.create({
195 +
    data: {
196 +
      userId,
197 +
      type: input.type,
198 +
      moment: input.moment,
199 +
      triggerId: input.triggerId,
200 +
      moodId: input.moodId,
201 +
    },
202 +
    include: careActionIncludes,
203 +
  });
204 +
};
/dev/null → api/src/services/medicineRegimen.service.ts
1 +
import { prisma } from '@app/lib/prisma';
2 +
import { MedicineRegimen } from '@prisma/client';
3 +
import { CreateMedicineRegimenInput, UpdateMedicineRegimenInput } from '@app/schemas';
4 +

5 +
export const getMedicineRegimensByUserId = async (
6 +
  userId: number,
7 +
): Promise<MedicineRegimen[]> => {
8 +
  return prisma.medicineRegimen.findMany({
9 +
    where: { userId, active: true },
10 +
    orderBy: { createdAt: 'desc' },
11 +
  });
12 +
};
13 +

14 +
export const createMedicineRegimen = async (
15 +
  userId: number,
16 +
  input: CreateMedicineRegimenInput,
17 +
): Promise<MedicineRegimen> => {
18 +
  return prisma.medicineRegimen.create({
19 +
    data: { ...input, userId },
20 +
  });
21 +
};
22 +

23 +
export const updateMedicineRegimen = async (
24 +
  userId: number,
25 +
  id: number,
26 +
  input: UpdateMedicineRegimenInput,
27 +
): Promise<MedicineRegimen> => {
28 +
  return prisma.medicineRegimen.update({
29 +
    where: { id, userId },
30 +
    data: input,
31 +
  });
32 +
};
33 +

34 +
export const deactivateMedicineRegimen = async (
35 +
  userId: number,
36 +
  id: number,
37 +
): Promise<MedicineRegimen> => {
38 +
  return prisma.medicineRegimen.update({
39 +
    where: { id, userId },
40 +
    data: { active: false },
41 +
  });
42 +
};