Package Gnumed :: Package business :: Module gmMedication
[frames] | no frames]

Source Code for Module Gnumed.business.gmMedication

  1  # -*- coding: utf8 -*- 
  2  """Medication handling code. 
  3   
  4  license: GPL 
  5  """ 
  6  #============================================================ 
  7  # $Source: /cvsroot/gnumed/gnumed/gnumed/client/business/gmMedication.py,v $ 
  8  # $Id: gmMedication.py,v 1.20 2009/12/25 21:38:50 ncq Exp $ 
  9  __version__ = "$Revision: 1.20 $" 
 10  __author__ = "K.Hilbert <Karsten.Hilbert@gmx.net>" 
 11   
 12  import sys, logging, csv, codecs, os, re as regex 
 13   
 14   
 15  if __name__ == '__main__': 
 16          sys.path.insert(0, '../../') 
 17  from Gnumed.pycommon import gmBusinessDBObject, gmPG2, gmShellAPI, gmTools, gmDateTime 
 18  from Gnumed.business import gmATC 
 19   
 20   
 21  _log = logging.getLogger('gm.meds') 
 22  _log.info(__version__) 
 23   
 24  #============================================================ 
 25  # wishlist: 
 26  # - --conf-file= for glwin.exe 
 27  # - wirkstoff: Konzentration auch in Multiprodukten 
 28  # - wirkstoff: ATC auch in Multiprodukten 
 29  # - Suche nach ATC per CLI 
 30   
