@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,56 +1,55 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.encode = void 0;
4
- /**
5
- * Encode de Medicamentos from ANDES to FHIR
6
- * @param {} medicationStatement
7
- */
8
- // Muy incompleto hay que mejorarlo mucho todavía
9
- function encode(patientReference, medicationReference, prestacionMedicamento) {
10
- return {
11
- resourceType: 'MedicationStatement',
12
- status: (prestacionMedicamento.valor.estado === 'activo') ? 'active' : 'inactive',
13
- id: prestacionMedicamento._id,
14
- effectiveDateTime: prestacionMedicamento.createdAt,
15
- medicationCodeableConcept: {
16
- coding: [
17
- {
18
- system: 'http://snomed.info/sct',
19
- code: prestacionMedicamento.concepto.conceptId,
20
- display: prestacionMedicamento.concepto.term
21
- }
22
- ]
23
- },
24
- meta: {
25
- profile: [
26
- 'http://hl7.org/fhir/uv/ips/StructureDefinition/medication-ips'
27
- ]
28
- },
29
- // extension: null,
30
- // identifier: '', // Business identifier, not a resource identifier
31
- subject: {
32
- reference: patientReference
33
- },
34
- medicationReference: {
35
- reference: medicationReference
36
- },
37
- // context: null, // Encounter | Episode of care (podría ser el informe del encuentro o lo que definamos que brinda más información sobre el por qué)
38
- dosage: [
39
- {
40
- text: prestacionMedicamento.valor,
41
- route: { coding: [{ system: 'http://standardterms.edqm.eu', code: prestacionMedicamento._id, display: prestacionMedicamento.nombre }] },
42
- timing: { coding: { system: 'http://terminology.hl7.org/CodeSystem/v3-GTSAbbreviation', code: 'QD', display: 'Diario' } }
43
- }
44
- ],
45
- // effectivePeriod: { // Esta parte se podría calcular entre la fecha de la prestación y la cant. de tiempo que se indica, pero hay problemas
46
- // en este registro ya que no siempre está la unidad de tiempo (dias, mes, etc) hay q ver si no es un bug.
47
- // start: '2015-03'
48
- // },
49
- text: {
50
- status: 'generated',
51
- div: `<div xmlns=\"http://www.w3.org/1999/xhtml\"><p><b>Generated Narrative with Details</b></p><p><b>id</b>: Medicacion </p><p><b>meta</b>: </p><p><b>text</b>: ${prestacionMedicamento.concepto.term}</p></div>`
52
- }
53
- };
54
- }
55
- exports.encode = encode;
56
- //# sourceMappingURL=medicationStatement.js.map
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.encode = void 0;
4
+ /**
5
+ * Encode de Medicamentos from ANDES to FHIR
6
+ * @param {} medicationStatement
7
+ */
8
+ // Muy incompleto hay que mejorarlo mucho todavía
9
+ function encode(patientReference, medicationReference, prestacionMedicamento) {
10
+ return {
11
+ resourceType: 'MedicationStatement',
12
+ status: (prestacionMedicamento.valor.estado === 'activo') ? 'active' : 'inactive',
13
+ id: prestacionMedicamento._id, // El código de la prestación donde está el registro del contexto de porque está consumiendo el medicamento
14
+ effectiveDateTime: prestacionMedicamento.createdAt,
15
+ medicationCodeableConcept: {
16
+ coding: [
17
+ {
18
+ system: 'http://snomed.info/sct',
19
+ code: prestacionMedicamento.concepto.conceptId,
20
+ display: prestacionMedicamento.concepto.term
21
+ }
22
+ ]
23
+ },
24
+ meta: {
25
+ profile: [
26
+ 'http://hl7.org/fhir/uv/ips/StructureDefinition/medication-ips'
27
+ ]
28
+ },
29
+ // extension: null,
30
+ // identifier: '', // Business identifier, not a resource identifier
31
+ subject: {
32
+ reference: patientReference
33
+ },
34
+ medicationReference: {
35
+ reference: medicationReference
36
+ },
37
+ // context: null, // Encounter | Episode of care (podría ser el informe del encuentro o lo que definamos que brinda más información sobre el por qué)
38
+ dosage: [
39
+ {
40
+ text: prestacionMedicamento.valor, // indicación
41
+ route: { coding: [{ system: 'http://standardterms.edqm.eu', code: prestacionMedicamento._id, display: prestacionMedicamento.nombre }] },
42
+ timing: { coding: { system: 'http://terminology.hl7.org/CodeSystem/v3-GTSAbbreviation', code: 'QD', display: 'Diario' } }
43
+ }
44
+ ],
45
+ // effectivePeriod: { // Esta parte se podría calcular entre la fecha de la prestación y la cant. de tiempo que se indica, pero hay problemas
46
+ // en este registro ya que no siempre está la unidad de tiempo (dias, mes, etc) hay q ver si no es un bug.
47
+ // start: '2015-03'
48
+ // },
49
+ text: {
50
+ status: 'generated',
51
+ div: `<div xmlns="http://www.w3.org/1999/xhtml"><p><b>Generated Narrative with Details</b></p><p><b>id</b>: Medicacion </p><p><b>meta</b>: </p><p><b>text</b>: ${prestacionMedicamento.concepto.term}</p></div>`
52
+ }
53
+ };
54
+ }
55
+ exports.encode = encode;
@@ -0,0 +1,6 @@
1
+ import { Organization } from 'fhir/r4';
2
+ import { AndesOrganization } from '../types/andes/organization.types';
3
+ /**
4
+ * Encode an ANDES Organization to FHIR Organization
5
+ */
6
+ export declare function encode(organization: AndesOrganization | null | undefined): Organization | null;
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.encode = void 0;
4
+ const config_1 = require("./config");
5
+ /**
6
+ * Encode an ANDES Organization to FHIR Organization
7
+ */
8
+ function encode(organization) {
9
+ const data = organization;
10
+ if (!data)
11
+ return null;
12
+ // Identificadores
13
+ const identificadores = [];
14
+ if (data.codigo?.sisa) {
15
+ identificadores.push({
16
+ system: 'andes.gob.ar/sisa',
17
+ value: data.codigo.sisa
18
+ });
19
+ }
20
+ if (data.codigo?.cuie) {
21
+ identificadores.push({
22
+ system: 'andes.gob.ar/cuie',
23
+ value: data.codigo.cuie
24
+ });
25
+ }
26
+ if (data.codigo?.remediar) {
27
+ identificadores.push({
28
+ system: 'andes.gob.ar/remediar',
29
+ value: data.codigo.remediar
30
+ });
31
+ }
32
+ if (data.codigo?.sips) {
33
+ identificadores.push({
34
+ system: 'andes.gob.ar/sips',
35
+ value: data.codigo.sips
36
+ });
37
+ }
38
+ identificadores.push({
39
+ system: (0, config_1.makeUrl)('Organization'),
40
+ value: data._id ?? data.id
41
+ });
42
+ // Contactos → telecom
43
+ const contactos = (data.contacto ?? [])
44
+ .map((item) => {
45
+ const cp = {
46
+ value: item.valor,
47
+ rank: item.ranking
48
+ };
49
+ switch (item.tipo) {
50
+ case 'fijo':
51
+ case 'celular':
52
+ cp.system = 'phone';
53
+ break;
54
+ case 'email':
55
+ cp.system = 'email';
56
+ break;
57
+ }
58
+ return cp;
59
+ });
60
+ // Dirección → address
61
+ const direcciones = [];
62
+ if (data.direccion) {
63
+ const dir = data.direccion;
64
+ direcciones.push({
65
+ postalCode: dir.codigoPostal ?? '',
66
+ line: [dir.valor],
67
+ city: dir.ubicacion?.localidad?.nombre ?? '',
68
+ state: dir.ubicacion?.provincia?.nombre ?? '',
69
+ country: dir.ubicacion?.pais?.nombre ?? ''
70
+ });
71
+ }
72
+ // Organización FHIR
73
+ const organizacionFHIR = {
74
+ resourceType: 'Organization',
75
+ id: data._id ?? data.id,
76
+ identifier: identificadores,
77
+ active: data.activo ?? undefined,
78
+ name: data.nombre ?? undefined,
79
+ type: data.tipoEstablecimiento
80
+ ? [{
81
+ text: data.tipoEstablecimiento.nombre
82
+ }]
83
+ : undefined
84
+ };
85
+ if (contactos.length > 0) {
86
+ organizacionFHIR.telecom = contactos;
87
+ }
88
+ if (direcciones.length > 0) {
89
+ organizacionFHIR.address = direcciones;
90
+ }
91
+ return organizacionFHIR;
92
+ }
93
+ exports.encode = encode;
@@ -0,0 +1,14 @@
1
+ import { Patient } from 'fhir/r4';
2
+ import { AndesPatient } from '../types/andes/patient.types';
3
+ /**
4
+ * Encode a patient from ANDES to FHIR
5
+ */
6
+ export declare function encode(patient: AndesPatient | null | undefined): Patient | null;
7
+ /**
8
+ * Decode a patient from FHIR to ANDES
9
+ */
10
+ export declare function decode(patient: Patient): AndesPatient;
11
+ /**
12
+ * Verify if a patient has a FHIR format
13
+ */
14
+ export declare function verify(patient: any): boolean;
@@ -0,0 +1,465 @@
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
+ * Helpers
7
+ */
8
+ function formatDateOnly(value) {
9
+ if (!value)
10
+ return undefined;
11
+ const d = typeof value === 'string' ? new Date(value) : value;
12
+ if (isNaN(d.getTime()))
13
+ return undefined;
14
+ return d.toISOString().slice(0, 10);
15
+ }
16
+ function formatDateTime(value) {
17
+ if (!value)
18
+ return undefined;
19
+ const d = typeof value === 'string' ? new Date(value) : value;
20
+ if (isNaN(d.getTime()))
21
+ return undefined;
22
+ return d.toISOString();
23
+ }
24
+ function mapGeneroFHIRToAndes(gender) {
25
+ switch (gender) {
26
+ case 'female':
27
+ return 'femenino';
28
+ case 'male':
29
+ return 'masculino';
30
+ case 'other':
31
+ return 'otro';
32
+ default:
33
+ return undefined;
34
+ }
35
+ }
36
+ function mapSexoAndesToGenderFHIR(sexo) {
37
+ switch (sexo) {
38
+ case 'femenino':
39
+ return 'female';
40
+ case 'masculino':
41
+ return 'male';
42
+ case 'otro':
43
+ return 'other';
44
+ default:
45
+ return undefined; // unknown
46
+ }
47
+ }
48
+ function buildGenderIdentityExtension(genero) {
49
+ if (!genero) {
50
+ return [];
51
+ }
52
+ return [{
53
+ url: 'http://hl7.org/fhir/StructureDefinition/individual-genderIdentity',
54
+ valueCode: genero
55
+ }];
56
+ }
57
+ function buildStatusExtension(estado) {
58
+ const value = estado ?? 'temporal';
59
+ return [{
60
+ url: 'andes.gob.ar/fhir/StructureDefinition/patient-status',
61
+ valueCode: value
62
+ }];
63
+ }
64
+ function mapEstadoCivilAndesToFHIR(estadoCivil) {
65
+ switch (estadoCivil) {
66
+ case 'casado':
67
+ return 'Married';
68
+ case 'divorciado':
69
+ return 'Divorced';
70
+ case 'viudo':
71
+ return 'Widowed';
72
+ case 'soltero':
73
+ return 'unmarried';
74
+ default:
75
+ return 'unknown';
76
+ }
77
+ }
78
+ function mapEstadoCivilFHIRToAndes(estadoCivil) {
79
+ switch (estadoCivil) {
80
+ case 'Married':
81
+ return 'casado';
82
+ case 'Divorced':
83
+ return 'divorciado';
84
+ case 'Widowed':
85
+ return 'viudo';
86
+ case 'unmarried':
87
+ return 'soltero';
88
+ default:
89
+ return 'otro';
90
+ }
91
+ }
92
+ /**
93
+ * Encode a patient from ANDES to FHIR
94
+ */
95
+ function encode(patient) {
96
+ if (!patient) {
97
+ return null;
98
+ }
99
+ // Identificadores
100
+ const identificadores = [];
101
+ // Dominio local (id de ANDES o equivalente)
102
+ identificadores.push({
103
+ system: (0, config_1.getDominio)(),
104
+ value: patient._id ?? patient.id
105
+ });
106
+ if (patient.documento) {
107
+ identificadores.push({
108
+ system: 'http://www.renaper.gob.ar/dni',
109
+ value: patient.documento
110
+ });
111
+ }
112
+ if (patient.cuil) {
113
+ identificadores.push({
114
+ system: 'http://www.renaper.gob.ar/cuil',
115
+ value: patient.cuil
116
+ });
117
+ }
118
+ if (patient.numeroIdentificacion) {
119
+ if (patient.tipoIdentificacion === 'dni extranjero') {
120
+ identificadores.push({
121
+ system: 'andes.gob.ar/sid/foreign-id',
122
+ value: patient.numeroIdentificacion
123
+ });
124
+ }
125
+ if (patient.tipoIdentificacion === 'pasaporte') {
126
+ identificadores.push({
127
+ system: 'andes.gob.ar/sid/passport',
128
+ value: patient.numeroIdentificacion
129
+ });
130
+ }
131
+ }
132
+ // Contactos → telecom
133
+ const contactos = (patient.contacto ?? [])
134
+ .filter((c) => !!c.valor)
135
+ .map((unContacto) => {
136
+ const cont = {
137
+ value: unContacto.valor,
138
+ rank: unContacto.ranking
139
+ };
140
+ switch (unContacto.tipo) {
141
+ case 'fijo':
142
+ case 'celular':
143
+ cont.system = 'phone';
144
+ break;
145
+ case 'email':
146
+ cont.system = 'email';
147
+ break;
148
+ }
149
+ return cont;
150
+ });
151
+ // Direcciones → address
152
+ const direcciones = (patient.direccion ?? [])
153
+ .filter((dir) => !!dir.ubicacion?.localidad)
154
+ .map((unaDireccion) => {
155
+ const city = typeof unaDireccion.ubicacion.localidad === 'object'
156
+ ? unaDireccion.ubicacion.localidad?.nombre
157
+ : unaDireccion.ubicacion.localidad;
158
+ const state = typeof unaDireccion.ubicacion.provincia === 'object'
159
+ ? unaDireccion.ubicacion.provincia?.nombre
160
+ : unaDireccion.ubicacion.provincia;
161
+ const country = typeof unaDireccion.ubicacion.pais === 'object'
162
+ ? unaDireccion.ubicacion.pais?.nombre
163
+ : unaDireccion.ubicacion.pais;
164
+ return {
165
+ postalCode: unaDireccion.codigoPostal ?? '',
166
+ line: [unaDireccion.valor],
167
+ city: city ?? '',
168
+ state: state ?? '',
169
+ country: country ?? ''
170
+ };
171
+ });
172
+ // Relaciones → contact
173
+ const relacionesFHIR = (patient.relaciones ?? [])
174
+ .filter((r) => !!r.relacion)
175
+ .map((unaRelacion) => {
176
+ return {
177
+ relationship: [{
178
+ text: unaRelacion.relacion.nombre
179
+ }],
180
+ name: {
181
+ family: unaRelacion.apellido,
182
+ given: unaRelacion.nombre.split(' ')
183
+ }
184
+ };
185
+ });
186
+ // Género
187
+ // const generoFHIR = mapGeneroAndesToFHIR(patient.genero ?? patient.sexo);
188
+ const generoFHIR = mapSexoAndesToGenderFHIR(patient.sexo ?? patient.genero);
189
+ const genderIdentityExtensions = buildGenderIdentityExtension(patient.genero);
190
+ const statusExtensions = buildStatusExtension(patient.estado);
191
+ const birthDate = formatDateOnly(patient.fechaNacimiento);
192
+ const extensions = [...statusExtensions, ...genderIdentityExtensions];
193
+ const pacienteFHIR = {
194
+ resourceType: 'Patient',
195
+ id: patient._id ?? patient.id,
196
+ identifier: identificadores,
197
+ active: patient.activo ?? undefined,
198
+ name: [{
199
+ use: 'official',
200
+ family: patient.apellido,
201
+ given: patient.nombre.split(' '),
202
+ text: `${patient.nombre} ${patient.apellido}`
203
+ }],
204
+ gender: generoFHIR,
205
+ birthDate,
206
+ ...(extensions.length > 0 && { extension: extensions })
207
+ };
208
+ if (patient.fechaFallecimiento) {
209
+ const deceased = formatDateTime(patient.fechaFallecimiento);
210
+ if (deceased) {
211
+ pacienteFHIR.deceasedDateTime = deceased;
212
+ }
213
+ }
214
+ if (patient.estadoCivil) {
215
+ pacienteFHIR.maritalStatus = {
216
+ text: mapEstadoCivilAndesToFHIR(patient.estadoCivil)
217
+ };
218
+ }
219
+ if (patient.foto) {
220
+ pacienteFHIR.photo = [{ data: patient.foto }];
221
+ }
222
+ if (contactos.length > 0) {
223
+ pacienteFHIR.telecom = contactos;
224
+ }
225
+ if (direcciones.length > 0) {
226
+ pacienteFHIR.address = direcciones;
227
+ }
228
+ if (relacionesFHIR.length > 0) {
229
+ pacienteFHIR.contact = relacionesFHIR;
230
+ }
231
+ if (patient.createdBy?.organizacion) {
232
+ const managingOrganization = {
233
+ reference: patient.createdBy.organizacion.id,
234
+ display: patient.createdBy.organizacion.nombre
235
+ };
236
+ pacienteFHIR.managingOrganization = managingOrganization;
237
+ }
238
+ return pacienteFHIR;
239
+ }
240
+ exports.encode = encode;
241
+ /**
242
+ * Decode a patient from FHIR to ANDES
243
+ */
244
+ function decode(patient) {
245
+ let genero;
246
+ let sexo;
247
+ // Cuando el paciente viene por FHIR suponemos el valor del género
248
+ genero = mapGeneroFHIRToAndes(patient.gender);
249
+ sexo = genero;
250
+ function getValue(items, key) {
251
+ if (!items)
252
+ return undefined;
253
+ const element = items.find(el => el.system === key);
254
+ return element?.value;
255
+ }
256
+ const tiposIdentificacion = ['andes.gob.ar/sid/foreign-id', 'andes.gob.ar/sid/passport'];
257
+ const tipoAndes = ['dni extranjero', 'pasaporte'];
258
+ let tipoIdentificacion;
259
+ let numeroIdentificacion;
260
+ for (let i = 0; i < tiposIdentificacion.length; i++) {
261
+ const val = getValue(patient.identifier, tiposIdentificacion[i]);
262
+ if (val) {
263
+ tipoIdentificacion = tipoAndes[i];
264
+ numeroIdentificacion = val;
265
+ }
266
+ }
267
+ const firstName = patient.name?.[0];
268
+ const nombre = firstName
269
+ ? (firstName.given ?? []).join(' ').trim()
270
+ : '';
271
+ const apellido = firstName
272
+ ? (Array.isArray(firstName.family)
273
+ ? firstName.family.join(' ').trim()
274
+ : (firstName.family ?? ''))
275
+ : '';
276
+ const pacienteAndes = {
277
+ id: getValue(patient.identifier, (0, config_1.makeUrl)('Patient')) ?? patient.id,
278
+ documento: getValue(patient.identifier, 'http://www.renaper.gob.ar/dni'),
279
+ tipoIdentificacion,
280
+ numeroIdentificacion,
281
+ nombre,
282
+ apellido,
283
+ fechaNacimiento: patient.birthDate,
284
+ genero,
285
+ sexo,
286
+ estado: 'temporal'
287
+ };
288
+ const contactos = patient.telecom
289
+ ? patient.telecom.map((unContacto) => {
290
+ const cont = {
291
+ valor: unContacto.value,
292
+ ranking: unContacto.rank
293
+ };
294
+ switch (unContacto.system) {
295
+ case 'phone':
296
+ cont.tipo = 'celular';
297
+ break;
298
+ case 'email':
299
+ cont.tipo = 'email';
300
+ break;
301
+ }
302
+ return cont;
303
+ })
304
+ : [];
305
+ const relaciones = patient.contact
306
+ ? patient.contact.map((aContact) => {
307
+ const relText = aContact.relationship?.[0]?.text ?? '';
308
+ const givenName = (aContact.name?.given ?? []).join(' ').replace(',', ' ');
309
+ const familyName = Array.isArray(aContact.name?.family)
310
+ ? (aContact.name?.family).join(' ').replace(',', ' ')
311
+ : aContact.name?.family ?? '';
312
+ return {
313
+ relacion: { nombre: relText },
314
+ nombre: givenName,
315
+ apellido: familyName
316
+ };
317
+ })
318
+ : [];
319
+ if (patient.maritalStatus?.text) {
320
+ pacienteAndes.estadoCivil = mapEstadoCivilFHIRToAndes(patient.maritalStatus.text);
321
+ }
322
+ const direcciones = patient.address
323
+ ? patient.address.map((unaDireccion) => {
324
+ const valor = Array.isArray(unaDireccion.line)
325
+ ? (unaDireccion.line[0] ?? '')
326
+ : unaDireccion.line ?? '';
327
+ const dir = {
328
+ activo: true,
329
+ valor,
330
+ codigoPostal: unaDireccion.postalCode,
331
+ ubicacion: {
332
+ pais: unaDireccion.country,
333
+ provincia: unaDireccion.state,
334
+ localidad: unaDireccion.city
335
+ }
336
+ };
337
+ return dir;
338
+ })
339
+ : [];
340
+ pacienteAndes.direccion = direcciones;
341
+ if (patient.active !== undefined) {
342
+ pacienteAndes.activo = patient.active;
343
+ }
344
+ if (contactos.length > 0) {
345
+ pacienteAndes.contacto = contactos;
346
+ }
347
+ if (patient.photo && patient.photo.length > 0) {
348
+ pacienteAndes.foto = patient.photo[0].data;
349
+ }
350
+ if (relaciones.length > 0) {
351
+ pacienteAndes.relaciones = relaciones;
352
+ }
353
+ if (patient.managingOrganization) {
354
+ pacienteAndes.createdBy = {
355
+ organizacion: {
356
+ id: patient.managingOrganization.reference ?? '',
357
+ nombre: patient.managingOrganization.display ?? ''
358
+ }
359
+ };
360
+ }
361
+ return pacienteAndes;
362
+ }
363
+ exports.decode = decode;
364
+ /**
365
+ * Verify if a patient has a FHIR format
366
+ */
367
+ function verify(patient) {
368
+ let respuesta = true;
369
+ const fieldVerified = Object.keys(patient).every(pacienteFHIRFields);
370
+ if (fieldVerified) {
371
+ respuesta = ('resourceType' in patient) && patient.resourceType === 'Patient';
372
+ respuesta = respuesta && ('identifier' in patient);
373
+ if (patient.identifier?.length > 0) {
374
+ patient.identifier.forEach((anIdentifier) => {
375
+ respuesta = respuesta && Object.keys(anIdentifier).every(identifierFields);
376
+ });
377
+ }
378
+ patient.name?.forEach((aName) => {
379
+ respuesta = respuesta && validName(aName);
380
+ });
381
+ if (patient.active !== undefined) {
382
+ respuesta = respuesta && (typeof patient.active === 'boolean');
383
+ }
384
+ if (patient.telecom) {
385
+ patient.telecom.forEach((aTelecom) => {
386
+ respuesta = respuesta && Object.keys(aTelecom).every(telecomFields);
387
+ });
388
+ }
389
+ if (patient.gender) {
390
+ respuesta = respuesta && patient.gender.match('male|female|other|unknown') != null;
391
+ }
392
+ if (patient.birthDate) {
393
+ respuesta = respuesta && typeof patient.birthDate === 'string';
394
+ }
395
+ if (patient.deceasedDateTime) {
396
+ respuesta = respuesta && typeof patient.deceasedDateTime === 'string';
397
+ }
398
+ if (patient.address) {
399
+ patient.address.forEach((anAddress) => {
400
+ respuesta = respuesta && Object.keys(anAddress).every(addressFields);
401
+ });
402
+ }
403
+ if (patient.maritalStatus && patient.maritalStatus.text) {
404
+ respuesta = respuesta &&
405
+ Object.keys(patient.maritalStatus).every(codingFields) &&
406
+ typeof patient.maritalStatus.text === 'string' &&
407
+ patient.maritalStatus.text.match('Married|Divorced|Widowed|unmarried|unknown') != null;
408
+ }
409
+ if (patient.photo) {
410
+ patient.photo.forEach((aPhoto) => {
411
+ respuesta = respuesta && Object.keys(aPhoto).every(photoFields);
412
+ });
413
+ }
414
+ if (patient.contact) {
415
+ patient.contact.forEach((aContact) => {
416
+ if (aContact.relationship) {
417
+ aContact.relationship.forEach((aRelation) => {
418
+ respuesta = respuesta && Object.keys(aRelation).every(codingFields);
419
+ });
420
+ }
421
+ if (aContact.name) {
422
+ respuesta = respuesta && validName(aContact.name);
423
+ }
424
+ });
425
+ }
426
+ }
427
+ else {
428
+ respuesta = fieldVerified;
429
+ }
430
+ return respuesta;
431
+ }
432
+ exports.verify = verify;
433
+ /**
434
+ * Verify helpers
435
+ */
436
+ function pacienteFHIRFields(elem) {
437
+ return elem.match('resourceType|identifier|active|name|telecom|gender|birthDate|deceasedBoolean|deceasedDateTime|address|maritalStatus|photo|contact') != null;
438
+ }
439
+ function identifierFields(elem) {
440
+ return elem.match('use|type|system|value|period|assigner') != null;
441
+ }
442
+ function nameFields(elem) {
443
+ return elem.match('resourceType|family|given') != null;
444
+ }
445
+ function telecomFields(elem) {
446
+ return elem.match('resourceType|system|value|use|rank|period') != null;
447
+ }
448
+ function addressFields(elem) {
449
+ return elem.match('resourceType|use|type|text|line|city|district|state|postalCode|country|period') != null;
450
+ }
451
+ function codingFields(elem) {
452
+ return elem.match('coding|text') != null;
453
+ }
454
+ function photoFields(elem) {
455
+ return elem.match('contentType|language|data|url|size|hash|title|creation') != null;
456
+ }
457
+ function validName(aName) {
458
+ return Object.keys(aName).every(nameFields) &&
459
+ ('resourceType' in aName) && aName.resourceType === 'HumanName' &&
460
+ ('family' in aName) && Array.isArray(aName.family) && aName.family.every(areStrings) &&
461
+ ('given' in aName) && Array.isArray(aName.given) && aName.given.every(areStrings);
462
+ }
463
+ function areStrings(elem) {
464
+ return typeof elem === 'string';
465
+ }
@@ -0,0 +1 @@
1
+ export {};