1 """GNUmed family history handling middleware"""
2
3 __license__ = "GPL"
4 __author__ = "K.Hilbert <Karsten.Hilbert@gmx.net>"
5
6
7
8 import sys, logging
9
10
11
12 if __name__ == '__main__':
13 sys.path.insert(0, '../../')
14 from Gnumed.pycommon import gmPG2
15 from Gnumed.pycommon import gmBusinessDBObject
16 from Gnumed.pycommon import gmDateTime
17 from Gnumed.pycommon import gmTools
18
19 from Gnumed.business import gmCoding
20
21
22 _log = logging.getLogger('gm.fhx')
23
24
25
26
28
29 args = {'rel': relationship, 'gen': genetic}
30
31
32 cmd = """
33 SELECT *, _(description) as l10n_description
34 FROM clin.fhx_relation_type
35 WHERE
36 description = %(rel)s
37 OR
38 _(description) = %(rel)s
39 """
40 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}])
41 if len(rows) > 0:
42 return rows[0]
43
44
45 cmd = """
46 INSERT INTO clin.fhx_relation_type (
47 description,
48 is_genetic
49 ) VALUES (
50 i18n.i18n(gm.nullify_empty_string(%(rel)s)),
51 %(gen)s
52 )
53 RETURNING *
54 """
55 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True)
56 return rows[0]
57
58
59
60
61 _SQL_get_family_history = "SELECT * from clin.v_family_history WHERE %s"
62
63 -class cFamilyHistory(gmBusinessDBObject.cBusinessDBObject):
64 """Represents a Family History item."""
65
66 _cmd_fetch_payload = _SQL_get_family_history % "pk_family_history = %s"
67 _cmds_store_payload = [
68 """
69 UPDATE clin.family_history SET
70 narrative = gm.nullify_empty_string(%(condition)s),
71 age_noted = gm.nullify_empty_string(%(age_noted)s),
72 age_of_death = %(age_of_death)s,
73 contributed_to_death = %(contributed_to_death)s,
74 clin_when = %(when_known_to_patient)s,
75 name_relative = gm.nullify_empty_string(%(name_relative)s),
76 dob_relative = %(dob_relative)s,
77 comment = gm.nullify_empty_string(%(comment)s),
78 fk_episode = %(pk_episode)s,
79 fk_relation_type = %(pk_fhx_relation_type)s
80 WHERE
81 pk = %(pk_family_history)s
82 AND
83 xmin = %(xmin_family_history)s
84 RETURNING
85 pk as pk_family_history,
86 xmin as xmin_family_history
87 """
88 ]
89
90 _updatable_fields = [
91 'condition',
92 'age_noted',
93 'age_of_death',
94 'contributed_to_death',
95 'when_known_to_patient',
96 'name_relative',
97 'dob_relative',
98 'pk_encounter',
99 'pk_episode',
100 'pk_fhx_relation_type',
101 'comment'
102 ]
103
104
105 - def add_code(self, pk_code=None):
106 """<pk_code> must be a value from ref.coding_system_root.pk_coding_system (clin.lnk_code2item_root.fk_generic_code)"""
107
108 if pk_code in self._payload[self._idx['pk_generic_codes']]:
109 return
110
111 cmd = """
112 INSERT INTO clin.lnk_code2fhx
113 (fk_item, fk_generic_code)
114 SELECT
115 %(item)s,
116 %(code)s
117 WHERE NOT EXISTS (
118 SELECT 1 FROM clin.lnk_code2fhx
119 WHERE
120 fk_item = %(item)s
121 AND
122 fk_generic_code = %(code)s
123 )"""
124 args = {
125 'item': self._payload[self._idx['pk_family_history']],
126 'code': pk_code
127 }
128 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
129 return
130
131
132 - def remove_code(self, pk_code=None):
133 """<pk_code> must be a value from ref.coding_system_root.pk_coding_system (clin.lnk_code2item_root.fk_generic_code)"""
134 cmd = "DELETE FROM clin.lnk_code2fhx WHERE fk_item = %(item)s AND fk_generic_code = %(code)s"
135 args = {
136 'item': self._payload[self._idx['pk_family_history']],
137 'code': pk_code
138 }
139 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
140 return True
141
142
144
145
146
147 return self.format (
148 include_episode = True,
149 include_comment = True,
150 include_codes = True
151 ).split('\n')
152
153
154 - def format(self, left_margin=0, include_episode=False, include_comment=False, include_codes=False):
155
156 line = '%s%s' % (
157 (' ' * left_margin),
158 self._payload[self._idx['l10n_relation']]
159 )
160 if self._payload[self._idx['age_of_death']] is not None:
161 line += ' (%s %s)' % (
162 gmTools.u_latin_cross,
163 gmDateTime.format_interval_medically(self._payload[self._idx['age_of_death']])
164 )
165 line += ': %s' % self._payload[self._idx['condition']]
166 if self._payload[self._idx['age_noted']] is not None:
167 line += gmTools.coalesce(self._payload[self._idx['age_noted']], '', ' (@ %s)')
168 if self._payload[self._idx['contributed_to_death']]:
169 line += ' %s %s' % (
170 gmTools.u_arrow2right,
171 gmTools.u_skull_and_crossbones
172 )
173
174 if include_episode:
175 line += '\n%s %s: %s' % (
176 (' ' * left_margin),
177 _('Episode'),
178 self._payload[self._idx['episode']]
179 )
180
181 if include_comment:
182 if self._payload[self._idx['comment']] is not None:
183 line += '\n%s %s' % (
184 (' ' * left_margin),
185 self._payload[self._idx['comment']]
186 )
187
188 if include_codes:
189 codes = self.generic_codes
190 if len(codes) > 0:
191 line += '\n'
192 for c in codes:
193 line += '%s %s: %s (%s - %s)\n' % (
194 (' ' * left_margin),
195 c['code'],
196 c['term'],
197 c['name_short'],
198 c['version']
199 )
200 del codes
201
202 return line
203
204
205
206
208 if len(self._payload[self._idx['pk_generic_codes']]) == 0:
209 return []
210
211 cmd = gmCoding._SQL_get_generic_linked_codes % 'pk_generic_code IN %(pks)s'
212 args = {'pks': tuple(self._payload[self._idx['pk_generic_codes']])}
213 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True)
214 return [ gmCoding.cGenericLinkedCode(row = {'data': r, 'idx': idx, 'pk_field': 'pk_lnk_code2item'}) for r in rows ]
215
216 - def _set_generic_codes(self, pk_codes):
217 queries = []
218
219 if len(self._payload[self._idx['pk_generic_codes']]) > 0:
220 queries.append ({
221 'cmd': 'DELETE FROM clin.lnk_code2fhx WHERE fk_item = %(fhx)s AND fk_generic_code IN %(codes)s',
222 'args': {
223 'fhx': self._payload[self._idx['pk_family_history']],
224 'codes': tuple(self._payload[self._idx['pk_generic_codes']])
225 }
226 })
227
228 for pk_code in pk_codes:
229 queries.append ({
230 'cmd': 'INSERT INTO clin.lnk_code2fhx (fk_item, fk_generic_code) VALUES (%(fhx)s, %(pk_code)s)',
231 'args': {
232 'fhx': self._payload[self._idx['pk_family_history']],
233 'pk_code': pk_code
234 }
235 })
236 if len(queries) == 0:
237 return
238
239 rows, idx = gmPG2.run_rw_queries(queries = queries)
240 return
241
242 generic_codes = property(_get_generic_codes, _set_generic_codes)
243
244 -def get_family_history(order_by=None, patient=None):
245
246 args = {}
247 where_parts = []
248
249 if patient is not None:
250 where_parts.append('pk_patient = %(pat)s')
251 args['pat'] = patient
252
253 if order_by is None:
254 if len(where_parts) == 0:
255 order_by = 'true'
256 else:
257 order_by = ''
258 else:
259 if len(where_parts) == 0:
260 order_by = 'true ORDER BY %s' % order_by
261 else:
262 order_by = 'ORDER BY %s' % order_by
263
264 cmd = _SQL_get_family_history % ' AND '.join(where_parts) + ' ' + order_by
265 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True)
266 return [ cFamilyHistory(row = {'data': r, 'idx': idx, 'pk_field': 'pk_family_history'}) for r in rows ]
267
268 -def create_family_history(encounter=None, episode=None, condition=None, relation=None):
269
270 args = {
271 'enc': encounter,
272 'epi': episode,
273 'cond': condition,
274 'rel': relation
275 }
276 cmd = """
277 INSERT INTO clin.family_history (
278 soap_cat,
279 fk_encounter,
280 fk_episode,
281 narrative,
282 fk_relation_type
283 ) VALUES (
284 's'::text,
285 %(enc)s,
286 %(epi)s,
287 gm.nullify_empty_string(%(cond)s),
288 %(rel)s
289 )
290 RETURNING pk
291 """
292 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True, get_col_idx = False)
293
294 return cFamilyHistory(aPK_obj = rows[0]['pk'])
295
296 -def delete_family_history(pk_family_history=None):
297 args = {'pk': pk_family_history}
298 cmd = "DELETE FROM clin.family_history WHERE pk = %(pk)s"
299 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
300 return True
301
302
303
304 if __name__ == "__main__":
305
306 if len(sys.argv) < 2:
307 sys.exit()
308
309 if sys.argv[1] != 'test':
310 sys.exit()
311
312
317
318 test_get_fhx()
319
320
321