31 -class cGelbeListeCSVFile(object):
32 """Iterator over a Gelbe Liste/MMI v8.2 CSV file.""" 33 34 version = u'Gelbe Liste/MMI v8.2 CSV file interface' 35 default_transfer_file_windows = r"c:\rezept.txt" 36 #default_encoding = 'cp1252' 37 default_encoding = 'cp1250' 38 csv_fieldnames = [ 39 u'name', 40 u'packungsgroesse', # obsolete, use "packungsmenge" 41 u'darreichungsform', 42 u'packungstyp', 43 u'festbetrag', 44 u'avp', 45 u'hersteller', 46 u'rezepttext', 47 u'pzn', 48 u'status_vertrieb', 49 u'status_rezeptpflicht', 50 u'status_fachinfo', 51 u'btm', 52 u'atc', 53 u'anzahl_packungen', 54 u'zuzahlung_pro_packung', 55 u'einheit', 56 u'schedule_morgens', 57 u'schedule_mittags', 58 u'schedule_abends', 59 u'schedule_nachts', 60 u'status_dauermedikament', 61 u'status_hausliste', 62 u'status_negativliste', 63 u'ik_nummer', 64 u'status_rabattvertrag', 65 u'wirkstoffe', 66 u'wirkstoffmenge', 67 u'wirkstoffeinheit', 68 u'wirkstoffmenge_bezug', 69 u'wirkstoffmenge_bezugseinheit', 70 u'status_import', 71 u'status_lifestyle', 72 u'status_ausnahmeliste', 73 u'packungsmenge', 74 u'apothekenpflicht', 75 u'status_billigere_packung', 76 u'rezepttyp', 77 u'besonderes_arzneimittel', # Abstimmungsverfahren SGB-V 78 u't-rezept-pflicht', # Thalidomid-Rezept 79 u'erstattbares_medizinprodukt', 80 u'hilfsmittel', 81 u'hzv_rabattkennung', 82 u'hzv_preis' 83 ] 84 boolean_fields = [ 85 u'status_rezeptpflicht', 86 u'status_fachinfo', 87 u'btm', 88 u'status_dauermedikament', 89 u'status_hausliste', 90 u'status_negativliste', 91 u'status_rabattvertrag', 92 u'status_import', 93 u'status_lifestyle', 94 u'status_ausnahmeliste', 95 u'apothekenpflicht', 96 u'status_billigere_packung', 97 u'besonderes_arzneimittel', # Abstimmungsverfahren SGB-V 98 u't-rezept-pflicht', 99 u'erstattbares_medizinprodukt', 100 u'hilfsmittel' 101 ] 102 #--------------------------------------------------------
103 - def __init__(self, filename=None):
104 105 _log.info(cGelbeListeCSVFile.version) 106 107 self.filename = filename 108 if filename is None: 109 self.filename = cGelbeListeCSVFile.default_transfer_file_windows 110 111 _log.debug('reading Gelbe Liste/MMI drug data from [%s]', self.filename) 112 113 self.csv_file = codecs.open(filename = filename, mode = 'rUb', encoding = cGelbeListeCSVFile.default_encoding) 114 115 self.csv_lines = gmTools.unicode_csv_reader ( 116 self.csv_file, 117 fieldnames = cGelbeListeCSVFile.csv_fieldnames, 118 delimiter = ';', 119 quotechar = '"', 120 dict = True 121 )
122 #--------------------------------------------------------
123 - def __iter__(self):
124 return self
125 #--------------------------------------------------------
126 - def next(self):
127 line = self.csv_lines.next() 128 129 for field in cGelbeListeCSVFile.boolean_fields: 130 line[field] = (line[field].strip() == u'T') 131 132 # split field "Wirkstoff" by ";" 133 if line['wirkstoffe'].strip() == u'': 134 line['wirkstoffe'] = [] 135 else: 136 line['wirkstoffe'] = [ wirkstoff.strip() for wirkstoff in line['wirkstoffe'].split(u';') ] 137 138 return line
139 #--------------------------------------------------------
140 - def close(self, truncate=True):
141 try: self.csv_file.close() 142 except: pass 143 144 if truncate: 145 try: os.open(self.filename, 'wb').close 146 except: pass
147 #============================================================
148 -class cDrugDataSourceInterface(object):
149 150 #--------------------------------------------------------
151 - def get_data_source_version(self):
152 raise NotImplementedError
153 #--------------------------------------------------------
154 - def create_data_source_entry(self):
155 raise NotImplementedError
156 #--------------------------------------------------------
157 - def switch_to_frontend(self):
158 raise NotImplementedError
159 #--------------------------------------------------------
160 - def select_drugs(self):
161 raise NotImplementedError
162 #--------------------------------------------------------
163 - def import_drugs(self):
164 raise NotImplementedError
165 #--------------------------------------------------------
166 - def check_drug_interactions(self):
167 raise NotImplementedError
168 #--------------------------------------------------------
169 - def show_info_on_drug(self, drug=None):
170 raise NotImplementedError
171 #============================================================
172 -class cGelbeListeWindowsInterface(cDrugDataSourceInterface):
173 """Support v8.2 CSV file interface only.""" 174 175 version = u'Gelbe Liste/MMI v8.2 interface' 176 default_encoding = 'cp1250' 177 bdt_line_template = u'%03d6210#%s\r\n' # Medikament verordnet auf Kassenrezept 178 bdt_line_base_length = 8 179 #--------------------------------------------------------
180 - def __init__(self):
181 _log.info(u'%s (native Windows)', cGelbeListeWindowsInterface.version) 182 183 self.path_to_binary = r'C:\Programme\MMI PHARMINDEX\glwin.exe' 184 self.args = r'-KEEPBACKGROUND -PRESCRIPTIONFILE %s -CLOSETOTRAY' 185 186 paths = gmTools.gmPaths() 187 188 self.default_csv_filename = os.path.join(paths.home_dir, '.gnumed', 'tmp', 'rezept.txt') 189 self.default_csv_filename_arg = os.path.join(paths.home_dir, '.gnumed', 'tmp') 190 self.interactions_filename = os.path.join(paths.home_dir, '.gnumed', 'tmp', 'gm2mmi.bdt') 191 self.data_date_filename = r'C:\Programme\MMI PHARMINDEX\datadate.txt' 192 193 self.data_date = None 194 self.online_update_date = None
195 196 # use adjusted config.dat 197 #--------------------------------------------------------
198 - def get_data_source_version(self):
199 200 open(self.data_date_filename, 'wb').close() 201 202 cmd = u'%s -DATADATE' % self.path_to_binary 203 if not gmShellAPI.run_command_in_shell(command = cmd, blocking = True): 204 _log.error('problem querying the MMI drug database for version information') 205 return { 206 'data': u'?', 207 'online_update': u'?' 208 } 209 210 version_file = open(self.data_date_filename, 'rU') 211 versions = { 212 'data': version_file.readline()[:10], 213 'online_update': version_file.readline()[:10] 214 } 215 version_file.close() 216 217 return versions
218 #--------------------------------------------------------
219 - def create_data_source_entry(self):
220 versions = self.get_data_source_version() 221 222 args = { 223 'lname': u'Medikamentendatenbank "mmi PHARMINDEX" (Gelbe Liste)', 224 'sname': u'GL/MMI', 225 'ver': u'Daten: %s, Preise (Onlineupdate): %s' % (versions['data'], versions['online_update']), 226 'src': u'Medizinische Medien Informations GmbH, Am Forsthaus Gravenbruch 7, 63263 Neu-Isenburg', 227 'lang': u'de' 228 } 229 230 cmd = u"""select pk from ref.data_source where name_long = %(lname)s and name_short = %(sname)s and version = %(ver)s""" 231 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}]) 232 if len(rows) > 0: 233 return rows[0]['pk'] 234 235 cmd = u""" 236 INSERT INTO ref.data_source (name_long, name_short, version, source, lang) 237 VALUES ( 238 %(lname)s, 239 %(sname)s, 240 %(ver)s, 241 %(src)s, 242 %(lang)s 243 ) 244 returning pk 245 """ 246 247 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True) 248 249 return rows[0]['pk']
250 #--------------------------------------------------------
251 - def switch_to_frontend(self, blocking=False, cmd=None):
252 253 # must make sure csv file exists 254 open(self.default_csv_filename, 'wb').close() 255 256 if cmd is None: 257 cmd = (u'%s %s' % (self.path_to_binary, self.args)) % self.default_csv_filename_arg 258 259 if not gmShellAPI.run_command_in_shell(command = cmd, blocking = blocking): 260 _log.error('problem switching to the MMI drug database') 261 # apparently on the first call MMI does not 262 # consistently return 0 on success 263 # return False 264 265 return True
266 #--------------------------------------------------------
267 - def select_drugs(self, filename=None):
268 269 # better to clean up interactions file 270 open(self.interactions_filename, 'wb').close() 271 272 if not self.switch_to_frontend(blocking = True): 273 return None 274 275 return cGelbeListeCSVFile(filename = self.default_csv_filename)
276 #--------------------------------------------------------
278 279 selected_drugs = self.select_drugs() 280 if selected_drugs is None: 281 return None 282 283 new_substances = [] 284 285 for drug in selected_drugs: 286 atc = None # hopefully MMI eventually supports atc-per-substance in a drug... 287 if len(drug['wirkstoffe']) == 1: 288 atc = drug['atc'] 289 for wirkstoff in drug['wirkstoffe']: 290 new_substances.append(create_used_substance(substance = wirkstoff, atc = atc)) 291 292 selected_drugs.close() 293 294 return new_substances
295 #--------------------------------------------------------
296 - def import_drugs(self):
297 298 selected_drugs = self.select_drugs() 299 if selected_drugs is None: 300 return None 301 302 data_src_pk = self.create_data_source_entry() 303 304 new_drugs = [] 305 new_substances = [] 306 307 for entry in selected_drugs: 308 309 _log.debug('importing drug: %s %s', entry['name'], entry['darreichungsform']) 310 311 if entry[u'hilfsmittel']: 312 _log.debug('skipping Hilfsmittel') 313 continue 314 315 if entry[u'erstattbares_medizinprodukt']: 316 _log.debug('skipping sonstiges Medizinprodukt') 317 continue 318 319 # create branded drug (or get it if it already exists) 320 drug = create_branded_drug(brand_name = entry['name'], preparation = entry['darreichungsform']) 321 if drug is None: 322 drug = get_drug_by_brand(brand_name = entry['name'], preparation = entry['darreichungsform']) 323 new_drugs.append(drug) 324 325 # update fields 326 drug['is_fake'] = False 327 drug['atc_code'] = entry['atc'] 328 drug['external_code'] = u'%s::%s' % ('DE-PZN', entry['pzn']) 329 drug['fk_data_source'] = data_src_pk 330 drug.save() 331 332 # add components to brand 333 atc = None # hopefully MMI eventually supports atc-per-substance in a drug... 334 if len(entry['wirkstoffe']) == 1: 335 atc = entry['atc'] 336 for wirkstoff in entry['wirkstoffe']: 337 drug.add_component(substance = wirkstoff, atc = atc) 338 339 # create as consumable substances, too 340 atc = None # hopefully MMI eventually supports atc-per-substance in a drug... 341 if len(entry['wirkstoffe']) == 1: 342 atc = entry['atc'] 343 for wirkstoff in entry['wirkstoffe']: 344 new_substances.append(create_used_substance(substance = wirkstoff, atc = atc)) 345 346 return new_drugs, new_substances
347 #--------------------------------------------------------
348 - def check_drug_interactions(self, pzn_list=None, substances=None):
349 """For this to work the BDT interaction check must be configured in the MMI.""" 350 351 if pzn_list is None: 352 if substances is None: 353 return 354 if len(substances) < 2: 355 return 356 pzn_list = [ s.external_code for s in substances ] 357 pzn_list = [ pzn for pzn in pzn_list if pzn is not None ] 358 pzn_list = [ code_value for code_type, code_value in pzn_list if code_type == u'DE-PZN'] 359 360 else: 361 if len(pzn_list) < 2: 362 return 363 364 if pzn_list < 2: 365 return 366 367 bdt_file = codecs.open(filename = self.interactions_filename, mode = 'wb', encoding = cGelbeListeWindowsInterface.default_encoding) 368 369 for pzn in pzn_list: 370 pzn = pzn.strip() 371 lng = cGelbeListeWindowsInterface.bdt_line_base_length + len(pzn) 372 bdt_file.write(cGelbeListeWindowsInterface.bdt_line_template % (lng, pzn)) 373 374 bdt_file.close() 375 376 self.switch_to_frontend(blocking = False)
377 #--------------------------------------------------------
378 - def show_info_on_substance(self, substance=None):
379 380 cmd = None 381 382 if substance.external_code is not None: 383 code_type, pzn = substance.external_code 384 if code_type == u'DE-PZN': 385 cmd = u'%s -PZN %s' % (self.path_to_binary, pzn) 386 387 if cmd is None: 388 name = gmTools.coalesce ( 389 substance['brand'], 390 substance['substance'] 391 ) 392 cmd = u'%s -NAME %s' % (self.path_to_binary, name) 393 394 # better to clean up interactions file 395 open(self.interactions_filename, 'wb').close() 396 397 self.switch_to_frontend(cmd = cmd)
398 #============================================================
399 -class cGelbeListeWineInterface(cGelbeListeWindowsInterface):
400
401 - def __init__(self):
402 cGelbeListeWindowsInterface.__init__(self) 403 404 _log.info(u'%s (WINE extension)', cGelbeListeWindowsInterface.version) 405 406 # FIXME: if -CLOSETOTRAY is used GNUmed cannot detect the end of MMI 407 self.path_to_binary = r'wine "C:\Programme\MMI PHARMINDEX\glwin.exe"' 408 self.args = r'"-PRESCRIPTIONFILE %s -KEEPBACKGROUND"' 409 410 paths = gmTools.gmPaths() 411 412 self.default_csv_filename = os.path.join(paths.home_dir, '.wine', 'drive_c', 'windows', 'temp', 'mmi2gm.csv') 413 self.default_csv_filename_arg = r'c:\windows\temp\mmi2gm.csv' 414 self.interactions_filename = os.path.join(paths.home_dir, '.wine', 'drive_c', 'windows', 'temp', 'gm2mmi.bdt') 415 self.data_date_filename = os.path.join(paths.home_dir, '.wine', 'drive_c', 'Programme', 'MMI PHARMINDEX', 'datadate.txt')
416 #============================================================
417 -class cIfapInterface(cDrugDataSourceInterface):
418 """empirical CSV interface""" 419
420 - def __init__(self):
421 pass
422
423 - def print_transfer_file(self, filename=None):
424 425 try: 426 csv_file = open(filename, 'rb') # FIXME: encoding ? 427 except: 428 _log.exception('cannot access [%s]', filename) 429 csv_file = None 430 431 field_names = u'PZN Handelsname Form Abpackungsmenge Einheit Preis1 Hersteller Preis2 rezeptpflichtig Festbetrag Packungszahl Packungsgr\xf6\xdfe'.split() 432 433 if csv_file is None: 434 return False 435 436 csv_lines = csv.DictReader ( 437 csv_file, 438 fieldnames = field_names, 439 delimiter = ';' 440 ) 441 442 for line in csv_lines: 443 print "--------------------------------------------------------------------"[:31] 444 for key in field_names: 445 tmp = ('%s ' % key)[:30] 446 print '%s: %s' % (tmp, line[key]) 447 448 csv_file.close()
449 450 # narr = u'%sx %s %s %s (\u2258 %s %s) von %s (%s)' % ( 451 # line['Packungszahl'].strip(), 452 # line['Handelsname'].strip(), 453 # line['Form'].strip(), 454 # line[u'Packungsgr\xf6\xdfe'].strip(), 455 # line['Abpackungsmenge'].strip(), 456 # line['Einheit'].strip(), 457 # line['Hersteller'].strip(), 458 # line['PZN'].strip() 459 # ) 460 #============================================================ 461 drug_data_source_interfaces = { 462 'Gelbe Liste/MMI (Windows)': cGelbeListeWindowsInterface, 463 'Gelbe Liste/MMI (WINE)': cGelbeListeWineInterface 464 } 465 #============================================================ 466 # substances in use across all patients 467 #------------------------------------------------------------
468 -def get_substances_in_use():
469 cmd = u'select * from clin.consumed_substance order by description' 470 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}]) 471 return rows
472 #------------------------------------------------------------
473 -def get_substance_by_pk(pk=None):
474 cmd = u'select * from clin.consumed_substance WHERE pk = %(pk)s' 475 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': {'pk': pk}}]) 476 if len(rows) == 0: 477 return None 478 return rows[0]
479 #------------------------------------------------------------
480 -def create_used_substance(substance=None, atc=None):
481 482 substance = substance.strip() 483 484 if atc is not None: 485 atc = atc.strip() 486 487 args = {'desc': substance, 'atc': atc} 488 489 cmd = u'select pk, atc_code, description from clin.consumed_substance where description = %(desc)s' 490 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}]) 491 492 if len(rows) == 0: 493 cmd = u'insert into clin.consumed_substance (description, atc_code) values (%(desc)s, gm.nullify_empty_string(%(atc)s)) returning pk, atc_code, description' 494 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True) 495 496 gmATC.propagate_atc(substance = substance, atc = atc) 497 498 row = rows[0] 499 # unfortunately not a real dict so no setting stuff by keyword 500 #row['atc_code'] = args['atc'] 501 row[1] = args['atc'] 502 return row
503 #------------------------------------------------------------
504 -def delete_used_substance(substance=None):
505 args = {'pk': substance} 506 cmd = u""" 507 delete from clin.consumed_substance 508 where 509 pk = %(pk)s and not exists ( 510 select 1 from clin.substance_intake 511 where fk_substance = %(pk)s 512 )""" 513 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
514 #============================================================
515 -class cSubstanceIntakeEntry(gmBusinessDBObject.cBusinessDBObject):
516 """Represents a substance currently taken by a patient.""" 517 518 _cmd_fetch_payload = u"select * from clin.v_pat_substance_intake where pk_substance_intake = %s" 519 _cmds_store_payload = [ 520 u"""update clin.substance_intake set 521 clin_when = %(started)s, 522 strength = gm.nullify_empty_string(%(strength)s), 523 preparation = %(preparation)s, 524 schedule = gm.nullify_empty_string(%(schedule)s), 525 aim = gm.nullify_empty_string(%(aim)s), 526 narrative = gm.nullify_empty_string(%(notes)s), 527 intake_is_approved_of = %(intake_is_approved_of)s, 528 529 -- is_long_term = %(is_long_term)s, 530 is_long_term = ( 531 case 532 when ( 533 (%(is_long_term)s is False) 534 and 535 (gm.is_null_or_blank_string(%(duration)s) is True) 536 ) is True then null 537 else %(is_long_term)s 538 end 539 )::boolean, 540 duration = ( 541 case 542 when %(is_long_term)s is True then null 543 else gm.nullify_empty_string(%(duration)s) 544 end 545 )::interval, 546 547 fk_brand = %(pk_brand)s, 548 fk_substance = %(pk_substance)s, 549 fk_episode = %(pk_episode)s 550 where 551 pk = %(pk_substance_intake)s and 552 xmin = %(xmin_substance_intake)s 553 returning 554 xmin as xmin_substance_intake 555 """ 556 ] 557 _updatable_fields = [ 558 u'started', 559 u'preparation', 560 u'strength', 561 u'intake_is_approved_of', 562 u'schedule', 563 u'duration', 564 u'aim', 565 u'is_long_term', 566 u'notes', 567 u'pk_brand', 568 u'pk_substance', 569 u'pk_episode' 570 ] 571 #--------------------------------------------------------
572 - def format(self, left_margin=0, date_format='%Y-%m-%d'):
573 574 if self._payload[self._idx['duration']] is None: 575 duration = gmTools.bool2subst ( 576 self._payload[self._idx['is_long_term']], 577 _('long-term'), 578 _('short-term'), 579 _('?short-term') 580 ) 581 else: 582 duration = gmDateTime.format_interval ( 583 self._payload[self._idx['duration']], 584 accuracy_wanted = gmDateTime.acc_days 585 ) 586 587 line = u'%s%s (%s %s): %s %s %s (%s)' % ( 588 u' ' * left_margin, 589 self._payload[self._idx['started']].strftime(date_format), 590 gmTools.u_right_arrow, 591 duration, 592 self._payload[self._idx['substance']], 593 self._payload[self._idx['strength']], 594 self._payload[self._idx['preparation']], 595 gmTools.bool2subst(self._payload[self._idx['is_currently_active']], _('ongoing'), _('inactive'), _('?ongoing')) 596 ) 597 598 return line
599 #--------------------------------------------------------
600 - def _get_external_code(self):
601 drug = self.containing_drug 602 603 if drug is None: 604 return None 605 606 return drug.external_code
607 608 external_code = property(_get_external_code, lambda x:x) 609 #--------------------------------------------------------
610 - def _get_containing_drug(self):
611 if self._payload[self._idx['pk_brand']] is None: 612 return None 613 614 return cBrandedDrug(aPK_obj = self._payload[self._idx['pk_brand']])
615 616 containing_drug = property(_get_containing_drug, lambda x:x) 617 #--------------------------------------------------------
618 - def _get_parsed_schedule(self):
619 tests = [ 620 # lead, trail 621 ' 1-1-1-1 ', 622 # leading dose 623 '1-1-1-1', 624 '22-1-1-1', 625 '1/3-1-1-1', 626 '/4-1-1-1' 627 ] 628 pattern = "^(\d\d|/\d|\d/\d|\d)[\s-]{1,5}\d{0,2}[\s-]{1,5}\d{0,2}[\s-]{1,5}\d{0,2}$" 629 for test in tests: 630 print test.strip(), ":", regex.match(pattern, test.strip())
631 #------------------------------------------------------------
632 -def create_substance_intake(substance=None, atc=None, encounter=None, episode=None, preparation=None):
633 634 args = { 635 'enc': encounter, 636 'epi': episode, 637 'prep': preparation, 638 'subst': create_used_substance(substance = substance, atc = atc)['pk'] 639 } 640 641 cmd = u""" 642 insert into clin.substance_intake ( 643 fk_encounter, 644 fk_episode, 645 fk_substance, 646 preparation, 647 intake_is_approved_of 648 ) values ( 649 %(enc)s, 650 %(epi)s, 651 %(subst)s, 652 gm.nullify_empty_string(%(prep)s), 653 False 654 ) 655 returning pk 656 """ 657 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True) 658 return cSubstanceIntakeEntry(aPK_obj = rows[0][0])
659 #------------------------------------------------------------
660 -def delete_substance_intake(substance=None):
661 cmd = u'delete from clin.substance_intake where pk = %(pk)s' 662 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': {'pk': substance}}])
663 #============================================================
664 -class cBrandedDrug(gmBusinessDBObject.cBusinessDBObject):
665 """Represents a drug as marketed by a manufacturer.""" 666 667 _cmd_fetch_payload = u"select *, xmin from ref.branded_drug where pk = %s" 668 _cmds_store_payload = [ 669 u"""update ref.branded_drug set 670 description = %(description)s, 671 preparation = %(preparation)s, 672 atc_code = gm.nullify_empty_string(%(atc_code)s), 673 external_code = gm.nullify_empty_string(%(external_code)s), 674 is_fake = %(is_fake)s, 675 fk_data_source = %(fk_data_source)s 676 where 677 pk = %(pk)s and 678 xmin = %(xmin)s 679 returning 680 xmin 681 """ 682 ] 683 _updatable_fields = [ 684 u'description', 685 u'preparation', 686 u'atc_code', 687 u'is_fake', 688 u'external_code', 689 u'fk_data_source' 690 ] 691 #--------------------------------------------------------
692 - def _get_external_code(self):
693 if self._payload[self._idx['external_code']] is None: 694 return None 695 696 if regex.match(u'.+::.+', self._payload[self._idx['external_code']], regex.UNICODE) is None: 697 # FIXME: maybe evaluate fk_data_source 698 return None 699 700 return regex.split(u'::', self._payload[self._idx['external_code']], 1)
701 702 external_code = property(_get_external_code, lambda x:x) 703 #--------------------------------------------------------
704 - def _get_components(self):
705 cmd = u'select * from ref.substance_in_brand where fk_brand = %(brand)s' 706 args = {'brand': self._payload[self._idx['pk']]} 707 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False) 708 return rows
709 710 components = property(_get_components, lambda x:x) 711 #--------------------------------------------------------
712 - def add_component(self, substance=None, atc=None):
713 714 # normalize atc 715 atc = gmATC.propagate_atc(substance = substance, atc = atc) 716 717 args = { 718 'brand': self.pk_obj, 719 'desc': substance, 720 'atc': atc 721 } 722 723 # already exists ? 724 cmd = u""" 725 SELECT pk 726 FROM ref.substance_in_brand 727 WHERE 728 fk_brand = %(brand)s 729 AND 730 ((description = %(desc)s) OR ((atc_code = %(atc)s) IS TRUE)) 731 """ 732 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False) 733 if len(rows) > 0: 734 return 735 736 # create it 737 cmd = u""" 738 INSERT INTO ref.substance_in_brand (fk_brand, description, atc_code) 739 VALUES (%(brand)s, %(desc)s, %(atc)s) 740 """ 741 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
742 #------------------------------------------------------------
743 - def remove_component(substance=None):
744 delete_component_from_branded_drug(brand = self.pk_obj, component = substance)
745 #------------------------------------------------------------
746 -def get_substances_in_brands():
747 cmd = u'SELECT * FROM ref.v_substance_in_brand ORDER BY brand, substance' 748 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = False) 749 return rows
750 #------------------------------------------------------------
751 -def get_branded_drugs():
752 753 cmd = u'SELECT pk FROM ref.branded_drug ORDER BY description' 754 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = False) 755 756 return [ cBrandedDrug(aPK_obj = r['pk']) for r in rows ]
757 #------------------------------------------------------------
758 -def get_drug_by_brand(brand_name=None, preparation=None):
759 args = {'brand': brand_name, 'prep': preparation} 760 761 cmd = u'SELECT pk FROM ref.branded_drug WHERE description = %(brand)s AND preparation = %(prep)s' 762 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False) 763 764 if len(rows) == 0: 765 return None 766 767 return cBrandedDrug(aPK_obj = rows[0]['pk'])
768 #------------------------------------------------------------
769 -def create_branded_drug(brand_name=None, preparation=None, return_existing=False):
770 771 if preparation is None: 772 preparation = _('units') 773 774 if preparation.strip() == u'': 775 preparation = _('units') 776 777 drug = get_drug_by_brand(brand_name = brand_name, preparation = preparation) 778 779 if drug is not None: 780 if return_existing: 781 return drug 782 return None 783 784 cmd = u'insert into ref.branded_drug (description, preparation) values (%(brand)s, %(prep)s) returning pk' 785 args = {'brand': brand_name, 'prep': preparation} 786 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True, get_col_idx = False) 787 788 return cBrandedDrug(aPK_obj = rows[0]['pk'])
789 #------------------------------------------------------------
790 -def delete_branded_drug(brand=None):
791 cmd = u'delete from ref.branded_drug where pk = %(pk)s' 792 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': {'pk': brand}}])
793 #------------------------------------------------------------
794 -def delete_component_from_branded_drug(brand=None, component=None):
795 cmd = u'delete from ref.substance_in_brand where fk_brand = %(brand)s and pk = %(comp)s' 796 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': {'brand': brand, 'comp': component}}])
797 #============================================================ 798 # main 799 #------------------------------------------------------------ 800 if __name__ == "__main__": 801 802 from Gnumed.pycommon import gmLog2 803 from Gnumed.pycommon import gmI18N 804 805 gmI18N.activate_locale() 806 # gmDateTime.init() 807 #--------------------------------------------------------
808 - def test_MMI_interface():
809 mmi = cGelbeListeWineInterface() 810 print mmi 811 print "interface definition:", mmi.version 812 print "database versions: ", mmi.get_data_source_version()
813 #--------------------------------------------------------
814 - def test_MMI_file():
815 mmi_file = cGelbeListeCSVFile(filename = sys.argv[2]) 816 for drug in mmi_file: 817 print "-------------" 818 print '"%s" (ATC: %s / PZN: %s)' % (drug['name'], drug['atc'], drug['pzn']) 819 for stoff in drug['wirkstoffe']: 820 print " Wirkstoff:", stoff 821 print drug 822 mmi_file.close()
823 #--------------------------------------------------------
824 - def test_mmi_switch_to():
825 mmi = cGelbeListeWineInterface() 826 mmi.switch_to_frontend(blocking = False)
827 #--------------------------------------------------------
828 - def test_mmi_select_drugs():
829 mmi = cGelbeListeWineInterface() 830 mmi_file = mmi.select_drugs() 831 for drug in mmi_file: 832 print "-------------" 833 print '"%s" (ATC: %s / PZN: %s)' % (drug['name'], drug['atc'], drug['pzn']) 834 for stoff in drug['wirkstoffe']: 835 print " Wirkstoff:", stoff 836 print drug 837 mmi_file.close()
838 #--------------------------------------------------------
839 - def test_mmi_import_drugs():
840 mmi = cGelbeListeWineInterface() 841 mmi.import_drugs()
842 #--------------------------------------------------------
843 - def test_mmi_interaction_check():
844 mmi = cGelbeListeInterface() 845 print mmi 846 print "interface definition:", mmi.version 847 # Metoprolol + Hct vs Citalopram 848 diclofenac = '7587712' 849 phenprocoumon = '4421744' 850 mmi.check_drug_interactions(pzn_list = [diclofenac, phenprocoumon])
851 #--------------------------------------------------------
852 - def test_create_substance_intake():
853 drug = create_substance_intake ( 854 substance = u'Whiskey', 855 atc = u'no ATC available', 856 encounter = 1, 857 episode = 1, 858 preparation = 'a nice glass' 859 ) 860 print drug
861 #--------------------------------------------------------
862 - def test_show_components():
863 drug = cBrandedDrug(aPK_obj = sys.argv[2]) 864 print drug 865 print drug.components
866 #-------------------------------------------------------- 867 if (len(sys.argv)) > 1 and (sys.argv[1] == 'test'): 868 #test_MMI_interface() 869 #test_MMI_file() 870 #test_mmi_switch_to() 871 #test_mmi_select_drugs() 872 #test_mmi_import_substances() 873 #test_mmi_import_drugs() 874 #test_interaction_check() 875 #test_create_substance_intake() 876 test_show_components() 877 #============================================================ 878 # $Log: gmMedication.py,v $ 879 # Revision 1.20 2009/12/25 21:38:50 ncq 880 # - add 2 new fields to MMI CSV file 881 # - show-info-on-drug 882 # - enhance switch-to-frontend to allow custom startup cmd 883 # 884 # Revision 1.19 2009/12/02 16:48:58 ncq 885 # - add infrastructure for removing component from brand 886 # 887 # Revision 1.18 2009/12/01 21:48:09 ncq 888 # - get-substance-by-pk 889 # 890 # Revision 1.17 2009/11/30 21:56:36 ncq 891 # - components property on branded drug 892 # 893 # Revision 1.16 2009/11/30 15:06:27 ncq 894 # - handle a bunch of possibilities of dirty records retrieved from GLI/MMI 895 # - default preparation to i18n(units) 896 # 897 # Revision 1.15 2009/11/29 19:59:31 ncq 898 # - improve substance/component creation with propagate-atc 899 # 900 # Revision 1.14 2009/11/29 15:57:27 ncq 901 # - while SQL results are dicts as far as *retrieval* is concerned, 902 # they are NOT for inserting data into them, so use list access 903 # 904 # Revision 1.13 2009/11/28 18:27:30 ncq 905 # - much improved ATC detection on substance creation 906 # - create-patient-consumed-substance -> create-substance-intake 907 # - get-branded-drugs 908 # - get-substances-in-brands 909 # - delete-branded-drugs 910 # 911 # Revision 1.12 2009/11/24 19:57:22 ncq 912 # - implement getting/creating data souce entry for MMI 913 # - implement version retrieval for MMI 914 # - import-drugs() 915 # - check-drug-interactions() 916 # - cConsumedSubstance -> cSubstanceIntakeEntry + .external_code 917 # - cBrandedDrug 918 # - tests 919 # 920 # Revision 1.11 2009/11/06 15:05:07 ncq 921 # - get-substances-in-use 922 # - meds formatting 923 # - delete-patient-consumed-substance 924 # 925 # Revision 1.10 2009/10/29 17:16:59 ncq 926 # - return newly created substances from creator func and substance importer method 927 # - better naming 928 # - finish up cConsumedSubstance 929 # 930 # Revision 1.9 2009/10/28 16:40:12 ncq 931 # - add some docs about schedule parsing 932 # 933 # Revision 1.8 2009/10/26 22:29:05 ncq 934 # - better factorization of paths in MMI interface 935 # - update ATC on INN if now known 936 # - delete-consumed-substance 937 # 938 # Revision 1.7 2009/10/21 20:37:18 ncq 939 # - MMI uses cp1250, rather than cp1252, (at least under WINE) contrary to direct communication ... 940 # - use unicode csv reader 941 # - add a bunch of file cleanup 942 # - split MMI interface into WINE vs native Windows version 943 # 944 # Revision 1.6 2009/10/21 09:15:50 ncq 945 # - much improved MMI frontend 946 # 947 # Revision 1.5 2009/09/29 13:14:25 ncq 948 # - faulty ordering of definitions 949 # 950 # Revision 1.4 2009/09/01 22:16:35 ncq 951 # - improved interaction check test 952 # 953 # Revision 1.3 2009/08/24 18:36:20 ncq 954 # - add CSV file iterator 955 # - add BDT interaction check 956 # 957 # Revision 1.2 2009/08/21 09:56:37 ncq 958 # - start drug data source interfaces 959 # - add MMI/Gelbe Liste interface 960 # 961 # Revision 1.1 2009/05/12 12:02:01 ncq 962 # - start supporting current medications 963 # 964 # 965