@andes/fhir 1.11.1 → 1.12.0-beta.2

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.
Files changed (94) hide show
  1. package/.circleci/config.yml +71 -68
  2. package/.editorconfig +13 -13
  3. package/.env.example +2 -0
  4. package/.github/labeler.yml +10 -10
  5. package/.github/pull_request_template.md +28 -28
  6. package/.github/workflows/build_test.yml +14 -14
  7. package/.github/workflows/has_conflicts.yml +13 -13
  8. package/.vscode/settings.json +2 -0
  9. package/CHANGELOG.md +312 -291
  10. package/LICENSE +674 -674
  11. package/README.md +2 -2
  12. package/coverage/clover.xml +198 -0
  13. package/coverage/coverage-final.json +5 -0
  14. package/coverage/lcov-report/base.css +224 -0
  15. package/coverage/lcov-report/block-navigation.js +87 -0
  16. package/coverage/lcov-report/config.ts.html +136 -0
  17. package/coverage/lcov-report/device.ts.html +193 -0
  18. package/coverage/lcov-report/favicon.png +0 -0
  19. package/coverage/lcov-report/helpers/index.html +116 -0
  20. package/coverage/lcov-report/helpers/patientFactory.ts.html +124 -0
  21. package/coverage/lcov-report/index.html +131 -0
  22. package/coverage/lcov-report/lib/config.ts.html +136 -0
  23. package/coverage/lcov-report/lib/device.ts.html +193 -0
  24. package/coverage/lcov-report/lib/index.html +146 -0
  25. package/coverage/lcov-report/lib/patient.ts.html +1267 -0
  26. package/coverage/lcov-report/patient.ts.html +1207 -0
  27. package/coverage/lcov-report/prettify.css +1 -0
  28. package/coverage/lcov-report/prettify.js +2 -0
  29. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  30. package/coverage/lcov-report/sorter.js +210 -0
  31. package/coverage/lcov.info +410 -0
  32. package/dist/index.js +51 -32
  33. package/dist/index.js.map +1 -1
  34. package/dist/src/data/patient.json +191 -185
  35. package/dist/src/helpers/patientFactory.js +31 -0
  36. package/dist/src/helpers/patientFactory.js.map +1 -0
  37. package/dist/src/lib/allergyIntolerance.js +39 -39
  38. package/dist/src/lib/allergyIntolerance.js.map +1 -1
  39. package/dist/src/lib/bundle.js +25 -22
  40. package/dist/src/lib/bundle.js.map +1 -1
  41. package/dist/src/lib/composition.js +151 -150
  42. package/dist/src/lib/composition.js.map +1 -1
  43. package/dist/src/lib/condition.js +79 -79
  44. package/dist/src/lib/condition.js.map +1 -1
  45. package/dist/src/lib/config.js +20 -22
  46. package/dist/src/lib/config.js.map +1 -1
  47. package/dist/src/lib/config.test.js +12 -12
  48. package/dist/src/lib/config.test.js.map +1 -1
  49. package/dist/src/lib/device.js +38 -38
  50. package/dist/src/lib/device.js.map +1 -1
  51. package/dist/src/lib/device.test.js +9 -9
  52. package/dist/src/lib/device.test.js.map +1 -1
  53. package/dist/src/lib/document-reference.js +106 -103
  54. package/dist/src/lib/document-reference.js.map +1 -1
  55. package/dist/src/lib/immunization.js +67 -67
  56. package/dist/src/lib/medication.js +64 -64
  57. package/dist/src/lib/medication.js.map +1 -1
  58. package/dist/src/lib/medicationRequest.js +102 -99
  59. package/dist/src/lib/medicationRequest.js.map +1 -1
  60. package/dist/src/lib/medicationStatement.js +55 -55
  61. package/dist/src/lib/medicationStatement.js.map +1 -1
  62. package/dist/src/lib/organization.js +90 -90
  63. package/dist/src/lib/organization.js.map +1 -1
  64. package/dist/src/lib/patient.js +378 -360
  65. package/dist/src/lib/patient.js.map +1 -1
  66. package/dist/src/lib/patient.test.js +78 -39
  67. package/dist/src/lib/patient.test.js.map +1 -1
  68. package/dist/src/lib/practitioner.js +160 -160
  69. package/dist/src/lib/practitioner.js.map +1 -1
  70. package/index.ts +31 -31
  71. package/jest.config.js +11 -11
  72. package/package.json +45 -54
  73. package/release.config.js +74 -0
  74. package/src/data/patient.json +190 -184
  75. package/src/helpers/patientFactory.ts +13 -0
  76. package/src/lib/allergyIntolerance.ts +36 -36
  77. package/src/lib/bundle.ts +19 -19
  78. package/src/lib/composition.ts +153 -153
  79. package/src/lib/condition.ts +80 -80
  80. package/src/lib/config.test.ts +13 -13
  81. package/src/lib/config.ts +17 -17
  82. package/src/lib/device.test.ts +9 -9
  83. package/src/lib/device.ts +36 -36
  84. package/src/lib/document-reference.ts +102 -102
  85. package/src/lib/immunization.ts +64 -64
  86. package/src/lib/medication.ts +61 -61
  87. package/src/lib/medicationRequest.ts +100 -100
  88. package/src/lib/medicationStatement.ts +52 -52
  89. package/src/lib/organization.ts +89 -89
  90. package/src/lib/patient.test.ts +62 -38
  91. package/src/lib/patient.ts +394 -374
  92. package/src/lib/practitioner.ts +157 -157
  93. package/tsconfig.test.json +17 -17
  94. package/tslint.json +138 -138
