• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ULL-ESIT-INF-DSI-2526 / grp02-medcore-api-groupd / 25599028277

09 May 2026 10:36AM UTC coverage: 83.451% (+2.8%) from 80.693%
25599028277

push

github

web-flow
Merge pull request #4 from ULL-ESIT-INF-DSI-2526/models/records

Implement patient records interfaces and improve record handling

42 of 49 branches covered (85.71%)

Branch coverage included in aggregate %.

59 of 65 new or added lines in 4 files covered. (90.77%)

195 of 235 relevant lines covered (82.98%)

6.84 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.41
/src/controller/record/createRecord.controller.ts
1
import { Request, Response } from 'express';
2
import { Record } from '../../models/records/recordSchema.js';
3
import { Patient } from '../../models/patients/patientSchema.js';
4
import { Staff } from '../../models/staff/staffSchema.js';
5
import { Medication } from '../../models/medications/medicationSchema.js';
6
import { prescribedMed } from '../../models/records/prescibedMed.js';
7

8
interface medInfo {
9
  natCode: string;
10
  amount: number;
11
  instructions: string;
12
}
13

14
async function processMedication(medications: medInfo[]) {
15
  const processedMedications = [];
6✔
16
  const medsToSave = [];
6✔
17
  let totalCost = 0;
6✔
18

19
  for (const medication of medications) {
6✔
20
    const med = await Medication.findOne({ natCode: medication.natCode });
6✔
21
    if (!med) throw new Error(`NOT_FOUND_MED_${medication.natCode}`);
6✔
22

23
    if (med.expiration && new Date(med.expiration) < new Date()) {
5✔
24
      throw new Error(`EXPIRED_MED_${medication.natCode}`);
1✔
25
    }
26

27
    if (med.stock < medication.amount) {
4✔
28
      throw new Error(`INSUFFICIENT_STOCK_${medication.natCode}`);
1✔
29
    }
30

31
    totalCost += med.price * medication.amount;
3✔
32
    processedMedications.push({
3✔
33
      medication: med._id,
34
      amount: medication.amount,
35
      instructions: medication.instructions,
36
    });
37

38
    med.stock -= medication.amount;
3✔
39
    medsToSave.push(med);
3✔
40
  }
41

42
  for (const med of medsToSave) {
3✔
43
    await med.save();
3✔
44
  }
45

46
  return { processedMedications, totalCost };
3✔
47
}
48

49
export async function createRecord(req: Request, res: Response) {
50
  try {
11✔
51
    const patientDNI: string = req.body.idenNumber;
11✔
52
    const medNumber: number = req.body.medicalLicenseNumber;
11✔
53
    const medications: medInfo[] = req.body.medications;
11✔
54

55
    const patient = await Patient.findOne({ idenNumber: patientDNI });
11✔
56
    if (!patient) {
11✔
57
      return res.status(404).json({
1✔
58
        error: `El paciente con identificación ${patientDNI} no existe en la base de datos.`,
59
      });
60
    }
61

62
    if (patient.status === 'deceased') {
10✔
63
      return res.status(400).json({
1✔
64
        error: `El paciente con identificación ${patientDNI} está fallecido`,
65
      });
66
    }
67

68
    const doctor = await Staff.findOne({ medicalLicenseNumber: medNumber });
9✔
69
    if (!doctor) {
9✔
70
      return res.status(404).json({
1✔
71
        error: `El médico con número ${medNumber} no existe en la base de datos`,
72
      });
73
    }
74

75
    if (doctor.state === 'inactivo') {
8✔
76
      return res.status(400).json({
1✔
77
        error: `El médico con número ${medNumber} no se encuentra activo`,
78
      });
79
    }
80

81
    let finalMedications: prescribedMed[] = [];
7✔
82
    let finalCost = 0;
7✔
83
    if (medications && medications.length > 0) {
7✔
84
      const medResult = await processMedication(medications);
6✔
85
      finalMedications = medResult.processedMedications;
3✔
86
      finalCost = medResult.totalCost;
3✔
87
    }
88

89
    const newRecord = await Record.create({
4✔
90
      patient: patient._id,
91
      doctor: doctor._id,
92
      regType: req.body.regType,
93
      admissionReason: req.body.admissionReason,
94
      diagnosis: req.body.diagnosis,
95
      medicationList: finalMedications,
96
      totalPrice: finalCost,
97
    });
98

99
    return res.status(201).json(newRecord);
2✔
100
  } catch (error) {
101
    if (error instanceof Error) {
5✔
102
      if (error.message.startsWith('NOT_FOUND_MED_')) {
5✔
103
        return res.status(404).json({
1✔
104
          error: `Medication not found: ${error.message.split('NOT_FOUND_MED_')[1]}`,
105
        });
106
      } else if (error.message.startsWith('EXPIRED_MED_')) {
4✔
107
        return res.status(400).json({
1✔
108
          error: `Medication expired: ${error.message.split('EXPIRED_MED_')[1]}`,
109
        });
110
      } else if (error.message.startsWith('INSUFFICIENT_STOCK_')) {
3✔
111
        return res.status(400).json({
1✔
112
          error: `Insufficient stock for medication: ${error.message.split('INSUFFICIENT_STOCK_')[1]}`,
113
        });
114
      } else if (error.name === 'ValidationError') {
2✔
115
        return res.status(400).json({ error: error.message });
1✔
116
      } else {
117
        return res.status(500).json({ error: error.message });
1✔
118
      }
119
    } else {
NEW
120
      return res
×
121
        .status(500)
122
        .json({ error: 'Error interno del servidor desconocido' });
123
    }
124
  }
125
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc