| Home | Trees | Indices | Help |
|
|---|
|
|
1 # -*- coding: latin-1 -*-
2 """GNUmed provider inbox middleware.
3
4 This should eventually end up in a class cPractice.
5 """
6 #============================================================
7 __license__ = "GPL"
8 __author__ = "K.Hilbert <Karsten.Hilbert@gmx.net>"
9
10
11 import sys
12 import logging
13
14
15 if __name__ == '__main__':
16 sys.path.insert(0, '../../')
17 from Gnumed.pycommon import gmPG2
18 from Gnumed.pycommon import gmBusinessDBObject
19 from Gnumed.pycommon import gmTools
20 from Gnumed.pycommon import gmDateTime
21
22 from Gnumed.business import gmStaff
23
24 _log = logging.getLogger('gm.inbox')
25
26 #============================================================
27 # provider message inbox
28 #------------------------------------------------------------
29 _SQL_get_inbox_messages = """SELECT * FROM dem.v_message_inbox d_vi WHERE %s"""
30
32
33 _cmd_fetch_payload = _SQL_get_inbox_messages % "pk_inbox_message = %s"
34 _cmds_store_payload = [
35 """
36 UPDATE dem.message_inbox SET
37 fk_staff = %(pk_staff)s,
38 fk_inbox_item_type = %(pk_type)s,
39 comment = gm.nullify_empty_string(%(comment)s),
40 data = gm.nullify_empty_string(%(data)s),
41 importance = %(importance)s,
42 fk_patient = %(pk_patient)s,
43 ufk_context = NULLIF(%(pk_context)s::integer[], ARRAY[NULL::integer]),
44 due_date = %(due_date)s,
45 expiry_date = %(expiry_date)s
46 WHERE
47 pk = %(pk_inbox_message)s
48 AND
49 xmin = %(xmin_message_inbox)s
50 RETURNING
51 pk as pk_inbox_message,
52 xmin as xmin_message_inbox
53 """
54 ]
55 _updatable_fields = [
56 'pk_staff',
57 'pk_type',
58 'comment',
59 'data',
60 'importance',
61 'pk_patient',
62 'pk_context',
63 'due_date',
64 'expiry_date'
65 ]
66 #------------------------------------------------------------
68 tt = '%s: %s%s\n' % (
69 gmDateTime.pydt_strftime (
70 self._payload[self._idx['received_when']],
71 format = '%A, %Y %b %d, %H:%M',
72 accuracy = gmDateTime.acc_minutes
73 ),
74 gmTools.bool2subst(self._payload[self._idx['is_virtual']], _('virtual message'), _('message')),
75 gmTools.coalesce(self._payload[self._idx['pk_inbox_message']], '', ' #%s ')
76 )
77
78 tt += '%s: %s\n' % (
79 self._payload[self._idx['l10n_category']],
80 self._payload[self._idx['l10n_type']]
81 )
82
83 tt += '%s %s %s\n' % (
84 self._payload[self._idx['modified_by']],
85 gmTools.u_arrow2right,
86 gmTools.coalesce(self._payload[self._idx['provider']], _('everyone'))
87 )
88
89 tt += '\n%s%s%s\n\n' % (
90 gmTools.u_left_double_angle_quote,
91 self._payload[self._idx['comment']],
92 gmTools.u_right_double_angle_quote
93 )
94
95 if with_patient and (self._payload[self._idx['pk_patient']] is not None):
96 tt += _('Patient: %s, %s%s %s #%s\n' % (
97 self._payload[self._idx['lastnames']],
98 self._payload[self._idx['firstnames']],
99 gmTools.coalesce(self._payload[self._idx['l10n_gender']], '', ' (%s)'),
100 gmDateTime.pydt_strftime(self._payload[self._idx['dob']], '%Y %b %d', none_str = ''),
101 self._payload[self._idx['pk_patient']]
102 ))
103
104 if self._payload[self._idx['due_date']] is not None:
105 if self._payload[self._idx['is_overdue']]:
106 template = _('Due: %s (%s ago)\n')
107 else:
108 template = _('Due: %s (in %s)\n')
109 tt += template % (
110 gmDateTime.pydt_strftime(self._payload[self._idx['due_date']], '%Y %b %d'),
111 gmDateTime.format_interval_medically(self._payload[self._idx['interval_due']])
112 )
113
114 if self._payload[self._idx['expiry_date']] is not None:
115 if self._payload[self._idx['is_expired']]:
116 template = _('Expired: %s\n')
117 else:
118 template = _('Expires: %s\n')
119 tt += template % gmDateTime.pydt_strftime(self._payload[self._idx['expiry_date']], '%Y %b %d')
120
121 if self._payload[self._idx['data']] is not None:
122 tt += self._payload[self._idx['data']][:150]
123 if len(self._payload[self._idx['data']]) > 150:
124 tt += gmTools.u_ellipsis
125
126 return tt
127 #------------------------------------------------------------
129
130 if order_by is None:
131 order_by = '%s ORDER BY due_date, importance DESC, received_when DESC'
132 else:
133 order_by = '%%s ORDER BY %s' % order_by
134
135 args = {'pat': pk_patient}
136 where_parts = [
137 'pk_patient = %(pat)s',
138 'due_date IS NOT NULL'
139 ]
140
141 cmd = "SELECT * FROM dem.v_message_inbox WHERE %s" % (
142 order_by % ' AND '.join(where_parts)
143 )
144 _log.debug('SQL: %s', cmd)
145 _log.debug('args: %s', args)
146 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True)
147 if return_pks:
148 return [ r['pk_inbox_message'] for r in rows ]
149 return [ cInboxMessage(row = {'data': r, 'idx': idx, 'pk_field': 'pk_inbox_message'}) for r in rows ]
150
151 #------------------------------------------------------------
153
154 if order_by is None:
155 order_by = '%s ORDER BY due_date, importance DESC, received_when DESC'
156 else:
157 order_by = '%%s ORDER BY %s' % order_by
158
159 args = {'pat': pk_patient}
160 where_parts = [
161 'pk_patient = %(pat)s',
162 'is_overdue IS TRUE'
163 ]
164
165 cmd = "SELECT * FROM dem.v_message_inbox WHERE %s" % (
166 order_by % ' AND '.join(where_parts)
167 )
168 _log.debug('SQL: %s', cmd)
169 _log.debug('args: %s', args)
170 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True)
171 if return_pks:
172 return [ r['pk_inbox_message'] for r in rows ]
173 return [ cInboxMessage(row = {'data': r, 'idx': idx, 'pk_field': 'pk_inbox_message'}) for r in rows ]
174
175 #------------------------------------------------------------
176 -def get_relevant_messages(pk_staff=None, pk_patient=None, include_without_provider=False, order_by=None, return_pks=False):
177
178 if order_by is None:
179 order_by = '%s ORDER BY importance desc, received_when desc'
180 else:
181 order_by = '%%s ORDER BY %s' % order_by
182
183 args = {}
184 where_parts = []
185
186 if pk_staff is not None:
187 if include_without_provider:
188 where_parts.append('((pk_staff IN (%(staff)s, NULL)) OR (modified_by = (SELECT short_alias FROM dem.staff WHERE pk = %(staff)s)))')
189 else:
190 where_parts.append('((pk_staff = %(staff)s) OR (modified_by = (SELECT short_alias FROM dem.staff WHERE pk = %(staff)s)))')
191 args['staff'] = pk_staff
192
193 if pk_patient is not None:
194 where_parts.append('pk_patient = %(pat)s')
195 args['pat'] = pk_patient
196
197 where_parts.append("""
198 -- messages which have no due date and are not expired
199 ((due_date IS NULL) AND ((expiry_date IS NULL) OR (expiry_date > now())))
200 OR
201 -- messages which are due and not expired
202 ((due_date IS NOT NULL) AND (due_date < now()) AND ((expiry_date IS NULL) OR (expiry_date > now())))
203 """)
204
205 cmd = _SQL_get_inbox_messages % (
206 order_by % ' AND '.join(where_parts)
207 )
208 _log.debug('SQL: %s', cmd)
209 _log.debug('args: %s', args)
210 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True)
211 if return_pks:
212 return [ r['pk_inbox_message'] for r in rows ]
213 return [ cInboxMessage(row = {'data': r, 'idx': idx, 'pk_field': 'pk_inbox_message'}) for r in rows ]
214
215 #------------------------------------------------------------
216 -def get_inbox_messages(pk_staff=None, pk_patient=None, include_without_provider=False, exclude_expired=False, expired_only=False, overdue_only=False, unscheduled_only=False, exclude_unscheduled=False, order_by=None, return_pks=False):
217
218 if order_by is None:
219 order_by = '%s ORDER BY importance desc, received_when desc'
220 else:
221 order_by = '%%s ORDER BY %s' % order_by
222
223 args = {}
224 where_parts = []
225
226 if pk_staff is not None:
227 if include_without_provider:
228 where_parts.append('((pk_staff IN (%(staff)s, NULL)) OR (modified_by = (SELECT short_alias FROM dem.staff WHERE pk = %(staff)s)))')
229 else:
230 where_parts.append('((pk_staff = %(staff)s) OR (modified_by = (SELECT short_alias FROM dem.staff WHERE pk = %(staff)s)))')
231 args['staff'] = pk_staff
232
233 if pk_patient is not None:
234 where_parts.append('pk_patient = %(pat)s')
235 args['pat'] = pk_patient
236
237 if exclude_expired:
238 where_parts.append('is_expired IS FALSE')
239
240 if expired_only:
241 where_parts.append('is_expired IS TRUE')
242
243 if overdue_only:
244 where_parts.append('is_overdue IS TRUE')
245
246 if unscheduled_only:
247 where_parts.append('due_date IS NULL')
248
249 if exclude_unscheduled:
250 where_parts.append('due_date IS NOT NULL')
251
252 cmd = _SQL_get_inbox_messages % (
253 order_by % ' AND '.join(where_parts)
254 )
255 _log.debug('SQL: %s', cmd)
256 _log.debug('args: %s', args)
257 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True)
258 if return_pks:
259 return [ r['pk_inbox_message'] for r in rows ]
260 return [ cInboxMessage(row = {'data': r, 'idx': idx, 'pk_field': 'pk_inbox_message'}) for r in rows ]
261
262 #------------------------------------------------------------
263 -def create_inbox_message(message_type=None, subject=None, patient=None, staff=None, message_category='clinical'):
264
265 success, pk_type = gmTools.input2int(initial = message_type)
266 if not success:
267 pk_type = create_inbox_item_type(message_type = message_type, category = message_category)
268
269 cmd = """
270 INSERT INTO dem.message_inbox (
271 fk_staff,
272 fk_patient,
273 fk_inbox_item_type,
274 comment
275 ) VALUES (
276 %(staff)s,
277 %(pat)s,
278 %(type)s,
279 gm.nullify_empty_string(%(subject)s)
280 )
281 RETURNING pk
282 """
283 args = {
284 'staff': staff,
285 'pat': patient,
286 'type': pk_type,
287 'subject': subject
288 }
289 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True, get_col_idx = False)
290
291 return cInboxMessage(aPK_obj = rows[0]['pk'])
292
293 #------------------------------------------------------------
295 args = {'pk': inbox_message}
296 cmd = "DELETE FROM dem.message_inbox WHERE pk = %(pk)s"
297 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
298 return True
299
300 #------------------------------------------------------------
302
303 # determine category PK
304 success, pk_cat = gmTools.input2int(initial = category)
305 if not success:
306 args = {'cat': category}
307 cmd = """SELECT COALESCE (
308 (SELECT pk FROM dem.inbox_item_category WHERE _(description) = %(cat)s),
309 (SELECT pk FROM dem.inbox_item_category WHERE description = %(cat)s)
310 ) AS pk"""
311 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}])
312 if rows[0]['pk'] is None:
313 cmd = "INSERT INTO dem.inbox_item_category (description) VALUES (%(cat)s) RETURNING pk"
314 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True)
315 pk_cat = rows[0]['pk']
316 else:
317 pk_cat = rows[0]['pk']
318
319 # find type PK or create type
320 args = {'pk_cat': pk_cat, 'type': message_type}
321 cmd = """SELECT COALESCE (
322 (SELECT pk FROM dem.inbox_item_type where fk_inbox_item_category = %(pk_cat)s AND _(description) = %(type)s),
323 (SELECT pk FROM dem.inbox_item_type where fk_inbox_item_category = %(pk_cat)s AND description = %(type)s)
324 ) AS pk"""
325 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}])
326 if rows[0]['pk'] is None:
327 cmd = """
328 INSERT INTO dem.inbox_item_type (
329 fk_inbox_item_category,
330 description,
331 is_user
332 ) VALUES (
333 %(pk_cat)s,
334 %(type)s,
335 TRUE
336 ) RETURNING pk"""
337 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True)
338
339 return rows[0]['pk']
340
341 #============================================================
344 if provider_id is None:
345 self.__provider_id = gmStaff.gmCurrentProvider()['pk_staff']
346 else:
347 self.__provider_id = provider_id
348 #--------------------------------------------------------
350 return delete_inbox_message(inbox_message = pk)
351 #--------------------------------------------------------
353 return create_inbox_message (
354 message_type = message_type,
355 subject = subject,
356 patient = patient,
357 staff = self.__provider_id
358 )
359 #--------------------------------------------------------
360 # properties
361 #--------------------------------------------------------
362 - def get_messages(self, pk_patient=None, include_without_provider=False, exclude_expired=False, expired_only=False, overdue_only=False, unscheduled_only=False, exclude_unscheduled=False, order_by=None):
363 return get_inbox_messages (
364 pk_staff = self.__provider_id,
365 pk_patient = pk_patient,
366 include_without_provider = include_without_provider,
367 exclude_expired = exclude_expired,
368 expired_only = expired_only,
369 overdue_only = overdue_only,
370 unscheduled_only = unscheduled_only,
371 exclude_unscheduled = exclude_unscheduled,
372 order_by = order_by
373 )
374
375 messages = property(get_messages, lambda x:x)
376
377 #--------------------------------------------------------
379 return get_relevant_messages (
380 pk_staff = self.__provider_id,
381 pk_patient = pk_patient,
382 include_without_provider = include_without_provider
383 )
384
385 #============================================================
386 if __name__ == '__main__':
387
388 if len(sys.argv) < 2:
389 sys.exit()
390
391 if sys.argv[1] != 'test':
392 sys.exit()
393
394 from Gnumed.pycommon import gmI18N
395
396 gmI18N.activate_locale()
397 gmI18N.install_domain()
398
399 #---------------------------------------
401 gmStaff.gmCurrentProvider(provider = gmStaff.cStaff())
402 inbox = cProviderInbox()
403 for msg in inbox.messages:
404 print(msg)
405 #---------------------------------------
409 #---------------------------------------
411 print(create_inbox_item_type(message_type = 'test'))
412 #---------------------------------------
416 #---------------------------------------
417 #test_inbox()
418 #test_msg()
419 #test_create_type()
420 #test_due()
421
422 #============================================================
423
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Sat Feb 29 02:55:27 2020 | http://epydoc.sourceforge.net |