| Home | Trees | Indices | Help |
|
|---|
|
|
1 # -*- coding: utf-8 -*-
2 """GNUmed allergy related business object."""
3 #============================================================
4 __author__ = "Carlos Moro <cfmoro1976@yahoo.es>"
5 __license__ = "GPL v2 or later"
6
7 import types, sys, logging, datetime as pyDT
8
9
10 if __name__ == '__main__':
11 sys.path.insert(0, '../../')
12 from Gnumed.pycommon import gmPG2
13 from Gnumed.pycommon import gmI18N
14 from Gnumed.pycommon import gmBusinessDBObject
15 from Gnumed.pycommon import gmDateTime
16 from Gnumed.pycommon import gmTools
17
18
19 _log = logging.getLogger('gm.domain')
20 #============================================================
21 # allergy state related code
22 #============================================================
23 allergy_states = [
24 None, # unknown
25 0, # no allergies
26 1 # some allergies
27 ]
28 #------------------------------------------------------------
30
31 _log.debug('checking allergy state for identity of encounter [%s]', encounter)
32
33 args = {'enc': encounter}
34 cmd_create = """
35 INSERT INTO clin.allergy_state (
36 fk_encounter,
37 has_allergy
38 ) SELECT
39 %(enc)s,
40 NULL
41 WHERE NOT EXISTS (
42 SELECT 1 FROM clin.v_pat_allergy_state
43 WHERE pk_patient = (
44 SELECT fk_patient FROM clin.encounter WHERE pk = %(enc)s
45 )
46 )
47 """
48 cmd_search = """
49 SELECT pk_allergy_state FROM clin.v_pat_allergy_state
50 WHERE pk_patient = (
51 SELECT fk_patient FROM clin.encounter WHERE pk = %(enc)s
52 )
53 """
54 rows, idx = gmPG2.run_rw_queries (
55 queries = [
56 {'cmd': cmd_create, 'args': args},
57 {'cmd': cmd_search, 'args': args}
58 ],
59 return_data = True
60 )
61
62 return cAllergyState(aPK_obj = rows[0][0])
63
64 #------------------------------------------------------------
66 """Represents the allergy state of one patient."""
67
68 _cmd_fetch_payload = "select * from clin.v_pat_allergy_state where pk_allergy_state = %s"
69 _cmds_store_payload = [
70 """update clin.allergy_state set
71 last_confirmed = %(last_confirmed)s,
72 has_allergy = %(has_allergy)s,
73 comment = gm.nullify_empty_string(%(comment)s)
74 where
75 pk = %(pk_allergy_state)s and
76 xmin = %(xmin_allergy_state)s""",
77 """select xmin_allergy_state from clin.v_pat_allergy_state where pk_allergy_state = %(pk_allergy_state)s"""
78 ]
79 _updatable_fields = [
80 'last_confirmed', # special value u'now' will set to datetime.datetime.now() in the local time zone
81 'has_allergy', # verified against allergy_states (see above)
82 'comment' # u'' maps to None / NULL
83 ]
84
85 #--------------------------------------------------------
87 lines = []
88 lines.append('%s (%s)' % (
89 self.state_string,
90 gmDateTime.pydt_strftime(self['last_confirmed'], '%Y %b %d', none_str = '?')
91 ))
92 if self._payload[self._idx['comment']] is not None:
93 lines.append(' %s' % self._payload[self._idx['comment']])
94 return lines
95
96 #--------------------------------------------------------
97 # properties
98 #--------------------------------------------------------
100 if self._payload[self._idx['has_allergy']] is None:
101 return _('unknown allergy state')
102 if self._payload[self._idx['has_allergy']] == 0:
103 return _('no known allergies')
104 if self._payload[self._idx['has_allergy']] == 1:
105 return _('*does* have allergies')
106 _log.error('unknown allergy state [%s]', self._payload[self._idx['has_allergy']])
107 return _('ERROR: unknown allergy state [%s]') % self._payload[self._idx['has_allergy']]
108
111
112 state_string = property(_get_as_string, _set_string)
113
114 #--------------------------------------------------------
116 if self._payload[self._idx['has_allergy']] is None:
117 if self._payload[self._idx['comment']] is None:
118 return '?'
119 else:
120 return '?!'
121 if self._payload[self._idx['has_allergy']] == 0:
122 if self._payload[self._idx['comment']] is None:
123 return '\u2300'
124 else:
125 return '\u2300!'
126 if self._payload[self._idx['has_allergy']] == 1:
127 return '!'
128 _log.error('unknown allergy state [%s]', self._payload[self._idx['has_allergy']])
129 return _('ERROR: unknown allergy state [%s]') % self._payload[self._idx['has_allergy']]
130
131 state_symbol = property(_get_as_symbol, lambda x:x)
132
133 #--------------------------------------------------------
135 table_rows = []
136 # Trennzeile als leere Zeile für bessere Lesbarkeit
137 table_rows.append('\\multicolumn{11}{l}{}\\tabularnewline')
138 # Zwischenüberschrift: 31 Zeichen, $..., 14pt, no frame, \textwidth
139 state = '%s (%s)' % (
140 self.state_string,
141 gmDateTime.pydt_strftime(self['last_confirmed'], '%b %Y', none_str = '?')
142 )
143 if strict:
144 state = state[:31]
145 table_rows.append('\\multicolumn{11}{>{\\RaggedRight}p{27.9cm}}{\\rule{0pt}{4.5mm} \\fontsize{14pt}{16pt}\selectfont %s\label{AnchorAllergieDetails}}\\tabularnewline' % gmTools.tex_escape_string(state))
146 # Freitextzeile: 200 Zeichen, @..., \textwidth
147 if self['comment'] is not None:
148 if strict:
149 cmt = self['comment'].strip()[:200]
150 else:
151 cmt = self['comment'].strip()
152 table_rows.append('\\multicolumn{11}{>{\\RaggedRight}p{27.9cm}}{%s}\\tabularnewline') % gmTools.tex_escape_string(cmt)
153 return table_rows
154
155 as_amts_latex = property(_get_as_amts_latex, lambda x:x)
156
157 #--------------------------------------------------------
159 lines = []
160 # Trennzeile für bessere Lesbarkeit als leere Zwischenüberschrift
161 lines.append('$ ')
162 # Zwischenüberschrift: 31 Zeichen, $..., \textwidth
163 txt = '$%s (%s)' % (
164 self.state_string,
165 gmDateTime.pydt_strftime(self['last_confirmed'], '%b %Y', none_str = '?')
166 )
167 if strict:
168 lines.append(txt[:32])
169 else:
170 lines.append(txt)
171 # Freitextzeile: 200 Zeichen, @..., \textwidth
172 if self['comment'] is not None:
173 if strict:
174 lines.append('@%s' % self['comment'][:200])
175 else:
176 lines.append('@%s' % self['comment'])
177 return lines
178
179 #--------------------------------------------------------
181 # Zwischenüberschrift
182 state = '%s (%s)' % (self.state_string, gmDateTime.pydt_strftime(self['last_confirmed'], '%b %Y', none_str = '?'))
183 if strict:
184 state = state[:32]
185 # Freitextzeile
186 if self['comment'] is None:
187 comment = ''
188 else:
189 comment = '<X t="%s"/>' % self['comment']
190 if strict:
191 comment = '<X t="%s"/>' % self['comment'][:200]
192 return '<S t="%s">%s%%s</S>' % (state, comment)
193
194 as_amts_data = property(_get_as_amts_data, lambda x:x)
195
196 #--------------------------------------------------------
198 if attribute == 'comment':
199 if value is not None:
200 if value.strip() == '':
201 value = None
202
203 elif attribute == 'last_confirmed':
204 if value == 'now':
205 value = pyDT.datetime.now(tz = gmDateTime.gmCurrentLocalTimezone)
206
207 elif attribute == 'has_allergy':
208 if value not in allergy_states:
209 raise ValueError('invalid allergy state [%s]' % value)
210
211 gmBusinessDBObject.cBusinessDBObject.__setitem__(self, attribute, value)
212
213 #============================================================
215 """Represents one allergy item.
216
217 Actually, those things are really things to "avoid".
218 Allergy is just one of several reasons for that.
219 See Adrian's post on gm-dev.
220
221 Another word might be Therapeutic Precautions.
222 """
223 _cmd_fetch_payload = "SELECT * FROM clin.v_pat_allergies WHERE pk_allergy = %s"
224 _cmds_store_payload = [
225 """UPDATE clin.allergy SET
226 clin_when = %(date)s,
227 substance = %(substance)s,
228 substance_code = %(substance_code)s,
229 generics = %(generics)s,
230 allergene = %(allergene)s,
231 atc_code = %(atc_code)s,
232 fk_type = %(pk_type)s,
233 generic_specific = %(generic_specific)s::boolean,
234 definite = %(definite)s::boolean,
235 narrative = %(reaction)s
236 WHERE
237 pk = %(pk_allergy)s AND
238 xmin = %(xmin_allergy)s""",
239 """SELECT xmin_allergy FROM clin.v_pat_allergies WHERE pk_allergy=%(pk_allergy)s"""
240 ]
241 _updatable_fields = [
242 'date',
243 'substance',
244 'substance_code',
245 'generics',
246 'allergene',
247 'atc_code',
248 'pk_type',
249 'generic_specific',
250 'definite',
251 'reaction'
252 ]
253 #--------------------------------------------------------
255 lines = []
256 lines.append('%s%s: %s [#%s]' % (
257 self._payload[self._idx['l10n_type']],
258 gmTools.bool2subst (
259 self._payload[self._idx['definite']],
260 ' (%s)' % _('definite'),
261 ' (%s)' % _('indefinite'),
262 ''
263 ),
264 self._payload[self._idx['descriptor']],
265 self._payload[self._idx['pk_allergy']]
266 ))
267 if self._payload[self._idx['reaction']] is not None:
268 lines.append(' ' + _('Reaction:') + ' ' + self._payload[self._idx['reaction']])
269 if self._payload[self._idx['date']] is not None:
270 lines.append(' ' + _('Noted:') + ' ' + gmDateTime.pydt_strftime(self._payload[self._idx['date']], '%Y %b %d'))
271 if self._payload[self._idx['allergene']] is not None:
272 lines.append(' ' + _('Allergene:') + ' ' + self._payload[self._idx['allergene']])
273 if self._payload[self._idx['substance']] is not None:
274 lines.append(' ' + _('Substance:') + ' ' + self._payload[self._idx['substance']])
275 if self._payload[self._idx['substance_code']] is not None:
276 lines.append(' ' + _('Code:') + ' ' + self._payload[self._idx['substance_code']])
277 if self._payload[self._idx['atc_code']] is not None:
278 lines.append(' ' + _('ATC:') + ' ' + self._payload[self._idx['atc_code']])
279 lines.append(' ' + _('Specific to:') + ' ' + gmTools.bool2subst (
280 self._payload[self._idx['generic_specific']],
281 _('this substance only'),
282 _('drug class'),
283 _('unknown')
284 ))
285 if self._payload[self._idx['generics']] is not None:
286 lines.append(' ' + _('Generics:') + ' ' + self._payload[self._idx['generics']])
287
288 return lines
289
290 #--------------------------------------------------------
292 if attribute == 'pk_type':
293 if value in ['allergy', 'sensitivity']:
294 cmd = 'select pk from clin._enum_allergy_type where value=%s'
295 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': [value]}])
296 value = rows[0][0]
297
298 gmBusinessDBObject.cBusinessDBObject.__setitem__(self, attribute, value)
299
300 #--------------------------------------------------------
302 # Freitextzeile: 200 Zeichen, @...
303 cells = ['\\multicolumn{1}{>{\\RaggedRight}p{4cm}}{%s}' % gmTools.tex_escape_string(self['descriptor'])]
304 txt = '%s%s' % (
305 self['l10n_type'],
306 gmTools.coalesce(self['reaction'], '', ': %s')
307 )
308 if strict:
309 txt = txt[:(200-len(self['descriptor']))]
310 cells.append('\\multicolumn{10}{>{\\RaggedRight}p{23.9cm}}{%s}' % gmTools.tex_escape_string(txt))
311 table_row = ' & '.join(cells)
312 table_row += '\\tabularnewline'
313 return table_row
314
315 as_amts_latex = property(_get_as_amts_latex, lambda x:x)
316
317 #--------------------------------------------------------
319 # Freitextzeile: 200 Zeichen, @..., \textwidth
320 txt = '@%s %s%s' % (
321 self['descriptor'],
322 self['l10n_type'],
323 gmTools.coalesce(self['reaction'], '', ': %s')
324 )
325 if strict:
326 return txt[:200]
327 return txt
328
329 #--------------------------------------------------------
331 txt = '%s %s%s' % (
332 self['descriptor'],
333 self['l10n_type'],
334 gmTools.coalesce(self['reaction'], '', ': %s')
335 )
336 if strict:
337 txt = txt[:200]
338 # Freitextzeile: 200 Zeichen
339 return '<X t="%s"/>' % txt
340
341 as_amts_data = property(_get_as_amts_data, lambda x:x)
342
343 #============================================================
344 # convenience functions
345 #------------------------------------------------------------
347 """Creates a new allergy clinical item.
348
349 allergene - allergic substance
350 allg_type - allergy or sensitivity, pk or string
351 encounter_id - encounter's primary key
352 episode_id - episode's primary key
353 """
354 cmd = """
355 SELECT pk_allergy
356 FROM clin.v_pat_allergies
357 WHERE
358 pk_patient = (SELECT fk_patient FROM clin.encounter WHERE pk = %(enc)s)
359 AND
360 allergene = %(allergene)s
361 """
362 #args = {'enc': encounter_id, 'substance': substance}
363 args = {'enc': encounter_id, 'allergene': allergene}
364 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}])
365 if len(rows) > 0:
366 # don't implicitely change existing data
367 return cAllergy(aPK_obj = rows[0][0])
368
369 # insert new allergy
370 queries = []
371
372 if type(allg_type) == int:
373 cmd = """
374 insert into clin.allergy (fk_type, fk_encounter, fk_episode, allergene, substance)
375 values (%s, %s, %s, %s, %s)"""
376 else:
377 cmd = """
378 insert into clin.allergy (fk_type, fk_encounter, fk_episode, allergene, substance)
379 values ((select pk from clin._enum_allergy_type where value = %s), %s, %s, %s, %s)"""
380 queries.append({'cmd': cmd, 'args': [allg_type, encounter_id, episode_id, allergene, allergene]})
381
382 cmd = "select currval('clin.allergy_id_seq')"
383 queries.append({'cmd': cmd})
384
385 rows, idx = gmPG2.run_rw_queries(queries=queries, return_data=True)
386 allergy = cAllergy(aPK_obj = rows[0][0])
387
388 return allergy
389
390 #============================================================
391 # main - unit testing
392 #------------------------------------------------------------
393 if __name__ == '__main__':
394
395 allg = cAllergy(aPK_obj=1)
396 print(allg)
397 fields = allg.get_fields()
398 for field in fields:
399 print(field, ':', allg[field])
400 print("updatable:", allg.get_updatable_fields())
401 enc_id = allg['pk_encounter']
402 epi_id = allg['pk_episode']
403 status, allg = create_allergy (
404 allergene = 'test substance',
405 allg_type = 1,
406 episode_id = epi_id,
407 encounter_id = enc_id
408 )
409 print(allg)
410 allg['reaction'] = 'hehehe'
411 status, data = allg.save_payload()
412 print('status:', status)
413 print('data:', data)
414 print(allg)
415
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Fri Jan 25 02:55:27 2019 | http://epydoc.sourceforge.net |