@@ -1,361 +1,379 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.verify = exports.decode = exports.encode = void 0;
4
- var config_1 = require("./config");
5
- /**
6
- * Encode a patient from ANDES to FHIR
7
- * @param {} patient
8
- */
9
- function encode(patient) {
10
- if (patient) {
11
- var identificadores = [];
12
- if (patient.documento) {
13
- identificadores.push({
14
- system: 'http://www.renaper.gob.ar/dni',
15
- value: patient.documento
16
- });
17
- }
18
- if (patient.cuil) {
19
- identificadores.push({
20
- system: 'http://www.renaper.gob.ar/cuil',
21
- value: patient.cuil
22
- });
23
- }
24
- identificadores.push({
25
- system: config_1.getDominio(),
26
- value: patient._id
27
- });
28
- // Parsea contactos
29
- var contactos = patient.contacto ? patient.contacto.filter(function (c) { return c.valor; }).map(function (unContacto) {
30
- var cont = {
31
- resourceType: 'ContactPoint',
32
- value: unContacto.valor,
33
- rank: unContacto.ranking,
34
- };
35
- switch (unContacto.tipo) {
36
- case 'fijo':
37
- cont['system'] = 'phone';
38
- break;
39
- case 'celular':
40
- cont['system'] = 'phone';
41
- break;
42
- case 'email':
43
- cont['system'] = 'email';
44
- break;
45
- }
46
- return cont;
47
- }) : [];
48
- // Parsea direcciones
49
- var direcciones = patient.direccion ? patient.direccion.filter(function (dir) { return dir.ubicacion.localidad; }).map(function (unaDireccion) {
50
- var direc = {
51
- resourceType: 'Address',
52
- postalCode: unaDireccion.codigoPostal ? unaDireccion.codigoPostal : '',
53
- line: [unaDireccion.valor],
54
- city: unaDireccion.ubicacion.localidad ? unaDireccion.ubicacion.localidad.nombre : '',
55
- state: unaDireccion.ubicacion.provincia ? unaDireccion.ubicacion.provincia.nombre : '',
56
- country: unaDireccion.ubicacion.pais ? unaDireccion.ubicacion.pais.nombre : '',
57
- };
58
- return direc;
59
- }) : [];
60
- // Parsea relaciones
61
- var relaciones = patient.relaciones ? patient.relaciones.filter(function (r) { return !!r.relacion; }).map(function (unaRelacion) {
62
- var relacion = {
63
- relationship: [{
64
- text: unaRelacion.relacion.nombre
65
- }],
66
- name: {
67
- resourceType: 'HumanName',
68
- family: unaRelacion.apellido.split(' '),
69
- given: unaRelacion.nombre.split(' '),
70
- }
71
- };
72
- return relacion;
73
- }) : [];
74
- var genero = void 0;
75
- switch (patient.genero) {
76
- case 'femenino':
77
- genero = 'female';
78
- break;
79
- case 'masculino':
80
- genero = 'male';
81
- break;
82
- case 'otro':
83
- genero = 'other';
84
- break;
85
- }
86
- var pacienteFHIR = {
87
- id: patient.id,
88
- resourceType: 'Patient',
89
- identifier: identificadores,
90
- active: patient.activo ? patient.activo : null,
91
- name: [{
92
- use: 'official',
93
- resourceType: 'HumanName',
94
- family: patient.apellido.split(' '),
95
- given: patient.nombre.split(' '),
96
- text: patient.nombre + " " + patient.apellido,
97
- _family: [{
98
- extension: [
99
- {
100
- url: 'http://hl7.org/fhir/StructureDefinition/humanname-fathers-family',
101
- valueString: patient.apellido
102
- },
103
- ]
104
- }],
105
- }],
106
- gender: genero,
107
- birthDate: patient.fechaNacimiento ? typeof patient.fechaNacimiento === 'string' ? new Date(patient.fechaNacimiento).toISOString().slice(0, 10) : patient.fechaNacimiento.toISOString().slice(0, 10) : null
108
- };
109
- if (patient.fechaFallecimiento) {
110
- pacienteFHIR.deceasedDateTime = typeof patient.fechaFallecimiento === 'string' ? new Date(patient.fechaFallecimiento.toISOString().slice(0, 10)) : patient.fechaFallecimiento.toISOString().slice(0, 10);
111
- }
112
- if (patient.estadoCivil) {
113
- var estadoCivil = void 0;
114
- switch (patient.estadoCivil) {
115
- case 'casado':
116
- estadoCivil = 'Married';
117
- break;
118
- case 'divorciado':
119
- estadoCivil = 'Divorced';
120
- break;
121
- case 'viudo':
122
- estadoCivil = 'Widowed';
123
- break;
124
- case 'soltero':
125
- estadoCivil = 'unmarried';
126
- break;
127
- default:
128
- estadoCivil = 'unknown';
129
- break;
130
- }
131
- pacienteFHIR['maritalStatus'] = {
132
- text: estadoCivil
133
- };
134
- }
135
- if (patient.foto) {
136
- pacienteFHIR['photo'] = [{
137
- patient: patient.foto
138
- }];
139
- }
140
- if (contactos.length > 0) { // A contact detail for the individual
141
- pacienteFHIR['telecom'] = contactos;
142
- }
143
- if (direcciones.length > 0) { // Addresses for the individual
144
- pacienteFHIR['address'] = direcciones;
145
- }
146
- if (relaciones.length > 0) { // A contact party (e.g. guardian, partner, friend) for the patient
147
- pacienteFHIR['contact'] = relaciones;
148
- }
149
- return pacienteFHIR;
150
- }
151
- else {
152
- return null;
153
- }
154
- }
155
- exports.encode = encode;
156
- /**
157
- * Decode a patient from FHIR to ANDES
158
- * @param {} patient
159
- */
160
- function decode(patient) {
161
- var genero;
162
- var sexo;
163
- // Cuando el paciente viene por FHIR suponemos el valor del genero tanto para nuestro field genero como sexo
164
- switch (patient.gender) {
165
- case 'female':
166
- genero = 'femenino';
167
- sexo = 'femenino';
168
- break;
169
- case 'male':
170
- genero = 'masculino';
171
- sexo = 'masculino';
172
- break;
173
- case 'other':
174
- genero = 'otro';
175
- sexo = 'otro';
176
- break;
177
- }
178
- function getValue(items, key) {
179
- var element = items.find(function (el) { return el.system === key; });
180
- if (element) {
181
- return element.value;
182
- }
183
- }
184
- var pacienteAndes = {
185
- id: getValue(patient.identifier, config_1.makeUrl('Patient')),
186
- documento: getValue(patient.identifier, 'http://www.renaper.gob.ar/dni'),
187
- nombre: patient.name[0].given.join().replace(',', ' '),
188
- apellido: Array.isArray(patient.name[0].family) ? patient.name[0].family.join().replace(',', ' ') : patient.name[0].family,
189
- fechaNacimiento: patient.birthDate,
190
- genero: genero,
191
- sexo: sexo,
192
- estado: 'temporal' // Todos los pacientes que recibimos por Fhir son considerados temporales en su conversión.
193
- };
194
- var contactos = patient.telecom ? patient.telecom.map(function (unContacto) {
195
- var cont = {
196
- valor: unContacto.value,
197
- ranking: unContacto.rank
198
- };
199
- switch (unContacto.system) {
200
- case 'phone':
201
- cont['tipo'] = 'celular';
202
- break;
203
- case 'email':
204
- cont['tipo'] = 'email';
205
- break;
206
- }
207
- return cont;
208
- }) : [];
209
- var relaciones = patient.contact ? patient.contact.map(function (aContact) {
210
- var relacion = {
211
- relacion: {
212
- nombre: aContact.relationship[0].text
213
- },
214
- nombre: aContact.name.given.join().replace(',', ' '),
215
- apellido: aContact.name.family
216
- };
217
- return relacion;
218
- }) : [];
219
- if (patient.maritalStatus) {
220
- var estadoCivil = void 0;
221
- switch (patient.maritalStatus['text']) {
222
- case 'Married':
223
- estadoCivil = 'casado';
224
- break;
225
- case 'Divorced':
226
- estadoCivil = 'divorciado';
227
- break;
228
- case 'Widowed':
229
- estadoCivil = 'viudo';
230
- break;
231
- case 'unmarried':
232
- estadoCivil = 'soltero';
233
- break;
234
- default:
235
- estadoCivil = 'otro';
236
- break;
237
- }
238
- pacienteAndes['estadoCivil'] = estadoCivil;
239
- }
240
- var direcciones = patient.address ? patient.address.map(function (unaDireccion) {
241
- var dir = {
242
- activo: true,
243
- valor: unaDireccion.line,
244
- codigoPostal: unaDireccion.postalCode,
245
- // TODO: En un MATETIME ver si la información de pais, provincia, localidad
246
- // se delega en el insert o update. Y este decoder sólo guarda la info tal cual viene.
247
- ubicacion: {
248
- pais: unaDireccion.country,
249
- provincia: unaDireccion.state,
250
- localidad: unaDireccion.city
251
- }
252
- };
253
- return dir;
254
- }) : [];
255
- pacienteAndes['direccion'] = direcciones;
256
- if (patient.active) {
257
- pacienteAndes['activo'] = patient.active;
258
- }
259
- if (contactos.length > 0) {
260
- pacienteAndes['contacto'] = contactos;
261
- }
262
- if (patient.photo) { // Image of the patient
263
- pacienteAndes['foto'] = patient.photo[0].data;
264
- }
265
- if (patient.contact) {
266
- pacienteAndes['relaciones'] = relaciones;
267
- }
268
- return pacienteAndes;
269
- }
270
- exports.decode = decode;
271
- /**
272
- * Verify if a patient has a FHIR format
273
- * @param {*} patient
274
- */
275
- function verify(patient) {
276
- var respuesta = true;
277
- var fieldVerified = Object.keys(patient).every(pacienteFHIRFields);
278
- // Verificamos que las key esten contenidas en los conjuntos mínimos pacienteFHIRField
279
- if (fieldVerified) {
280
- respuesta = ('resourceType' in patient) && patient.resourceType === 'Patient';
281
- respuesta = respuesta && ('identifier' in patient);
282
- if (patient.identifier.length > 0) {
283
- patient.identifier.forEach(function (anIdentifier) { return respuesta = respuesta && Object.keys(anIdentifier).every(identifierFields); });
284
- }
285
- patient.name.forEach(function (aName) { return respuesta = respuesta && validName(aName); });
286
- if (patient.active) {
287
- respuesta = respuesta && (typeof patient.active === 'boolean');
288
- }
289
- if (patient.telecom) {
290
- patient.telecom.forEach(function (aTelecom) { return respuesta = respuesta && Object.keys(aTelecom).every(telecomFields); });
291
- }
292
- if (patient.gender) {
293
- respuesta = respuesta && patient.gender.match('male|female|other|unknown') != null;
294
- }
295
- if (patient.birthDate) {
296
- respuesta = respuesta && typeof patient.birthDate === 'string'; // TODO: Algun control de que tenga formato Date
297
- }
298
- if (patient.deceasedDateTime) {
299
- respuesta = respuesta && typeof patient.deceasedDateTime === 'string'; // TODO: Algun control de que tenga formato DateTime
300
- }
301
- if (patient.address) {
302
- patient.address.forEach(function (anAddress) { return respuesta = respuesta && Object.keys(anAddress).every(addressFields); });
303
- }
304
- if (patient.maritalStatus && patient.maritalStatus.text) {
305
- respuesta = respuesta && Object.keys(patient.maritalStatus).every(codingFields)
306
- && typeof patient.maritalStatus.text === 'string'
307
- && patient.maritalStatus.text.match('Married|Divorced|Widowed|unmarried|unknown') != null;
308
- }
309
- if (patient.photo) {
310
- patient.photo.forEach(function (aPhoto) { return respuesta = respuesta && Object.keys(aPhoto).every(photoFields); });
311
- }
312
- if (patient.contact) {
313
- patient.contact.forEach(function (aContact) {
314
- if (aContact.relationship) {
315
- aContact.relationship.forEach(function (aRelation) { return respuesta = respuesta && Object.keys(aRelation).every(codingFields); });
316
- }
317
- if (aContact.name) {
318
- respuesta = respuesta && validName(aContact.name);
319
- }
320
- });
321
- }
322
- }
323
- else {
324
- respuesta = fieldVerified; // No cumple con los campos estandar de FHIR
325
- }
326
- return respuesta;
327
- }
328
- exports.verify = verify;
329
- function pacienteFHIRFields(elem) {
330
- return elem.match('resourceType|identifier|active|name|telecom|gender|birthDate|deceasedBoolean|deceasedDateTime|address|maritalStatus|photo|contact') != null;
331
- }
332
- function identifierFields(elem) {
333
- return elem.match('use|type|system|value|period|assigner') != null;
334
- }
335
- function nameFields(elem) {
336
- return elem.match('resourceType|family|given') != null;
337
- }
338
- function telecomFields(elem) {
339
- return elem.match('resourceType|system|value|use|rank|period') != null;
340
- }
341
- function addressFields(elem) {
342
- return elem.match('resourceType|use|type|text|line|city|district|state|postalCode|country|period') != null;
343
- }
344
- function codingFields(elem) {
345
- return elem.match('coding|text') != null;
346
- }
347
- function photoFields(elem) {
348
- return elem.match('contentType|language|data|url|size|hash|title|creation') != null;
349
- }
350
- function contactFields(elem) {
351
- return elem.match('relationship|name|telecom|address|gender|organization|period') != null;
352
- }
353
- function validName(aName) {
354
- return Object.keys(aName).every(nameFields) && ('resourceType' in aName) && aName.resourceType === 'HumanName' &&
355
- ('family' in aName) && Array.isArray(aName.family) && aName.family.every(areStrings) &&
356
- ('given' in aName) && Array.isArray(aName.given) && aName.given.every(areStrings);
357
- }
358
- function areStrings(elem) {
359
- return typeof elem === 'string';
360
- }
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.verify = exports.decode = exports.encode = void 0;
4
+ const config_1 = require("./config");
5
+ /**
6
+ * Encode a patient from ANDES to FHIR
7
+ * @param {} patient
8
+ */
9
+ function encode(patient) {
10
+ if (patient) {
11
+ const identificadores = [];
12
+ if (patient.documento) {
13
+ identificadores.push({
14
+ system: 'http://www.renaper.gob.ar/dni',
15
+ value: patient.documento
16
+ });
17
+ }
18
+ if (patient.cuil) {
19
+ identificadores.push({
20
+ system: 'http://www.renaper.gob.ar/cuil',
21
+ value: patient.cuil
22
+ });
23
+ }
24
+ identificadores.push({
25
+ system: config_1.getDominio(),
26
+ value: patient._id
27
+ });
28
+ // Parsea contactos
29
+ let contactos = patient.contacto ? patient.contacto.filter(c => c.valor).map(unContacto => {
30
+ let cont = {
31
+ resourceType: 'ContactPoint',
32
+ value: unContacto.valor,
33
+ rank: unContacto.ranking,
34
+ };
35
+ switch (unContacto.tipo) {
36
+ case 'fijo':
37
+ cont['system'] = 'phone';
38
+ break;
39
+ case 'celular':
40
+ cont['system'] = 'phone';
41
+ break;
42
+ case 'email':
43
+ cont['system'] = 'email';
44
+ break;
45
+ }
46
+ return cont;
47
+ }) : [];
48
+ // Parsea direcciones
49
+ let direcciones = patient.direccion ? patient.direccion.filter(dir => dir.ubicacion.localidad).map(unaDireccion => {
50
+ let direc = {
51
+ resourceType: 'Address',
52
+ postalCode: unaDireccion.codigoPostal ? unaDireccion.codigoPostal : '',
53
+ line: [unaDireccion.valor],
54
+ city: unaDireccion.ubicacion.localidad ? unaDireccion.ubicacion.localidad.nombre : '',
55
+ state: unaDireccion.ubicacion.provincia ? unaDireccion.ubicacion.provincia.nombre : '',
56
+ country: unaDireccion.ubicacion.pais ? unaDireccion.ubicacion.pais.nombre : '',
57
+ };
58
+ return direc;
59
+ }) : [];
60
+ // Parsea relaciones
61
+ let relaciones = patient.relaciones ? patient.relaciones.filter(r => !!r.relacion).map(unaRelacion => {
62
+ let relacion = {
63
+ relationship: [{
64
+ text: unaRelacion.relacion.nombre
65
+ }],
66
+ name: {
67
+ resourceType: 'HumanName',
68
+ family: unaRelacion.apellido.split(' '),
69
+ given: unaRelacion.nombre.split(' '),
70
+ }
71
+ };
72
+ return relacion;
73
+ }) : [];
74
+ let genero;
75
+ switch (patient.genero) {
76
+ case 'femenino':
77
+ genero = 'female';
78
+ break;
79
+ case 'masculino':
80
+ genero = 'male';
81
+ break;
82
+ case 'otro':
83
+ genero = 'other';
84
+ break;
85
+ }
86
+ let pacienteFHIR = {
87
+ id: patient.id,
88
+ resourceType: 'Patient',
89
+ identifier: identificadores,
90
+ active: patient.activo ? patient.activo : null,
91
+ name: [{
92
+ use: 'official',
93
+ resourceType: 'HumanName',
94
+ family: patient.apellido.split(' '),
95
+ given: patient.nombre.split(' '),
96
+ text: `${patient.nombre} ${patient.apellido}`,
97
+ _family: [{
98
+ extension: [
99
+ {
100
+ url: 'http://hl7.org/fhir/StructureDefinition/humanname-fathers-family',
101
+ valueString: patient.apellido
102
+ },
103
+ ]
104
+ }],
105
+ }],
106
+ gender: genero,
107
+ birthDate: patient.fechaNacimiento ? typeof patient.fechaNacimiento === 'string' ? new Date(patient.fechaNacimiento).toISOString().slice(0, 10) : patient.fechaNacimiento.toISOString().slice(0, 10) : null,
108
+ extension: [{
109
+ url: 'andes.gob.ar/fhir/StructureDefinition/patient-status',
110
+ valueCode: patient.estado ? patient.estado : 'temporal' // validado | temporal
111
+ }]
112
+ };
113
+ if (patient.fechaFallecimiento) {
114
+ pacienteFHIR.deceasedDateTime = typeof patient.fechaFallecimiento === 'string' ? new Date(patient.fechaFallecimiento.toISOString().slice(0, 10)) : patient.fechaFallecimiento.toISOString().slice(0, 10);
115
+ }
116
+ if (patient.estadoCivil) {
117
+ let estadoCivil;
118
+ switch (patient.estadoCivil) {
119
+ case 'casado':
120
+ estadoCivil = 'Married';
121
+ break;
122
+ case 'divorciado':
123
+ estadoCivil = 'Divorced';
124
+ break;
125
+ case 'viudo':
126
+ estadoCivil = 'Widowed';
127
+ break;
128
+ case 'soltero':
129
+ estadoCivil = 'unmarried';
130
+ break;
131
+ default:
132
+ estadoCivil = 'unknown';
133
+ break;
134
+ }
135
+ pacienteFHIR['maritalStatus'] = {
136
+ text: estadoCivil
137
+ };
138
+ }
139
+ if (patient.foto) {
140
+ pacienteFHIR['photo'] = [{
141
+ patient: patient.foto
142
+ }];
143
+ }
144
+ if (contactos.length > 0) { // A contact detail for the individual
145
+ pacienteFHIR['telecom'] = contactos;
146
+ }
147
+ if (direcciones.length > 0) { // Addresses for the individual
148
+ pacienteFHIR['address'] = direcciones;
149
+ }
150
+ if (relaciones.length > 0) { // A contact party (e.g. guardian, partner, friend) for the patient
151
+ pacienteFHIR['contact'] = relaciones;
152
+ }
153
+ let managingOrganization = {
154
+ reference: patient.createdBy.organizacion.id,
155
+ display: patient.createdBy.organizacion.nombre
156
+ };
157
+ pacienteFHIR['managingOrganization'] = managingOrganization;
158
+ return pacienteFHIR;
159
+ }
160
+ else {
161
+ return null;
162
+ }
163
+ }
164
+ exports.encode = encode;
165
+ /**
166
+ * Decode a patient from FHIR to ANDES
167
+ * @param {} patient
168
+ */
169
+ function decode(patient) {
170
+ let genero;
171
+ let sexo;
172
+ // Cuando el paciente viene por FHIR suponemos el valor del genero tanto para nuestro field genero como sexo
173
+ switch (patient.gender) {
174
+ case 'female':
175
+ genero = 'femenino';
176
+ sexo = 'femenino';
177
+ break;
178
+ case 'male':
179
+ genero = 'masculino';
180
+ sexo = 'masculino';
181
+ break;
182
+ case 'other':
183
+ genero = 'otro';
184
+ sexo = 'otro';
185
+ break;
186
+ }
187
+ function getValue(items, key) {
188
+ const element = items.find(el => el.system === key);
189
+ if (element) {
190
+ return element.value;
191
+ }
192
+ }
193
+ let pacienteAndes = {
194
+ id: getValue(patient.identifier, config_1.makeUrl('Patient')),
195
+ documento: getValue(patient.identifier, 'http://www.renaper.gob.ar/dni'),
196
+ nombre: patient.name[0].given.join().replace(',', ' '),
197
+ apellido: Array.isArray(patient.name[0].family) ? patient.name[0].family.join().replace(',', ' ') : patient.name[0].family,
198
+ fechaNacimiento: patient.birthDate,
199
+ genero,
200
+ sexo,
201
+ estado: 'temporal',
202
+ createdBy: null
203
+ };
204
+ let contactos = patient.telecom ? patient.telecom.map(unContacto => {
205
+ let cont = {
206
+ valor: unContacto.value,
207
+ ranking: unContacto.rank
208
+ };
209
+ switch (unContacto.system) {
210
+ case 'phone':
211
+ cont['tipo'] = 'celular';
212
+ break;
213
+ case 'email':
214
+ cont['tipo'] = 'email';
215
+ break;
216
+ }
217
+ return cont;
218
+ }) : [];
219
+ let relaciones = patient.contact ? patient.contact.map(aContact => {
220
+ let relacion = {
221
+ relacion: {
222
+ nombre: aContact.relationship[0].text
223
+ },
224
+ nombre: aContact.name.given.join().replace(',', ' '),
225
+ apellido: aContact.name.family
226
+ };
227
+ return relacion;
228
+ }) : [];
229
+ if (patient.maritalStatus) {
230
+ let estadoCivil;
231
+ switch (patient.maritalStatus['text']) {
232
+ case 'Married':
233
+ estadoCivil = 'casado';
234
+ break;
235
+ case 'Divorced':
236
+ estadoCivil = 'divorciado';
237
+ break;
238
+ case 'Widowed':
239
+ estadoCivil = 'viudo';
240
+ break;
241
+ case 'unmarried':
242
+ estadoCivil = 'soltero';
243
+ break;
244
+ default:
245
+ estadoCivil = 'otro';
246
+ break;
247
+ }
248
+ pacienteAndes['estadoCivil'] = estadoCivil;
249
+ }
250
+ let direcciones = patient.address ? patient.address.map(unaDireccion => {
251
+ let dir = {
252
+ activo: true,
253
+ valor: unaDireccion.line,
254
+ codigoPostal: unaDireccion.postalCode,
255
+ // TODO: En un MATETIME ver si la información de pais, provincia, localidad
256
+ // se delega en el insert o update. Y este decoder sólo guarda la info tal cual viene.
257
+ ubicacion: {
258
+ pais: unaDireccion.country,
259
+ provincia: unaDireccion.state,
260
+ localidad: unaDireccion.city
261
+ }
262
+ };
263
+ return dir;
264
+ }) : [];
265
+ pacienteAndes['direccion'] = direcciones;
266
+ if (patient.active) {
267
+ pacienteAndes['activo'] = patient.active;
268
+ }
269
+ if (contactos.length > 0) {
270
+ pacienteAndes['contacto'] = contactos;
271
+ }
272
+ if (patient.photo) { // Image of the patient
273
+ pacienteAndes['foto'] = patient.photo[0].data;
274
+ }
275
+ if (patient.contact) {
276
+ pacienteAndes['relaciones'] = relaciones;
277
+ }
278
+ if (patient.managingOrganization) {
279
+ pacienteAndes['createdBy'] = {
280
+ organizacion: {
281
+ id: patient.managingOrganization.reference,
282
+ nombre: patient.managingOrganization.display
283
+ }
284
+ };
285
+ }
286
+ return pacienteAndes;
287
+ }
288
+ exports.decode = decode;
289
+ /**
290
+ * Verify if a patient has a FHIR format
291
+ * @param {*} patient
292
+ */
293
+ function verify(patient) {
294
+ let respuesta = true;
295
+ let fieldVerified = Object.keys(patient).every(pacienteFHIRFields);
296
+ // Verificamos que las key esten contenidas en los conjuntos mínimos pacienteFHIRField
297
+ if (fieldVerified) {
298
+ respuesta = ('resourceType' in patient) && patient.resourceType === 'Patient';
299
+ respuesta = respuesta && ('identifier' in patient);
300
+ if (patient.identifier.length > 0) {
301
+ patient.identifier.forEach(anIdentifier => respuesta = respuesta && Object.keys(anIdentifier).every(identifierFields));
302
+ }
303
+ patient.name.forEach(aName => respuesta = respuesta && validName(aName));
304
+ if (patient.active) {
305
+ respuesta = respuesta && (typeof patient.active === 'boolean');
306
+ }
307
+ if (patient.telecom) {
308
+ patient.telecom.forEach(aTelecom => respuesta = respuesta && Object.keys(aTelecom).every(telecomFields));
309
+ }
310
+ if (patient.gender) {
311
+ respuesta = respuesta && patient.gender.match('male|female|other|unknown') != null;
312
+ }
313
+ if (patient.birthDate) {
314
+ respuesta = respuesta && typeof patient.birthDate === 'string'; // TODO: Algun control de que tenga formato Date
315
+ }
316
+ if (patient.deceasedDateTime) {
317
+ respuesta = respuesta && typeof patient.deceasedDateTime === 'string'; // TODO: Algun control de que tenga formato DateTime
318
+ }
319
+ if (patient.address) {
320
+ patient.address.forEach(anAddress => respuesta = respuesta && Object.keys(anAddress).every(addressFields));
321
+ }
322
+ if (patient.maritalStatus && patient.maritalStatus.text) {
323
+ respuesta = respuesta && Object.keys(patient.maritalStatus).every(codingFields)
324
+ && typeof patient.maritalStatus.text === 'string'
325
+ && patient.maritalStatus.text.match('Married|Divorced|Widowed|unmarried|unknown') != null;
326
+ }
327
+ if (patient.photo) {
328
+ patient.photo.forEach(aPhoto => respuesta = respuesta && Object.keys(aPhoto).every(photoFields));
329
+ }
330
+ if (patient.contact) {
331
+ patient.contact.forEach(aContact => {
332
+ if (aContact.relationship) {
333
+ aContact.relationship.forEach(aRelation => respuesta = respuesta && Object.keys(aRelation).every(codingFields));
334
+ }
335
+ if (aContact.name) {
336
+ respuesta = respuesta && validName(aContact.name);
337
+ }
338
+ });
339
+ }
340
+ }
341
+ else {
342
+ respuesta = fieldVerified; // No cumple con los campos estandar de FHIR
343
+ }
344
+ return respuesta;
345
+ }
346
+ exports.verify = verify;
347
+ function pacienteFHIRFields(elem) {
348
+ return elem.match('resourceType|identifier|active|name|telecom|gender|birthDate|deceasedBoolean|deceasedDateTime|address|maritalStatus|photo|contact') != null;
349
+ }
350
+ function identifierFields(elem) {
351
+ return elem.match('use|type|system|value|period|assigner') != null;
352
+ }
353
+ function nameFields(elem) {
354
+ return elem.match('resourceType|family|given') != null;
355
+ }
356
+ function telecomFields(elem) {
357
+ return elem.match('resourceType|system|value|use|rank|period') != null;
358
+ }
359
+ function addressFields(elem) {
360
+ return elem.match('resourceType|use|type|text|line|city|district|state|postalCode|country|period') != null;
361
+ }
362
+ function codingFields(elem) {
363
+ return elem.match('coding|text') != null;
364
+ }
365
+ function photoFields(elem) {
366
+ return elem.match('contentType|language|data|url|size|hash|title|creation') != null;
367
+ }
368
+ function contactFields(elem) {
369
+ return elem.match('relationship|name|telecom|address|gender|organization|period') != null;
370
+ }
371
+ function validName(aName) {
372
+ return Object.keys(aName).every(nameFields) && ('resourceType' in aName) && aName.resourceType === 'HumanName' &&
373
+ ('family' in aName) && Array.isArray(aName.family) && aName.family.every(areStrings) &&
374
+ ('given' in aName) && Array.isArray(aName.given) && aName.given.every(areStrings);
375
+ }
376
+ function areStrings(elem) {
377
+ return typeof elem === 'string';
378
+ }
361
379
  //# sourceMappingURL=patient.js.map