1 """GNUmed hospital stay widgets"""
2
3 __author__ = "cfmoro1976@yahoo.es, karsten.hilbert@gmx.net"
4 __license__ = "GPL v2 or later"
5
6
7 import sys
8 import logging
9 import datetime as pydt
10
11
12
13 import wx
14
15
16
17 if __name__ == '__main__':
18 sys.path.insert(0, '../../')
19 from Gnumed.pycommon import gmI18N
20 from Gnumed.pycommon import gmDateTime
21 if __name__ == '__main__':
22 gmI18N.activate_locale()
23 gmI18N.install_domain()
24 gmDateTime.init()
25
26 from Gnumed.pycommon import gmTools
27 from Gnumed.pycommon import gmDispatcher
28 from Gnumed.pycommon import gmMatchProvider
29
30 from Gnumed.business import gmEMRStructItems
31 from Gnumed.business import gmPerson
32
33 from Gnumed.wxpython import gmPhraseWheel
34 from Gnumed.wxpython import gmListWidgets
35 from Gnumed.wxpython import gmEditArea
36
37
38 _log = logging.getLogger('gm.ui')
39
40
41
42
44
45 pat = gmPerson.gmCurrentPatient()
46 emr = pat.emr
47
48 if parent is None:
49 parent = wx.GetApp().GetTopWindow()
50
51
52 def get_tooltip(stay=None):
53 if stay is None:
54 return None
55 return stay.format (
56 include_procedures = True,
57 include_docs = True
58 )
59
60
61 def edit(stay=None):
62 return edit_hospital_stay(parent = parent, hospital_stay = stay)
63
64
65 def delete(stay=None):
66 if gmEMRStructItems.delete_hospital_stay(stay = stay['pk_hospital_stay']):
67 return True
68 gmDispatcher.send (
69 signal = 'statustext',
70 msg = _('Cannot delete hospitalization.'),
71 beep = True
72 )
73 return False
74
75
76 def refresh(lctrl):
77 stays = emr.get_hospital_stays()
78 items = [
79 [
80 s['admission'].strftime('%Y-%m-%d'),
81 gmTools.coalesce(s['discharge'], '', function_initial = ('strftime', '%Y-%m-%d')),
82 s['episode'],
83 '%s @ %s' % (s['ward'], s['hospital'])
84 ] for s in stays
85 ]
86 lctrl.set_string_items(items = items)
87 lctrl.set_data(data = stays)
88
89 gmListWidgets.get_choices_from_list (
90 parent = parent,
91 msg = _("The patient's hospitalizations:\n"),
92 caption = _('Editing hospitalizations ...'),
93 columns = [_('Admission'), _('Discharge'), _('Reason'), _('Hospital')],
94 single_selection = True,
95 edit_callback = edit,
96 new_callback = edit,
97 delete_callback = delete,
98 refresh_callback = refresh,
99 list_tooltip_callback = get_tooltip
100 )
101
102
114
115
117 """Phrasewheel to allow selection of a hospitalization."""
119
120 gmPhraseWheel.cPhraseWheel.__init__ (self, *args, **kwargs)
121
122 query = """
123 SELECT data, list_label, field_label FROM (
124 SELECT DISTINCT ON (data) * FROM ((
125
126 -- already-used org_units
127 SELECT
128 pk_org_unit
129 AS data,
130 ward || ' @ ' || hospital
131 AS list_label,
132 ward || ' @ ' || hospital
133 AS field_label,
134 1
135 AS rank
136 FROM
137 clin.v_hospital_stays
138 WHERE
139 ward %(fragment_condition)s
140 OR
141 hospital %(fragment_condition)s
142
143 ) UNION ALL (
144 -- wards
145 SELECT
146 pk_org_unit
147 AS data,
148 unit || ' (' || l10n_unit_category || ') @ ' || organization
149 AS list_label,
150 unit || ' @ ' || organization
151 AS field_label,
152 2
153 AS rank
154 FROM
155 dem.v_org_units
156 WHERE
157 unit_category = 'Ward'
158 AND
159 unit %(fragment_condition)s
160 AND
161 NOT EXISTS (
162 SELECT 1 FROM clin.v_hospital_stays WHERE clin.v_hospital_stays.pk_org_unit = dem.v_org_units.pk_org_unit
163 )
164
165 ) UNION ALL (
166 -- hospital units
167 SELECT
168 pk_org_unit
169 AS data,
170 unit || coalesce(' (' || l10n_unit_category || ')', '') || ' @ ' || organization || ' (' || l10n_organization_category || ')'
171 AS list_label,
172 unit || ' @ ' || organization
173 AS field_label,
174 3
175 AS rank
176 FROM
177 dem.v_org_units
178 WHERE
179 unit_category <> 'Ward'
180 AND
181 organization_category = 'Hospital'
182 AND
183 unit %(fragment_condition)s
184 AND
185 NOT EXISTS (
186 SELECT 1 FROM clin.v_hospital_stays WHERE clin.v_hospital_stays.pk_org_unit = dem.v_org_units.pk_org_unit
187 )
188
189 ) UNION ALL (
190 -- any other units
191 SELECT
192 pk_org_unit
193 AS data,
194 unit || coalesce(' (' || l10n_unit_category || ')', '') || ' @ ' || organization || ' (' || l10n_organization_category || ')'
195 AS list_label,
196 unit || ' @ ' || organization
197 AS field_label,
198 3
199 AS rank
200 FROM
201 dem.v_org_units
202 WHERE
203 unit_category <> 'Ward'
204 AND
205 organization_category <> 'Hospital'
206 AND
207 unit %(fragment_condition)s
208 AND
209 NOT EXISTS (
210 SELECT 1 FROM clin.v_hospital_stays WHERE clin.v_hospital_stays.pk_org_unit = dem.v_org_units.pk_org_unit
211 )
212 )) AS all_matches
213 ORDER BY data, rank
214 ) AS distinct_matches
215 ORDER BY rank, list_label
216 LIMIT 50
217 """
218
219 mp = gmMatchProvider.cMatchProvider_SQL2(queries = [query])
220 mp.setThresholds(2, 4, 6)
221 self.matcher = mp
222 self.selection_only = True
223
224
226 """Phrasewheel to allow selection of a hospital-type org_unit."""
228
229 gmPhraseWheel.cPhraseWheel.__init__ (self, *args, **kwargs)
230
231 ctxt = {'ctxt_pat': {'where_part': '(pk_patient = %(pat)s) AND', 'placeholder': 'pat'}}
232
233 mp = gmMatchProvider.cMatchProvider_SQL2 (
234 queries = [
235 """
236 SELECT
237 pk_hospital_stay,
238 descr
239 FROM (
240 SELECT DISTINCT ON (pk_hospital_stay)
241 pk_hospital_stay,
242 descr
243 FROM
244 (SELECT
245 pk_hospital_stay,
246 (
247 to_char(admission, 'YYYY-Mon-DD')
248 || ' (' || ward || ' @ ' || hospital || '):'
249 || episode
250 || coalesce((' (' || health_issue || ')'), '')
251 ) AS descr
252 FROM
253 clin.v_hospital_stays
254 WHERE
255 %(ctxt_pat)s (
256 hospital %(fragment_condition)s
257 OR
258 ward %(fragment_condition)s
259 OR
260 episode %(fragment_condition)s
261 OR
262 health_issue %(fragment_condition)s
263 )
264 ) AS the_stays
265 ) AS distinct_stays
266 ORDER BY descr
267 LIMIT 25
268 """ ],
269 context = ctxt
270 )
271 mp.setThresholds(3, 4, 6)
272 mp.set_context('pat', gmPerson.gmCurrentPatient().ID)
273
274 self.matcher = mp
275 self.selection_only = True
276
277
278 from Gnumed.wxGladeWidgets import wxgHospitalStayEditAreaPnl
279
280 -class cHospitalStayEditAreaPnl(wxgHospitalStayEditAreaPnl.wxgHospitalStayEditAreaPnl, gmEditArea.cGenericEditAreaMixin):
281
285
286
287
288
290
291 valid = True
292
293 if self._PRW_episode.GetValue().strip() == '':
294 valid = False
295 self._PRW_episode.display_as_valid(False)
296 gmDispatcher.send(signal = 'statustext', msg = _('Must select an episode or enter a name for a new one. Cannot save hospitalization.'), beep = True)
297 self._PRW_episode.SetFocus()
298
299 if not self._PRW_admission.is_valid_timestamp(empty_is_valid = False):
300 valid = False
301 gmDispatcher.send(signal = 'statustext', msg = _('Missing admission data. Cannot save hospitalization.'), beep = True)
302 self._PRW_admission.SetFocus()
303
304 if self._PRW_discharge.is_valid_timestamp(empty_is_valid = True):
305 if self._PRW_discharge.date is not None:
306 adm = self._PRW_admission.date
307 discharge = self._PRW_discharge.date
308
309 discharge = discharge.replace (
310 hour = adm.hour,
311 minute = adm.minute,
312 second = adm.second,
313 microsecond = adm.microsecond
314 )
315 if adm is not None:
316 if discharge == adm:
317 self._PRW_discharge.SetData(discharge + pydt.timedelta(seconds = 1))
318 elif not self._PRW_discharge.date > self._PRW_admission.date:
319 valid = False
320 self._PRW_discharge.display_as_valid(False)
321 gmDispatcher.send(signal = 'statustext', msg = _('Discharge date must be empty or later than admission. Cannot save hospitalization.'), beep = True)
322 self._PRW_discharge.SetFocus()
323
324 if self._PRW_hospital.GetData() is None:
325 valid = False
326 self._PRW_hospital.display_as_valid(False)
327 self.status_message = _('Must select a hospital. Cannot save hospitalization.')
328 self._PRW_hospital.SetFocus()
329 else:
330 self._PRW_hospital.display_as_valid(True)
331
332 return (valid is True)
333
347
349
350 self.data['pk_episode'] = self._PRW_episode.GetData(can_create = True)
351 self.data['pk_org_unit'] = self._PRW_hospital.GetData()
352 self.data['admission'] = self._PRW_admission.GetData()
353 self.data['discharge'] = self._PRW_discharge.GetData()
354 self.data['comment'] = self._TCTRL_comment.GetValue()
355 self.data.save_payload()
356
357 return True
358
366
378
380 print("this was not expected to be used in this edit area")
381
382
383
384
385 if __name__ == '__main__':
386
387 if len(sys.argv) < 2:
388 sys.exit()
389
390 if sys.argv[1] != 'test':
391 sys.exit()
392
393 from Gnumed.business import gmPersonSearch
394 from Gnumed.wxpython import gmPatSearchWidgets
395
396
397
398 pat = gmPersonSearch.ask_for_patient()
399 if pat is None:
400 print("No patient. Exiting gracefully...")
401 sys.exit(0)
402 gmPatSearchWidgets.set_active_patient(patient=pat)
403
404
405
406
407
408
409
410
411
412
413
418
419 test_hospital_stay_prw()
420