@phenyxhealth/importer 1.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@phenyxhealth/importer",
3
+ "version": "1.1.7",
4
+ "type": "module",
5
+ "description": "Imports a Phenyx-compatible JSON file with patients into a PhenyxHealth instance.",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "main": "./src/index.js",
10
+ "bin": {
11
+ "importer": "./src/index.js"
12
+ },
13
+ "scripts": {
14
+ "dev": "node ./src/index.js test/importer-config.json"
15
+ },
16
+ "author": "Diego M. Béjar",
17
+ "license": "ISC",
18
+ "dependencies": {
19
+ "@dmbejar/json-files": "^1.1.6",
20
+ "uuid": "13.0.0"
21
+ }
22
+ }
@@ -0,0 +1,26 @@
1
+ import ApiInstance from "../services/phenyxApiInstance.js";
2
+
3
+ const beSureDoctorExists = async (toBe) => {
4
+ const currentDoctors = await ApiInstance.getHumanResources();
5
+
6
+ for (const doctor of toBe) {
7
+ const doctorName = doctor.name;
8
+ const doctorTypeId = ApiInstance.getGlobalInfoElementId(ApiInstance.globalTypes.humanResources, ApiInstance.globalTypes.humanResources.values[doctor.hrGroup]);
9
+ const doctorExists = !!currentDoctors
10
+ .find(item => item.name === doctorName && item.typeId === doctorTypeId);
11
+
12
+ if (!doctorExists) {
13
+ console.log(`Adding ${doctor.name}...`);
14
+ await ApiInstance.createHumanResource({
15
+ name: doctor.name,
16
+ typeId: doctorTypeId,
17
+ });
18
+ }
19
+ }
20
+
21
+ return await ApiInstance.getHumanResources();
22
+ };
23
+
24
+ export {
25
+ beSureDoctorExists,
26
+ };
@@ -0,0 +1,84 @@
1
+ import { v4 } from 'uuid';
2
+ import ApiInstance from '../services/phenyxApiInstance.js';
3
+ import { getContrastingColor } from '../utils/colors.js';
4
+
5
+ const checkGlobals = async (mustBe, extraValues = []) => {
6
+ const {
7
+ name,
8
+ values = {},
9
+ } = mustBe;
10
+
11
+ // Sacar los valores de global
12
+ const currentContent = ApiInstance.getGlobalInfo(mustBe);
13
+
14
+ if (!currentContent) throw new Error(`Global info ${name} not found`);
15
+
16
+ // Añadir los valores extra
17
+ for (const extraValue of extraValues) {
18
+ if (!values[extraValue]) {
19
+ values[extraValue] = extraValue;
20
+ }
21
+ }
22
+
23
+ // Asegurarnos que existen los tipos especificadas
24
+ const valuesToCheck = [];
25
+ for (const key of Object.keys(values)) {
26
+ valuesToCheck.push(values[key]);
27
+ }
28
+
29
+ // Meter la info
30
+ if (valuesToCheck.length) await beSureGlobalExists(currentContent, valuesToCheck);
31
+ };
32
+
33
+ const beSureGlobalExists = async (currentList, toBeList) => {
34
+ const {
35
+ id,
36
+ name,
37
+ elements,
38
+ } = currentList;
39
+
40
+ let listUpdated = false;
41
+
42
+ for (const element of currentList.elements) {
43
+ if (!element.modality) {
44
+ element.modality = '';
45
+ }
46
+ }
47
+
48
+ for (const item of toBeList) {
49
+ const element = elements.find(element => element.name === item && !element.isDeleted);
50
+
51
+ if (!element) {
52
+ console.log(`Adding ${item} to ${name}...`);
53
+ const creationDate = new Date().toISOString();
54
+ elements.push({
55
+ id: v4(),
56
+ color: getContrastingColor(),
57
+ name: item,
58
+ createdAt: creationDate,
59
+ updatedAt: creationDate,
60
+ isDeleted: false,
61
+ modality: '',
62
+ })
63
+ listUpdated = true;
64
+ continue;
65
+ }
66
+
67
+ if (!element.color) {
68
+ element.color = getContrastingColor();
69
+ element.updatedAt = new Date().toISOString();
70
+ listUpdated = true;
71
+ }
72
+
73
+ if(!element.modality) {
74
+ element.modality = '';
75
+ }
76
+ }
77
+
78
+ if (listUpdated) await ApiInstance.updateGlobalInfo(id, currentList);
79
+ };
80
+
81
+ export {
82
+ checkGlobals,
83
+ beSureGlobalExists,
84
+ };
@@ -0,0 +1,34 @@
1
+ import ApiInstance from '../services/phenyxApiInstance.js';
2
+
3
+ const beSureLinacsExists = async (toBe) => {
4
+ // Sacar todos los recursos
5
+ const resources = await ApiInstance.getResources();
6
+ // Sacar el typeId de LINAC
7
+ const linacsTypeId = (await ApiInstance.getResourcesTypes())
8
+ .find(type => type.name === 'LINAC')
9
+ .id;
10
+
11
+ // Sacar solo los LINACs
12
+ const existingLinacs = resources.filter(item => item.typeId === linacsTypeId);
13
+
14
+ // Crear los que falten
15
+ for (const linac of toBe) {
16
+ if (!existingLinacs.find(item => item.name === linac)) {
17
+ console.log(`Adding ${linac}...`);
18
+ await ApiInstance.createResource({
19
+ name: linac,
20
+ typeId: linacsTypeId,
21
+ });
22
+ }
23
+ }
24
+
25
+ const updatedLinacs = await ApiInstance.getResources();
26
+
27
+ const response = updatedLinacs.filter(item => item.typeId === linacsTypeId);
28
+
29
+ return response;
30
+ };
31
+
32
+ export {
33
+ beSureLinacsExists,
34
+ };
@@ -0,0 +1,15 @@
1
+ import ApiInstance from '../services/phenyxApiInstance.js';
2
+
3
+ const login = (config) => {
4
+ const {
5
+ apiUrl: apiHost,
6
+ apiUser: user,
7
+ apiPwd: password,
8
+ } = config;
9
+
10
+ return ApiInstance.login({ apiHost, user, password });
11
+ };
12
+
13
+ export {
14
+ login,
15
+ };
package/src/index.js ADDED
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env node
2
+
3
+ import path from "path";
4
+ import { loadJson } from "@dmbejar/json-files";
5
+ import { ask } from "./utils/ask.js";
6
+ import { clearPatients } from "./scripts/clearPatients.js";
7
+ import { importer } from "./scripts/importer.js";
8
+
9
+ const work = async () => {
10
+ const args = process.argv.slice(2);
11
+
12
+ if (args.length === 0) {
13
+ console.log('No se proporcionaron argumentos.');
14
+ console.log('Uso: npx @phenyxhealth/importer <archivo.json>');
15
+ return;
16
+ }
17
+
18
+ const configFileName = args[0];
19
+ const config = loadJson({ fileName: path.resolve(process.cwd(), configFileName) });
20
+
21
+ console.log('Leyendo configuración desde:', configFileName);
22
+
23
+ if (!config.ok) {
24
+ console.log(config.error);
25
+ return;
26
+ }
27
+
28
+ if (config.data.deleteExistingPatients) {
29
+ const verifyDelete = 'yes, delete all';
30
+
31
+ const deletePatients = await ask(`Want to delete all patients before importing? ¡This operation is irreversible! Write "${verifyDelete}" to confirm: `);
32
+
33
+ if (deletePatients.toLowerCase().trim() === verifyDelete) {
34
+ await clearPatients(config.data);
35
+ } else {
36
+ console.log('Skipping patients deletion');
37
+ }
38
+ }
39
+
40
+ const folder = configFileName.substring(0, configFileName.lastIndexOf('/'));
41
+
42
+ if(folder) process.chdir(folder);
43
+
44
+ await importer(config.data);
45
+ }
46
+
47
+ work();
@@ -0,0 +1,20 @@
1
+ import ApiInstance from '../services/phenyxApiInstance.js';
2
+ import { login } from '../controllers/login.js';
3
+
4
+ const clearPatients = async (config) => {
5
+ await login(config);
6
+
7
+ const allPatients = await ApiInstance.getPatients();
8
+ const allPatientsIds = allPatients.map(p => p.id);
9
+
10
+ for (const patientId of allPatientsIds) {
11
+ console.log(`Deleting patient ${patientId}`);
12
+ await ApiInstance.deletePatient(patientId);
13
+ }
14
+
15
+ console.log('All patients deleted');
16
+ };
17
+
18
+ export {
19
+ clearPatients,
20
+ }
@@ -0,0 +1,435 @@
1
+ import path from 'path';
2
+ import { loadJson } from '@dmbejar/json-files';
3
+ import ApiInstance from '../services/phenyxApiInstance.js';
4
+ import { login } from '../controllers/login.js';
5
+ import { lowerCaseList, getListFromColumn } from '../utils/text.js';
6
+ import { checkGlobals } from '../controllers/global.js';
7
+ import { beSureDoctorExists } from '../controllers/doctors.js';
8
+ import { today } from '../utils/dates.js';
9
+ import { beSureLinacsExists } from '../controllers/linacs.js';
10
+
11
+ const importer = async (config) => {
12
+ // Config
13
+ ApiInstance.showLogs(config.showLogs);
14
+
15
+ const {
16
+ inputFile,
17
+ } = config;
18
+
19
+ console.log(`Importing patients from "${inputFile}"...`);
20
+
21
+ const {
22
+ ok: loadOk,
23
+ error: patientsError,
24
+ data: patients,
25
+ } = loadJson({ fileName: path.resolve(process.cwd(), inputFile) });
26
+
27
+ if (!loadOk) {
28
+ console.error('Error loading input file:', patientsError);
29
+ return;
30
+ }
31
+
32
+ console.log('Verifying globals...');
33
+
34
+ await login(config);
35
+
36
+ // check globals
37
+ checkGlobals(ApiInstance.globalTypes.sendingDepartment, lowerCaseList(getListFromColumn(patients, 'sendingDepartment')));
38
+ checkGlobals(ApiInstance.globalTypes.cei9, getListFromColumn(patients, 'cei9'));
39
+ checkGlobals(ApiInstance.globalTypes.treatmentClass, lowerCaseList(getListFromColumn(patients, 'treatmentClass')));
40
+ checkGlobals(ApiInstance.globalTypes.treatmentSubClass, lowerCaseList(getListFromColumn(patients, 'treatmentSubClass')));
41
+ checkGlobals(ApiInstance.globalTypes.treatmentTechnique, getListFromColumn(patients, 'treatmentTechnique'));
42
+ checkGlobals(ApiInstance.globalTypes.ctSimProtocols, getListFromColumn(patients, 'simulationProtocol'));
43
+
44
+ // Dar de alta cada LINAC que no exista
45
+ const linacs = await beSureLinacsExists(getListFromColumn(patients, 'confirmedLinac'));
46
+
47
+ // Dar de alta cada médico que no exista
48
+ const radOncs = await beSureDoctorExists(getListFromColumn(patients, 'assignedRadOnc', 'peerReviewedDoctor'), ApiInstance.globalTypes.humanResources.values.RadOnc);
49
+ const medPhys = await beSureDoctorExists(getListFromColumn(patients, 'dosimetryMedPhys'), ApiInstance.globalTypes.humanResources.values.MedPhys);
50
+
51
+ // Verificar los defaults
52
+ const defaultCompatibleLinacs = ApiInstance.defaultCompatibleLinacs;
53
+
54
+ if (!defaultCompatibleLinacs.length) {
55
+ console.log('\n\nERROR: No default compatible linacs found');
56
+ return;
57
+ }
58
+
59
+ const defaultDuration = ApiInstance.defaultDuration;
60
+ if (!defaultDuration) {
61
+ console.log('\n\nERROR: No default duration found');
62
+ return;
63
+ }
64
+
65
+ // Los pacientes
66
+ const allPatients = await ApiInstance.getPatients();
67
+ const allPatientsIds = allPatients.map(p => p.patientId);
68
+
69
+ let contadorPacientes = 0;
70
+ const ignoredPatients = [];
71
+
72
+ console.log('Uploading patients...');
73
+
74
+ // Alta de los pacientes
75
+ for (const patientInfo of patients) {
76
+ const {
77
+ patientId,
78
+ registrationDate,
79
+ assignedRadOnc,
80
+ peerReviewedDoctor,
81
+ peerReviewedStatus,
82
+ sendingDepartment,
83
+ firstConsultDate,
84
+ cei9,
85
+ tnm,
86
+ stage,
87
+ treatmentClass,
88
+ treatmentSubClass,
89
+ treatmentTechnique,
90
+ sessionsCompleted,
91
+ sessionsTotal,
92
+ fractionationPattern,
93
+ ctAppDate,
94
+ notificationDate,
95
+ confirmedDate,
96
+ simulationProtocol,
97
+ qaCompletedDate,
98
+ confirmedLinac,
99
+ dosimetryMedPhys,
100
+ dosimetryQaInProgressDate,
101
+ dosimetryQaCompletedDate,
102
+ confirmedStartingDate,
103
+ treatmentStop,
104
+ linacAllocationCriteria,
105
+ sessionDurationCriteria,
106
+ groupRRHH,
107
+ patientName,
108
+ } = patientInfo;
109
+
110
+ if (allPatientsIds.includes(patientId)) {
111
+ console.log(`El paciente ${patientId} ya existe`);
112
+ ignoredPatients.push(patientId);
113
+ continue;
114
+ }
115
+
116
+ console.log('Procesando paciente:', patientId);
117
+
118
+ // Convertir ciertos datos
119
+ const sendingDepartmentId = ApiInstance.getSendingDepartmentIdByName(sendingDepartment);
120
+ const cei9Id = ApiInstance.getGlobalInfoElementId(ApiInstance.globalTypes.cei9, cei9);
121
+ const treatmentClassId = ApiInstance.getGlobalInfoElementId(ApiInstance.globalTypes.treatmentClass, treatmentClass);
122
+ const treatmentSubClassId = ApiInstance.getGlobalInfoElementId(ApiInstance.globalTypes.treatmentSubClass, treatmentSubClass);
123
+ const linacAllocationCriteriaId = ApiInstance.getGlobalInfoElementId(ApiInstance.globalTypes.linacsAllocationCriteria, linacAllocationCriteria || 'Default');
124
+ const confirmedLinacId = linacs.find(linac => linac.name === confirmedLinac)?.id || '';
125
+ const sessionDurationCriteriaId = ApiInstance.getGlobalInfoElementId(ApiInstance.globalTypes.sessionDurationCriteria, sessionDurationCriteria || 'Default');
126
+ const treatmentTechniqueId = ApiInstance.getGlobalInfoElementId(ApiInstance.globalTypes.treatmentTechnique, treatmentTechnique);
127
+ const simulationProtocolId = ApiInstance.getGlobalInfoElementId(ApiInstance.globalTypes.ctSimProtocols, simulationProtocol);
128
+ const dosimetryMedPhysId = medPhys.find(med => med.name === dosimetryMedPhys)?.id || '';
129
+ const pendingSessions = sessionsTotal - sessionsCompleted;
130
+ const peerReviewedDoctorId = radOncs.find(radOnc => radOnc.name === peerReviewedDoctor)?.id || '';
131
+
132
+ const peerReviewedData = ApiInstance.getRewiewedStatus(peerReviewedStatus);
133
+
134
+ // Crear el formData
135
+ const formData = {
136
+ registration: {
137
+ patientId: patientId.trim() || `IM-${(i + 1).toString().padStart(6, '0')}`,
138
+ registrationDate: registrationDate,
139
+ firstConsultProposal: firstConsultDate,
140
+ assignedRadOnc: assignedRadOnc,
141
+ sendingDepartment: sendingDepartmentId,
142
+ },
143
+ consultation: {
144
+ cei: cei9Id,
145
+ tnm: tnm,
146
+ estadio: stage,
147
+ treatmentClass: treatmentClassId,
148
+ treatmentSubClass: treatmentSubClassId,
149
+ earlierStartDate: "",
150
+ latestStartDate: "",
151
+ mandatoryStartDate: "",
152
+ priority: "",
153
+ shift: "Morning",
154
+ treatmentType: "",
155
+ treatmentGoal: "",
156
+ noTreatment: false,
157
+ why: "",
158
+ state: "NOT_STARTED",
159
+ compatibleLinacs: defaultCompatibleLinacs,
160
+ firstSesionDuration: defaultDuration.firstSession,
161
+ regularSesionDuration: defaultDuration.regularSessions,
162
+ linacAllocationCriteria: linacAllocationCriteriaId,
163
+ sessionDurationCriteria: sessionDurationCriteriaId,
164
+ treatmentParticle: "",
165
+ treatmentTechnique: treatmentTechniqueId,
166
+ numberOfFractions: sessionsTotal,
167
+ fractionation: "",
168
+ fractionPattern: fractionationPattern,
169
+ weeklySessions: "",
170
+ daysBetweenSessions: "",
171
+ comments: "",
172
+ ctSim: "",
173
+ ctApplicationDate: ctAppDate,
174
+ stateChanges: []
175
+ },
176
+ onHold: {
177
+ items: [
178
+ {
179
+ id: 1,
180
+ start: "",
181
+ end: "",
182
+ motivation: "",
183
+ comments: ""
184
+ }
185
+ ],
186
+ state: "NOT_STARTED",
187
+ stateChanges: []
188
+ },
189
+ treatmentSimulation: {
190
+ notificationDate: notificationDate,
191
+ confirmedDate: confirmedDate,
192
+ simulationProtocol: simulationProtocolId,
193
+ ctGuidelines: "",
194
+ comments: "",
195
+ state: "NOT_STARTED",
196
+ stateChanges: [],
197
+ atachedFiles: []
198
+ },
199
+ contouringOar: {
200
+ guidelines: "",
201
+ proposedRrhh: "",
202
+ rrhhId: "",
203
+ countouringTool: "",
204
+ oarTableId: "",
205
+ comments: "",
206
+ state: "NOT_STARTED",
207
+ stateChanges: []
208
+ },
209
+ contouringVolumes: {
210
+ guidelines: "",
211
+ proposedRrhh: "",
212
+ rrhhId: "",
213
+ countouringTool: "",
214
+ comments: "",
215
+ volumesDescription: [
216
+ {
217
+ id: 1,
218
+ name: "PTV1",
219
+ desc: "PTVASOC1"
220
+ }
221
+ ],
222
+ volumesDose: [
223
+ {
224
+ ptv: "PTV1",
225
+ ptvAsoc: "PTVASOC1",
226
+ total: "100",
227
+ dose: 100,
228
+ fracPattern: "CMD"
229
+ },
230
+ {
231
+ ptv: "PTV1",
232
+ ptvAsoc: "PTVASOC1",
233
+ total: "100",
234
+ dose: 100,
235
+ fracPattern: "CMD"
236
+ }
237
+ ],
238
+ state: "NOT_STARTED",
239
+ stateChanges: []
240
+ },
241
+ treatmentDefinition: {
242
+ compatibleLinacs: defaultCompatibleLinacs,
243
+ firstSesionDuration: defaultDuration.firstSession,
244
+ regularSesionDuration: defaultDuration.regularSessions,
245
+ linacAllocationCriteria: linacAllocationCriteriaId,
246
+ sessionDurationCriteria: sessionDurationCriteriaId,
247
+ treatmentParticle: "",
248
+ treatmentTechnique: treatmentTechniqueId,
249
+ numberOfFractions: sessionsTotal,
250
+ fractionation: "",
251
+ fractionPattern: fractionationPattern,
252
+ weeklySessions: "",
253
+ daysBetweenSessions: "",
254
+ comments: "",
255
+ peerReviewed: peerReviewedData,
256
+ oarAndPtvTables: [
257
+ {
258
+ ptv: "PTV1",
259
+ ptvasoc: "PTVASOC1"
260
+ },
261
+ {
262
+ ptv: "PTV1",
263
+ ptvasoc: "PTVASOC1"
264
+ }
265
+ ],
266
+ checkListPeerReview: {
267
+ targetVolumes: false,
268
+ oarVolumes: false,
269
+ targetDoses: false,
270
+ oarToleranceTables: false,
271
+ treatmentTechnique: false,
272
+ fractionation: false
273
+ },
274
+ state: "NOT_STARTED",
275
+ stateChanges: []
276
+ },
277
+ dosimetry: {
278
+ proposedLinac: confirmedLinacId,
279
+ confirmedLinac: confirmedLinacId,
280
+ groupRrhh: groupRRHH,
281
+ idRrhh: dosimetryMedPhysId,
282
+ calculationMethod: "",
283
+ typeOfPlanning: "",
284
+ tpsUsed: "",
285
+ secondGroupRrhh: "",
286
+ secondIdRrhh: "",
287
+ secondCalculationMethod: "",
288
+ dosimetryComplete: false,
289
+ planDefinitionComplete: false,
290
+ dosimetricReportComplete: false,
291
+ state: "NOT_STARTED",
292
+ stateChanges: [],
293
+ dosimetricReportFiles: [],
294
+ treatmentPlanFiles: []
295
+ },
296
+ treatmentVerification: {
297
+ description: "",
298
+ comments: "",
299
+ verificationProtocol: "",
300
+ state: "NOT_STARTED",
301
+ stateChanges: [],
302
+ verificationReportFiles: [],
303
+ uploadFiles: []
304
+ },
305
+ treatmentDelivery: {
306
+ numberOfFractions: sessionsTotal,
307
+ confirmedLinac: confirmedLinacId,
308
+ treatmentTechnique: treatmentTechniqueId,
309
+ tentativeTreatmentStart: "",
310
+ confirmedTreatmentStart: confirmedStartingDate,
311
+ numberOfCompleteSessions: sessionsCompleted,
312
+ numberOfPendingSessions: pendingSessions,
313
+ startAssignedShift: "",
314
+ startConfirmedStartDate: "",
315
+ startWeeklyAssignedDays: [],
316
+ interruptedEstimatedEndDate: "",
317
+ interruAssignedShift: "",
318
+ interruptedConfirmedStartDate: "",
319
+ interruptedMotivation: "",
320
+ canceledMotivation: "",
321
+ stateChanges: []
322
+ },
323
+ nursing: {
324
+ rows: [
325
+ {
326
+ namefield: "value",
327
+ namefield2: "value2",
328
+ namefield3: "value2",
329
+ namefield4: "value2",
330
+ namefield5: "value2",
331
+ namefield6: "value2"
332
+ },
333
+ {
334
+ namefield: "value",
335
+ namefield2: "value2",
336
+ namefield3: "value2",
337
+ namefield4: "value2",
338
+ namefield5: "value2",
339
+ namefield6: "value2"
340
+ }
341
+ ],
342
+ state: "NOT_STARTED",
343
+ stateChanges: []
344
+ }
345
+ }
346
+
347
+ // Guardar el paciente
348
+ const createdId = await ApiInstance.createPatient({ firstName: patientName.trim(), formData });
349
+
350
+ // Recuperar el cliente
351
+ const patient = await ApiInstance.getPatient(createdId);
352
+
353
+ // Ajustar estados
354
+ if (peerReviewedDoctorId) {
355
+ await ApiInstance.createPatientStateChanges({
356
+ formDataId: patient.formData.treatmentDefinition.id,
357
+ humanResourceId: peerReviewedDoctorId,
358
+ date: today(),
359
+ nextStateCode: 'PEER_REVIEWED',
360
+ });
361
+ }
362
+
363
+ if (qaCompletedDate) {
364
+ await ApiInstance.createPatientStateChanges({
365
+ formDataId: patient.formData.treatmentDefinition.id,
366
+ date: qaCompletedDate,
367
+ nextStateCode: 'COMPLETED',
368
+ });
369
+ }
370
+
371
+ if (dosimetryQaInProgressDate) {
372
+ await ApiInstance.createPatientStateChanges({
373
+ formDataId: patient.formData.dosimetry.id,
374
+ date: dosimetryQaInProgressDate,
375
+ nextStateCode: 'IN_PROGRESS',
376
+ });
377
+ }
378
+
379
+ if (dosimetryQaCompletedDate) {
380
+ await ApiInstance.createPatientStateChanges({
381
+ formDataId: patient.formData.dosimetry.id,
382
+ date: dosimetryQaCompletedDate,
383
+ nextStateCode: 'COMPLETED',
384
+ });
385
+ }
386
+
387
+ if (confirmedStartingDate && today() < confirmedStartingDate) {
388
+ await ApiInstance.createPatientStateChanges({
389
+ formDataId: patient.formData.treatmentDelivery.id,
390
+ date: confirmedStartingDate,
391
+ nextStateCode: 'START_CONFIRMED',
392
+ });
393
+ }
394
+
395
+ if (parseInt(sessionsCompleted)) {
396
+ await ApiInstance.createPatientStateChanges({
397
+ formDataId: patient.formData.treatmentDelivery.id,
398
+ date: confirmedStartingDate || today(),
399
+ nextStateCode: 'IN_PROGRESS',
400
+ });
401
+ }
402
+
403
+ if (treatmentStop.toUpperCase().startsWith('CANC')) {
404
+ await ApiInstance.createPatientStateChanges({
405
+ formDataId: patient.formData.treatmentDelivery.id,
406
+ date: today(),
407
+ nextStateCode: 'CANCELED',
408
+ });
409
+ }
410
+
411
+ if (treatmentStop.toUpperCase().startsWith('INT')) {
412
+ await ApiInstance.createPatientStateChanges({
413
+ formDataId: patient.formData.treatmentDelivery.id,
414
+ date: today(),
415
+ nextStateCode: 'INTERRUPTED',
416
+ });
417
+ }
418
+
419
+ if (!!sessionsCompleted && sessionsCompleted != 0 && sessionsCompleted === sessionsTotal) {
420
+ await ApiInstance.createPatientStateChanges({
421
+ formDataId: patient.formData.treatmentDelivery.id,
422
+ date: today(),
423
+ nextStateCode: 'COMPLETED',
424
+ });
425
+ }
426
+
427
+ contadorPacientes++;
428
+ }
429
+
430
+ if (ignoredPatients.length) console.error('\n\nLos siguientes pacientes no se han podido importar porque ya existían en el sistema:', ignoredPatients.join(', '));
431
+ };
432
+
433
+ export {
434
+ importer,
435
+ };