1 """GNUmed vaccination related business objects.
2 """
3
4 __version__ = "$Revision: 1.38 $"
5 __author__ = "K.Hilbert <Karsten.Hilbert@gmx.net>"
6 __license__ = "GPL"
7
8 import sys, copy, logging
9
10
11 if __name__ == '__main__':
12 sys.path.insert(0, '../../')
13
14
15
16 from Gnumed.pycommon import gmBusinessDBObject, gmPG2, gmI18N, gmTools
17 from Gnumed.business import gmMedication
18
19
20 _log = logging.getLogger('gm.vaccination')
21 _log.info(__version__)
22
23
25 cmd = u'SELECT * from clin.vacc_indication'
26
27 if order_by is not None:
28 cmd = u'%s ORDER BY %s' % (cmd, order_by)
29
30 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = False)
31
32 return rows
33
34 _sql_fetch_vaccine = u"""SELECT *, xmin_vaccine FROM clin.v_vaccines WHERE %s"""
35
36 -class cVaccine(gmBusinessDBObject.cBusinessDBObject):
37 """Represents one vaccine."""
38
39 _cmd_fetch_payload = _sql_fetch_vaccine % u"pk_vaccine = %s"
40
41 _cmds_store_payload = [
42 u"""UPDATE clin.vaccine SET
43 -- internal_name = gm.nullify_empty_string(%(internal_name)s),
44 WHERE
45 pk = %(pk_vaccine)s
46 AND
47 xmin = %(xmin_vaccine)s
48 RETURNING
49 xmin as xmin_vaccine
50 """
51 ]
52
53 _updatable_fields = [
54 u'id_route',
55 u'is_live',
56 u'min_age',
57 u'max_age',
58 u'comment'
59
60 ]
61
62 - def __init__(self, aPK_obj=None, row=None):
63 super(cVaccine, self).__init__(aPK_obj = aPK_obj, row = row)
64
65 self.__brand = None
66
67
68
70 if self.__brand is None:
71 self.__brand = gmMedication.cBrandedDrug(aPK_obj = self._payload[self._idx['pk_brand']])
72 return self.__brand
73
74 brand = property(_get_brand, lambda x:x)
75
86
88
89 args = {'inds': indications}
90 cmd = _sql_fetch_vaccine % (u'is_fake_vaccine is True AND indications @> %(inds)s AND %(inds)s @> indications')
91
92 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True)
93
94 if len(rows) == 0:
95 _log.warning('no fake, generic vaccine found for [%s]', indications)
96 return None
97
98 return cVaccine(row = {'data': rows[0], 'idx': idx, 'pk_field': 'pk_vaccine'})
99
101
102 cmd = u'select gm.create_generic_monovalent_vaccines()'
103 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd}], return_data = True)
104
105 cmd = u'select gm.create_generic_combi_vaccines()'
106 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd}], return_data = True)
107
108 return rows[0][0]
109
110
111
112 sql_fetch_vaccination = u"""SELECT * FROM clin.v_pat_vaccinations WHERE %s"""
113
115
116 _cmd_fetch_payload = sql_fetch_vaccination % u"pk_vaccination = %s"
117
118 _cmds_store_payload = [
119 u"""UPDATE clin.vaccination SET
120 soap_cat = %(soap_cat)s,
121 clin_when = %(date_given)s,
122 site = gm.nullify_empty_string(%(site)s),
123 batch_no = gm.nullify_empty_string(%(batch_no)s),
124 reaction = gm.nullify_empty_string(%(reaction)s),
125 narrative = gm.nullify_empty_string(%(comment)s),
126 fk_vaccine = %(pk_vaccine)s,
127 fk_provider = %(pk_provider)s,
128 fk_encounter = %(pk_encounter)s,
129 fk_episode = %(pk_episode)s
130 WHERE
131 pk = %(pk_vaccination)s
132 AND
133 xmin = %(xmin_vaccination)s
134 RETURNING
135 xmin as xmin_vaccination
136 """
137 ]
138
139 _updatable_fields = [
140 u'soap_cat',
141 u'date_given',
142 u'site',
143 u'batch_no',
144 u'reaction',
145 u'comment',
146 u'pk_vaccine',
147 u'pk_provider',
148 u'pk_encounter',
149 u'pk_episode'
150 ]
151
175
177
178 cmd = u"""
179 INSERT INTO clin.vaccination (
180 fk_encounter,
181 fk_episode,
182 fk_vaccine,
183 batch_no
184 ) VALUES (
185 %(enc)s,
186 %(epi)s,
187 %(vacc)s,
188 %(batch)s
189 ) RETURNING pk;
190 """
191 args = {
192 u'enc': encounter,
193 u'epi': episode,
194 u'vacc': vaccine,
195 u'batch': batch_no
196 }
197
198 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False, return_data = True)
199
200 return cVaccination(aPK_obj = rows[0][0])
201
203 cmd = u"""DELETE FROM clin.vaccination WHERE pk = %(pk)s"""
204 args = {'pk': vaccination}
205
206 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
207
208
209
210
211
212
214 """Represents one missing vaccination.
215
216 - can be due or overdue
217 """
218 _cmd_fetch_payload = """
219 (select *, False as overdue
220 from clin.v_pat_missing_vaccs vpmv
221 where
222 pk_patient=%(pat_id)s
223 and
224 (select dob from dem.identity where pk=%(pat_id)s) between (now() - age_due_min) and (now() - coalesce(age_due_max, '115 years'::interval))
225 and
226 indication=%(indication)s
227 and
228 seq_no=%(seq_no)s
229 order by time_left)
230
231 UNION
232
233 (select *, True as overdue
234 from clin.v_pat_missing_vaccs vpmv
235 where
236 pk_patient=%(pat_id)s
237 and
238 now() - ((select dob from dem.identity where pk=%(pat_id)s)) > coalesce(age_due_max, '115 years'::interval)
239 and
240 indication=%(indication)s
241 and
242 seq_no=%(seq_no)s
243 order by amount_overdue)"""
244 _cmds_lock_rows_for_update = []
245 _cmds_store_payload = ["""select 1"""]
246 _updatable_fields = []
247
249 return self['overdue']
250
252
253
254
255
256 return (False, 'not implemented')
257
272
280
282 """Represents one vaccination course.
283 """
284 _cmd_fetch_payload = """
285 select *, xmin_vaccination_course from clin.v_vaccination_courses
286 where pk_course=%s"""
287 _cmds_lock_rows_for_update = [
288 """select 1 from clin.vaccination_course where id=%(pk_course)s and xmin=%(xmin_vaccination_course)s for update"""
289 ]
290 _cmds_store_payload = [
291 """update clin.vaccination_course set
292 name=%(course)s,
293 fk_recommended_by=%(pk_recommended_by)s,
294 fk_indication=(select id from clin.vacc_indication where description=%(indication)s),
295 comment=%(comment)s
296 where id=%(pk_course)s""",
297 """select xmin_vaccination_course from clin.v_vaccination_courses where pk_course=%(pk_course)s"""
298 ]
299 _updatable_fields = [
300 'course',
301 'pk_recommended_by',
302 'indication',
303 'comment'
304 ]
305
306
307
308
309 -def create_vaccination_old(patient_id=None, episode_id=None, encounter_id=None, staff_id = None, vaccine=None):
310
311
312
313 cmd = """
314 select pk_patient
315 from clin.v_pat_episodes
316 where pk_episode=%s
317 union
318 select pk_patient
319 from clin.v_pat_encounters
320 where pk_encounter=%s"""
321 rows = gmPG.run_ro_query('historica', cmd, None, episode_id, encounter_id)
322 if (rows is None) or (len(rows) == 0):
323 _log.error('error checking episode [%s] <-> encounter [%s] consistency' % (episode_id, encounter_id))
324 return (False, _('internal error, check log'))
325 if len(rows) > 1:
326 _log.error('episode [%s] and encounter [%s] belong to more than one patient !?!' % (episode_id, encounter_id))
327 return (False, _('consistency error, check log'))
328
329 queries = []
330 if type(vaccine) == types.IntType:
331 cmd = """insert into clin.vaccination (fk_encounter, fk_episode, fk_patient, fk_provider, fk_vaccine)
332 values (%s, %s, %s, %s, %s)"""
333 else:
334 cmd = """insert into clin.vaccination (fk_encounter, fk_episode, fk_patient, fk_provider, fk_vaccine)
335 values (%s, %s, %s, %s, (select pk from clin.vaccine where trade_name=%s))"""
336 vaccine = str(vaccine)
337 queries.append((cmd, [encounter_id, episode_id, patient_id, staff_id, vaccine]))
338
339 cmd = "select currval('clin.vaccination_id_seq')"
340 queries.append((cmd, []))
341 result, msg = gmPG.run_commit('historica', queries, True)
342 if (result is None) or (len(result) == 0):
343 return (False, msg)
344 try:
345 vacc = cVaccination(aPK_obj = result[0][0])
346 except gmExceptions.ConstructorError:
347 _log.exception('cannot instantiate vaccination' % (result[0][0]), sys.exc_info, verbose=0)
348 return (False, _('internal error, check log'))
349
350 return (True, vacc)
351
353
354 cmd = 'select name from clin.vaccination_course'
355 rows = gmPG.run_ro_query('historica', cmd)
356 if rows is None:
357 return None
358 if len(rows) == 0:
359 return []
360 data = []
361 for row in rows:
362 data.extend(rows)
363 return data
364
366
367 int(pk_patient)
368
369 cmd = """
370 select fk_regime
371 from clin.lnk_pat2vacc_reg l
372 where l.fk_patient = %s""" % pk_patient
373
374 rows = gmPG.run_ro_query('historica', cmd)
375 active = []
376 if rows and len(rows):
377 active = [ r[0] for r in rows]
378
379
380
381
382
383
384
385 r = ( {}, [] )
386
387
388 cmd = """
389 select
390 r.pk_regime ,
391 r.pk_recommended_by ,
392 r.indication,
393 r.regime ,
394 extract (epoch from d.min_age_due) /60/60/24,
395 extract (epoch from d.max_age_due) /60/60/24,
396 extract (epoch from d.min_interval ) /60/60/24,
397 d.seq_no
398 from
399 clin.v_vaccination_courses r, clin.vacc_def d
400 where
401 d.fk_regime = r.pk_regime
402 order by
403 r.pk_recommended_by, d.min_age_due"""
404
405
406
407
408 rows = gmPG.run_ro_query('historica', cmd)
409 if rows is None:
410 VaccByRecommender._recommended_regimes = r
411 return r, active
412
413 row_fields = ['pk_regime', 'pk_recommender', 'indication' , 'regime', 'min_age_due', 'max_age_due', 'min_interval', 'seq_no' ]
414
415 for row in rows:
416 m = {}
417 for k, i in zip(row_fields, range(len(row))):
418 m[k] = row[i]
419 pk_recommender = m['pk_recommender']
420
421 if not pk_recommender in r[0].keys():
422 r[0][pk_recommender] = []
423 r[1].append(pk_recommender)
424 r[0][pk_recommender].append(m)
425
426 for k, v in r[0].items():
427 print k
428 for x in v:
429 print '\t', x
430
431 VaccByRecommender._recommended_regimes = r
432 return r, active
433
435
436 int(pk_patient)
437
438 cmd = """
439 select
440 indication, regime,
441 pk_regime,
442 pk_recommended_by,
443 seq_no ,
444 extract(epoch from age_due_min) /60/60/24 as age_due_min,
445 extract(epoch from age_due_max) /60/60/24 as age_due_max,
446 extract(epoch from min_interval)/60/60/24 as min_interval
447 from
448 clin.v_pat_missing_vaccs
449 where pk_patient = %s
450 order by age_due_min, pk_recommended_by, indication
451 """ % pk_patient
452
453 rows = gmPG.run_ro_query('historica', cmd)
454
455 return rows
456
458 """Retrieves vaccination bundle indications list.
459
460 * vaccinations = list of any type of vaccination
461 - indicated
462 - due vacc
463 - overdue vaccs
464 - due boosters
465 - arbitrary
466 """
467
468
469
470 if vaccinations is None:
471 _log.error('list of vaccinations must be supplied')
472 return (False, [['ERROR: list of vaccinations not supplied', _('ERROR: list of vaccinations not supplied')]])
473 if len(vaccinations) == 0:
474 return (True, [['empty list of vaccinations', _('empty list of vaccinations')]])
475 inds = []
476 for vacc in vaccinations:
477 try:
478 inds.append([vacc['indication'], vacc['l10n_indication']])
479 except KeyError:
480 try:
481 inds.append([vacc['indication'], vacc['indication']])
482 except KeyError:
483 inds.append(['vacc -> ind error: %s' % str(vacc), _('vacc -> ind error: %s') % str(vacc)])
484 return (True, inds)
485
487 """
488 Schedules a vaccination course for a patient
489
490 * patient_id = Patient's PK
491 * course = course object or Vaccination course's PK
492 """
493
494 if isinstance(course, cVaccinationCourse):
495 course_id = course['pk_course']
496 else:
497 course_id = course
498
499
500 queries = []
501 cmd = """insert into clin.lnk_pat2vacc_reg (fk_patient, fk_course)
502 values (%s, %s)"""
503 queries.append((cmd, [patient_id, course_id]))
504 result, msg = gmPG.run_commit('historica', queries, True)
505 if result is None:
506 return (False, msg)
507 return (True, msg)
508
510 """unSchedules a vaccination course for a patient
511
512 * patient_id = Patient's PK
513 * course = course object or Vaccination course's PK
514 """
515
516 if isinstance(course, cVaccinationCourse):
517 course_id = course['pk_course']
518 else:
519 course_id = course
520
521
522 queries = []
523 cmd = """delete from clin.lnk_pat2vacc_reg where fk_patient = %s and fk_course = %s"""
524
525 queries.append((cmd, [patient_id, course_id]))
526 result, msg = gmPG.run_commit('historica', queries, True)
527 if result is None:
528 return (False, msg)
529 return (True, msg)
530
532
533 quoted_inds = [ "'"+x + "%'" for x in all_ind]
534
535
536
537
538
539
540
541
542
543
544
545 cmd_inds_per_vaccine = """
546 select
547 count(trade_name),
548 trade_name
549 from clin.v_inds4vaccine
550 group by trade_name"""
551
552 cmd_presence_in_vaccine = """
553 select count(v.trade_name) , v.trade_name
554
555 from
556 clin.vaccine v, clin.lnk_vaccine2inds l, clin.vacc_indication i
557 where
558 v.pk = l.fk_vaccine and l.fk_indication = i.id
559 and
560 i.description like any ( array [ %s ] )
561 group
562
563 by trade_name
564
565 """ % ', '.join( quoted_inds )
566
567 inds_per_vaccine = gmPG.run_ro_query( 'historica', cmd_inds_per_vaccine)
568
569 presence_in_vaccine = gmPG.run_ro_query( 'historica', cmd_presence_in_vaccine)
570
571 map_vacc_count_inds = dict ( [ (x[1], x[0]) for x in inds_per_vaccine ] )
572
573 matched_vaccines = []
574 for (presence, vaccine) in presence_in_vaccine:
575 if presence == len ( all_ind) :
576
577
578 if map_vacc_count_inds[vaccine] == presence:
579 matched_vaccines.append(vaccine)
580 return matched_vaccines
581
582
583
584 if __name__ == '__main__':
585
586 if len(sys.argv) < 2:
587 sys.exit()
588
589 if sys.argv[1] != u'test':
590 sys.exit()
591
592
593
601
603
604 pk_args = {
605 'pat_id': 12,
606 'indication': 'meningococcus C',
607 'seq_no': 1
608 }
609 missing_vacc = cMissingVaccination(aPK_obj=pk_args)
610 fields = missing_vacc.get_fields()
611 print "\nDue vaccination:"
612 print missing_vacc
613 for field in fields:
614 print field, ':', missing_vacc[field]
615
616 pk_args = {
617 'pat_id': 12,
618 'indication': 'haemophilus influenzae b',
619 'seq_no': 2
620 }
621 missing_vacc = cMissingVaccination(aPK_obj=pk_args)
622 fields = missing_vacc.get_fields()
623 print "\nOverdue vaccination (?):"
624 print missing_vacc
625 for field in fields:
626 print field, ':', missing_vacc[field]
627
629 pk_args = {
630 'pat_id': 12,
631 'indication': 'tetanus'
632 }
633 missing_booster = cMissingBooster(aPK_obj=pk_args)
634 fields = missing_booster.get_fields()
635 print "\nDue booster:"
636 print missing_booster
637 for field in fields:
638 print field, ':', missing_booster[field]
639
641 scheduled_vacc = cScheduledVaccination(aPK_obj=20)
642 print "\nScheduled vaccination:"
643 print scheduled_vacc
644 fields = scheduled_vacc.get_fields()
645 for field in fields:
646 print field, ':', scheduled_vacc[field]
647 print "updatable:", scheduled_vacc.get_updatable_fields()
648
650 vaccination_course = cVaccinationCourse(aPK_obj=7)
651 print "\nVaccination course:"
652 print vaccination_course
653 fields = vaccination_course.get_fields()
654 for field in fields:
655 print field, ':', vaccination_course[field]
656 print "updatable:", vaccination_course.get_updatable_fields()
657
659 result, msg = put_patient_on_schedule(patient_id=12, course_id=1)
660 print '\nPutting patient id 12 on schedule id 1... %s (%s)' % (result, msg)
661
666
667
668
669
670
671
672
673
674
675 test_get_vaccines()
676
677