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