api: fetch and create care actions/medicines
Pedro Lucas Porcellis porcellis@eletrotupi.com · 4 months ago
ce66d00c4b0f0549e45ca233432cd6098e28455c Browse filesParents
b4b8847Changed 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 +
};