| Home | Trees | Indices | Help |
|
|---|
|
|
1 # -*- coding: utf8 -*-
2 """Medication handling code.
3
4 license: GPL
5 """
6 #============================================================
7 __version__ = "$Revision: 1.21 $"
8 __author__ = "K.Hilbert <Karsten.Hilbert@gmx.net>"
9
10 import sys, logging, csv, codecs, os, re as regex, subprocess, decimal
11 from xml.etree import ElementTree as etree
12
13
14 if __name__ == '__main__':
15 sys.path.insert(0, '../../')
16 from Gnumed.pycommon import gmBusinessDBObject, gmPG2, gmShellAPI, gmTools
17 from Gnumed.pycommon import gmDispatcher, gmDateTime, gmHooks
18 from Gnumed.business import gmATC, gmAllergy
19
20
21 _log = logging.getLogger('gm.meds')
22 _log.info(__version__)
23
24 #============================================================
26 """Always relates to the active patient."""
27 gmHooks.run_hook_script(hook = u'after_substance_intake_modified')
28
29 gmDispatcher.connect(_on_substance_intake_modified, u'substance_intake_mod_db')
30
31 #============================================================
33
34 if search_term is None:
35 return u'http://www.dosing.de'
36
37 terms = []
38 names = []
39
40 if isinstance(search_term, cBrandedDrug):
41 if search_term['atc_code'] is not None:
42 terms.append(search_term['atc_code'])
43
44 elif isinstance(search_term, cSubstanceIntakeEntry):
45 names.append(search_term['substance'])
46 if search_term['atc_brand'] is not None:
47 terms.append(search_term['atc_brand'])
48 if search_term['atc_substance'] is not None:
49 terms.append(search_term['atc_substance'])
50
51 elif search_term is not None:
52 names.append(u'%s' % search_term)
53 terms.extend(gmATC.text2atc(text = u'%s' % search_term, fuzzy = True))
54
55 for name in names:
56 if name.endswith('e'):
57 terms.append(name[:-1])
58 else:
59 terms.append(name)
60
61 #url_template = u'http://www.google.de/#q=site%%3Adosing.de+%s'
62 #url = url_template % u'+OR+'.join(terms)
63
64 url_template = u'http://www.google.de/search?hl=de&source=hp&q=site%%3Adosing.de+%s&btnG=Google-Suche'
65 url = url_template % u'+OR+'.join(terms)
66
67 _log.debug(u'renal insufficiency URL: %s', url)
68
69 return url
70 #============================================================
71 # this should be in gmCoding.py
72 -def create_data_source(long_name=None, short_name=None, version=None, source=None, language=None):
73
74 args = {
75 'lname': long_name,
76 'sname': short_name,
77 'ver': version,
78 'src': source,
79 'lang': language
80 }
81
82 cmd = u"""select pk from ref.data_source where name_long = %(lname)s and name_short = %(sname)s and version = %(ver)s"""
83 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}])
84 if len(rows) > 0:
85 return rows[0]['pk']
86
87 cmd = u"""
88 INSERT INTO ref.data_source (name_long, name_short, version, source, lang)
89 VALUES (
90 %(lname)s,
91 %(sname)s,
92 %(ver)s,
93 %(src)s,
94 %(lang)s
95 )
96 returning pk
97 """
98 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True)
99
100 return rows[0]['pk']
101 #============================================================
102 # wishlist:
103 # - --conf-file= for glwin.exe
104 # - wirkstoff: Konzentration auch in Multiprodukten
105 # - wirkstoff: ATC auch in Multiprodukten
106 # - Suche nach ATC per CLI
107
109 """Iterator over a Gelbe Liste/MMI v8.2 CSV file."""
110
111 version = u'Gelbe Liste/MMI v8.2 CSV file interface'
112 default_transfer_file_windows = r"c:\rezept.txt"
113 #default_encoding = 'cp1252'
114 default_encoding = 'cp1250'
115 csv_fieldnames = [
116 u'name',
117 u'packungsgroesse', # obsolete, use "packungsmenge"
118 u'darreichungsform',
119 u'packungstyp',
120 u'festbetrag',
121 u'avp',
122 u'hersteller',
123 u'rezepttext',
124 u'pzn',
125 u'status_vertrieb',
126 u'status_rezeptpflicht',
127 u'status_fachinfo',
128 u'btm',
129 u'atc',
130 u'anzahl_packungen',
131 u'zuzahlung_pro_packung',
132 u'einheit',
133 u'schedule_morgens',
134 u'schedule_mittags',
135 u'schedule_abends',
136 u'schedule_nachts',
137 u'status_dauermedikament',
138 u'status_hausliste',
139 u'status_negativliste',
140 u'ik_nummer',
141 u'status_rabattvertrag',
142 u'wirkstoffe',
143 u'wirkstoffmenge',
144 u'wirkstoffeinheit',
145 u'wirkstoffmenge_bezug',
146 u'wirkstoffmenge_bezugseinheit',
147 u'status_import',
148 u'status_lifestyle',
149 u'status_ausnahmeliste',
150 u'packungsmenge',
151 u'apothekenpflicht',
152 u'status_billigere_packung',
153 u'rezepttyp',
154 u'besonderes_arzneimittel', # Abstimmungsverfahren SGB-V
155 u't_rezept_pflicht', # Thalidomid-Rezept
156 u'erstattbares_medizinprodukt',
157 u'hilfsmittel',
158 u'hzv_rabattkennung',
159 u'hzv_preis'
160 ]
161 boolean_fields = [
162 u'status_rezeptpflicht',
163 u'status_fachinfo',
164 u'btm',
165 u'status_dauermedikament',
166 u'status_hausliste',
167 u'status_negativliste',
168 u'status_rabattvertrag',
169 u'status_import',
170 u'status_lifestyle',
171 u'status_ausnahmeliste',
172 u'apothekenpflicht',
173 u'status_billigere_packung',
174 u'besonderes_arzneimittel', # Abstimmungsverfahren SGB-V
175 u't_rezept_pflicht',
176 u'erstattbares_medizinprodukt',
177 u'hilfsmittel'
178 ]
179 #--------------------------------------------------------
181
182 _log.info(cGelbeListeCSVFile.version)
183
184 self.filename = filename
185 if filename is None:
186 self.filename = cGelbeListeCSVFile.default_transfer_file_windows
187
188 _log.debug('reading Gelbe Liste/MMI drug data from [%s]', self.filename)
189
190 self.csv_file = codecs.open(filename = filename, mode = 'rUb', encoding = cGelbeListeCSVFile.default_encoding)
191
192 self.csv_lines = gmTools.unicode_csv_reader (
193 self.csv_file,
194 fieldnames = cGelbeListeCSVFile.csv_fieldnames,
195 delimiter = ';',
196 quotechar = '"',
197 dict = True
198 )
199 #--------------------------------------------------------
202 #--------------------------------------------------------
204 line = self.csv_lines.next()
205
206 for field in cGelbeListeCSVFile.boolean_fields:
207 line[field] = (line[field].strip() == u'T')
208
209 # split field "Wirkstoff" by ";"
210 if line['wirkstoffe'].strip() == u'':
211 line['wirkstoffe'] = []
212 else:
213 line['wirkstoffe'] = [ wirkstoff.strip() for wirkstoff in line['wirkstoffe'].split(u';') ]
214
215 return line
216 #--------------------------------------------------------
218 try: self.csv_file.close()
219 except: pass
220
221 if truncate:
222 try: os.open(self.filename, 'wb').close
223 except: pass
224 #--------------------------------------------------------
227
228 has_unknown_fields = property(_get_has_unknown_fields, lambda x:x)
229 #============================================================
231
232 #--------------------------------------------------------
236 #--------------------------------------------------------
239 #--------------------------------------------------------
242 #--------------------------------------------------------
245 #--------------------------------------------------------
248 #--------------------------------------------------------
251 #--------------------------------------------------------
254 #--------------------------------------------------------
257 #--------------------------------------------------------
260 #============================================================
262
263 version = u'FreeDiams v0.5.0 interface'
264 default_encoding = 'utf8'
265 default_dob_format = '%Y/%m/%d'
266
267 map_gender2mf = {
268 'm': u'M',
269 'f': u'F',
270 'tf': u'H',
271 'tm': u'H',
272 'h': u'H'
273 }
274 #--------------------------------------------------------
276 cDrugDataSourceInterface.__init__(self)
277 _log.info(cFreeDiamsInterface.version)
278
279 paths = gmTools.gmPaths()
280 self.__gm2fd_filename = os.path.join(paths.home_dir, '.gnumed', 'tmp', 'gm2freediams.xml')
281 self.__fd2gm_filename = os.path.join(paths.home_dir, '.gnumed', 'tmp', 'freediams2gm.xml')
282 self.__fd4gm_config_file = os.path.join(paths.home_dir, '.gnumed', 'freediams4gm.conf')
283
284 self.path_to_binary = None
285 self.__detect_binary()
286 #--------------------------------------------------------
288 # ~/.freediams/config.ini: [License] -> AcceptedVersion=....
289
290 if not self.__detect_binary():
291 return False
292
293 freediams = subprocess.Popen (
294 args = u'--version', # --version or -version or -v
295 executable = self.path_to_binary,
296 stdout = subprocess.PIPE,
297 stderr = subprocess.PIPE,
298 # close_fds = True, # Windows can't do that in conjunction with stdout/stderr = ... :-(
299 universal_newlines = True
300 )
301 data, errors = freediams.communicate()
302 version = regex.search('FreeDiams\s\d.\d.\d', data).group().split()[1]
303 _log.debug('FreeDiams %s', version)
304
305 return version
306 #--------------------------------------------------------
308 return create_data_source (
309 long_name = u'"FreeDiams" Drug Database Frontend',
310 short_name = u'FreeDiams',
311 version = self.get_data_source_version(),
312 source = u'http://ericmaeker.fr/FreeMedForms/di-manual/index.html',
313 language = u'fr' # actually to be multi-locale
314 )
315 #--------------------------------------------------------
317 """http://ericmaeker.fr/FreeMedForms/di-manual/en/html/ligne_commandes.html"""
318
319 if not self.__detect_binary():
320 return False
321
322 self.__create_gm2fd_file()
323 open(self.__fd2gm_filename, 'wb').close()
324
325 args = u'--exchange-in="%s"' % (self.__gm2fd_filename)
326 cmd = r'%s %s' % (self.path_to_binary, args)
327 if not gmShellAPI.run_command_in_shell(command = cmd, blocking = blocking):
328 _log.error('problem switching to the FreeDiams drug database')
329 return False
330
331 return True
332 #--------------------------------------------------------
334 self.switch_to_frontend()
335 #--------------------------------------------------------
337 """FreeDiams ONLY use CIS.
338
339 CIS stands for Unique Speciality Identifier (eg bisoprolol 5 mg, gel).
340 CIS is AFSSAPS specific, but pharmacist can retreive drug name with the CIS.
341 AFSSAPS is the French FDA.
342
343 CIP stands for Unique Presentation Identifier (eg 30 pills plaq)
344 CIP if you want to specify the packaging of the drug (30 pills
345 thermoformed tablet...) -- actually not really usefull for french
346 doctors.
347 # .external_code_type: u'FR-CIS'
348 # .external_cod: the CIS value
349 """
350 self.switch_to_frontend(blocking = True)
351 self.import_fd2gm_file()
352 #--------------------------------------------------------
354
355 if substances is None:
356 return
357 if len(substances) < 2:
358 return
359 drug_ids_list = [ (s.external_code_type, s.external_code) for s in substances ]
360 drug_ids_list = [ (code_value, code_type) for code_type, code_value in drug_ids_list if (code_value is not None)]
361
362 if drug_ids_list < 2:
363 return
364
365 self.__create_prescription_file(drug_ids_list = drug_ids_list)
366 self.switch_to_frontend(blocking = False)
367 #--------------------------------------------------------
372 #--------------------------------------------------------
374 if substance is None:
375 return
376 self.__create_prescription_file (
377 drug_ids_list = [(substance.external_code, substance.external_code_type)]
378 )
379 self.switch_to_frontend()
380 #--------------------------------------------------------
381 # internal helpers
382 #--------------------------------------------------------
384
385 if self.path_to_binary is not None:
386 return True
387
388 found, cmd = gmShellAPI.find_first_binary(binaries = [
389 r'/usr/bin/freediams',
390 r'freediams',
391 r'/Applications/FreeDiams.app/Contents/MacOs/FreeDiams',
392 r'c:\programs\freediams\freediams.exe',
393 r'freediams.exe'
394 ])
395
396 if found:
397 self.path_to_binary = cmd
398 return True
399
400 try:
401 self.custom_path_to_binary
402 except AttributeError:
403 _log.error('cannot find FreeDiams binary, no custom path set')
404 return False
405
406 found, cmd = gmShellAPI.detect_external_binary(binary = self.custom_path_to_binary)
407 if found:
408 self.path_to_binary = cmd
409 return True
410
411 _log.error('cannot find FreeDiams binary')
412 return False
413 #--------------------------------------------------------
415
416 # FIXME: pass in more data
417
418 xml = u"""<?xml version = "1.0" encoding = "UTF-8"?>
419
420 <FreeDiams>
421 <DrugsDatabaseName>%s</DrugsDatabaseName>
422 <FullPrescription version="0.4.0">
423
424 %s
425
426 </FullPrescription>
427 </FreeDiams>
428 """
429 drug_snippet = u"""<Prescription>
430 <OnlyForTest>True</OnlyForTest>
431 <Drug_UID>%s</Drug_UID>
432 <!-- <Drug_UID_type>%s</Drug_UID_type> -->
433 </Prescription>"""
434
435 xml_file = codecs.open(self.__fd2gm_filename, 'wb', 'utf8')
436
437 last_db_id = u'CA_HCDPD'
438 drug_snippets = []
439 for drug_id, db_id in drug_ids_list:
440 if db_id is not None:
441 last_db_id = db_id.replace(u'FreeDiams::', u'')
442 drug_snippets.append(drug_snippet % (drug_id, last_db_id))
443
444 xml_file.write(xml % (
445 last_db_id,
446 u'\n\t\t'.join(drug_snippets)
447 ))
448
449 xml_file.close()
450 #--------------------------------------------------------
452
453 xml_file = codecs.open(self.__gm2fd_filename, 'wb', 'utf8')
454
455 xml = u"""<?xml version="1.0" encoding="UTF-8"?>
456
457 <!-- Eric says the order of same-level nodes does not matter. -->
458
459 <FreeDiams_In version="0.5.0">
460 <EMR name="GNUmed" uid="unused"/>
461 <ConfigFile value="%s"/>
462 <ExchangeOut value="%s" format="xml"/> <!-- should perhaps better be html_xml ? -->
463 <!-- <DrugsDatabase uid="can be set to a specific DB"/> -->
464 <Ui editmode="select-only" blockPatientDatas="1"/>
465 %%s
466 </FreeDiams_In>
467
468 <!--
469 # FIXME: search by LOINC code and add (as soon as supported by FreeDiams ...)
470 <Creatinine value="12" unit="mg/l or mmol/l"/>
471 <Weight value="70" unit="kg or pd" />
472 <Height value="170" unit="cm or "/>
473 <ICD10 value="J11.0;A22;Z23"/>
474 -->
475 """ % (
476 self.__fd4gm_config_file,
477 self.__fd2gm_filename
478 )
479
480 if self.patient is None:
481 xml_file.write(xml % u'')
482 xml_file.close()
483 return
484
485 name = self.patient.get_active_name()
486 if self.patient['dob'] is None:
487 dob = u''
488 else:
489 dob = self.patient['dob'].strftime(cFreeDiamsInterface.default_dob_format)
490
491 emr = self.patient.get_emr()
492 allgs = emr.get_allergies()
493 atc_allgs = [
494 a['atc_code'] for a in allgs if ((a['atc_code'] is not None) and (a['type'] == u'allergy'))
495 ]
496 atc_sens = [
497 a['atc_code'] for a in allgs if ((a['atc_code'] is not None) and (a['type'] == u'sensitivity'))
498 ]
499 inn_allgs = [ a['allergene'] for a in allgs if a['type'] == u'allergy' ]
500 inn_sens = [ a['allergene'] for a in allgs if a['type'] == u'sensitivity' ]
501 # this is rather fragile: FreeDiams won't know what type of UID this is
502 # (but it will assume it is of the type of the drug database in use)
503 uid_allgs = [
504 a['substance_code'] for a in allgs if ((a['substance_code'] is not None) and (a['type'] == u'allergy'))
505 ]
506 uid_sens = [
507 a['substance_code'] for a in allgs if ((a['substance_code'] is not None) and (a['type'] == u'sensitivity'))
508 ]
509
510 patient_xml = u"""<Patient>
511 <Identity
512 lastnames="%s"
513 firstnames="%s"
514 uid="%s"
515 dob="%s"
516 gender="%s"
517 />
518 <ATCAllergies value="%s"/>
519 <ATCIntolerances value="%s"/>
520
521 <InnAllergies value="%s"/>
522 <InnIntolerances value="%s"/>
523
524 <DrugsUidAllergies value="%s"/>
525 <DrugsUidIntolerances value="%s"/>
526 </Patient>
527 """ % (
528 name['lastnames'],
529 name['firstnames'],
530 self.patient.ID,
531 dob,
532 cFreeDiamsInterface.map_gender2mf[self.patient['gender']],
533 u';'.join(atc_allgs),
534 u';'.join(atc_sens),
535 u';'.join(inn_allgs),
536 u';'.join(inn_sens),
537 u';'.join(uid_allgs),
538 u';'.join(uid_sens)
539 )
540
541 xml_file.write(xml % patient_xml)
542 xml_file.close()
543 #--------------------------------------------------------
545 """
546 If returning textual prescriptions (say, drugs which FreeDiams
547 did not know) then "IsTextual" will be True and UID will be -1.
548 """
549 fd2gm_xml = etree.ElementTree()
550 fd2gm_xml.parse(self.__fd2gm_filename)
551
552 data_src_pk = self.create_data_source_entry()
553
554 db_id = fd2gm_xml.find('DrugsDatabaseName').text.strip()
555 drugs = fd2gm_xml.findall('FullPrescription/Prescription')
556 for drug in drugs:
557 drug_name = drug.find('DrugName').text.replace(', )', ')').strip()
558 drug_uid = drug.find('Drug_UID').text.strip()
559 drug_form = drug.find('DrugForm').text.strip()
560 #drug_atc = drug.find('DrugATC').text.strip() # asked Eric to include
561
562 new_drug = create_branded_drug(brand_name = drug_name, preparation = drug_form, return_existing = True)
563 # update fields
564 new_drug['is_fake_brand'] = False
565 #new_drug['atc'] = drug_atc
566 new_drug['external_code_type'] = u'FreeDiams::%s' % db_id
567 new_drug['external_code'] = drug_uid
568 new_drug['pk_data_source'] = data_src_pk
569 new_drug.save()
570
571 components = drug.getiterator('Composition')
572 for comp in components:
573
574 subst = comp.attrib['molecularName'].strip()
575
576 amount = regex.match(r'\d+[.,]{0,1}\d*', comp.attrib['strenght'].strip()) # sic, typo
577 if amount is None:
578 amount = 99999
579 else:
580 amount = amount.group()
581
582 unit = regex.sub(r'\d+[.,]{0,1}\d*', u'', comp.attrib['strenght'].strip()).strip() # sic, typo
583 if unit == u'':
584 unit = u'*?*'
585
586 inn = comp.attrib['inn'].strip()
587 if inn != u'':
588 create_consumable_substance(substance = inn, atc = None, amount = amount, unit = unit)
589 if subst == u'':
590 subst = inn
591
592 new_drug.add_component(substance = subst, atc = None, amount = amount, unit = unit)
593 #============================================================
595 """Support v8.2 CSV file interface only."""
596
597 version = u'Gelbe Liste/MMI v8.2 interface'
598 default_encoding = 'cp1250'
599 bdt_line_template = u'%03d6210#%s\r\n' # Medikament verordnet auf Kassenrezept
600 bdt_line_base_length = 8
601 #--------------------------------------------------------
603
604 cDrugDataSourceInterface.__init__(self)
605
606 _log.info(u'%s (native Windows)', cGelbeListeWindowsInterface.version)
607
608 self.path_to_binary = r'C:\Programme\MMI PHARMINDEX\glwin.exe'
609 self.args = r'-KEEPBACKGROUND -PRESCRIPTIONFILE %s -CLOSETOTRAY'
610
611 paths = gmTools.gmPaths()
612
613 self.default_csv_filename = os.path.join(paths.home_dir, '.gnumed', 'tmp', 'rezept.txt')
614 self.default_csv_filename_arg = os.path.join(paths.home_dir, '.gnumed', 'tmp')
615 self.interactions_filename = os.path.join(paths.home_dir, '.gnumed', 'tmp', 'gm2mmi.bdt')
616 self.data_date_filename = r'C:\Programme\MMI PHARMINDEX\datadate.txt'
617
618 self.__data_date = None
619 self.__online_update_date = None
620
621 # use adjusted config.dat
622 #--------------------------------------------------------
624
625 if self.__data_date is not None:
626 if not force_reload:
627 return {
628 'data': self.__data_date,
629 'online_update': self.__online_update_date
630 }
631
632 open(self.data_date_filename, 'wb').close()
633
634 cmd = u'%s -DATADATE' % self.path_to_binary
635 if not gmShellAPI.run_command_in_shell(command = cmd, blocking = True):
636 _log.error('problem querying the MMI drug database for version information')
637 self.__data_date = None
638 self.__online_update_date = None
639 return {
640 'data': u'?',
641 'online_update': u'?'
642 }
643
644 try:
645 version_file = open(self.data_date_filename, 'rU')
646 except StandardError:
647 _log.error('problem querying the MMI drug database for version information')
648 _log.exception('cannot open MMI drug database version file [%s]', self.data_date_filename)
649 self.__data_date = None
650 self.__online_update_date = None
651 return {
652 'data': u'?',
653 'online_update': u'?'
654 }
655
656 self.__data_date = version_file.readline()[:10]
657 self.__online_update_date = version_file.readline()[:10]
658 version_file.close()
659
660 return {
661 'data': self.__data_date,
662 'online_update': self.__online_update_date
663 }
664 #--------------------------------------------------------
666 versions = self.get_data_source_version()
667
668 return create_data_source (
669 long_name = u'Medikamentendatenbank "mmi PHARMINDEX" (Gelbe Liste)',
670 short_name = u'GL/MMI',
671 version = u'Daten: %s, Preise (Onlineupdate): %s' % (versions['data'], versions['online_update']),
672 source = u'Medizinische Medien Informations GmbH, Am Forsthaus Gravenbruch 7, 63263 Neu-Isenburg',
673 language = u'de'
674 )
675 #--------------------------------------------------------
677
678 # must make sure csv file exists
679 open(self.default_csv_filename, 'wb').close()
680
681 if cmd is None:
682 cmd = (u'%s %s' % (self.path_to_binary, self.args)) % self.default_csv_filename_arg
683
684 if not gmShellAPI.run_command_in_shell(command = cmd, blocking = blocking):
685 _log.error('problem switching to the MMI drug database')
686 # apparently on the first call MMI does not
687 # consistently return 0 on success
688 # return False
689
690 return True
691 #--------------------------------------------------------
693
694 # better to clean up interactions file
695 open(self.interactions_filename, 'wb').close()
696
697 if not self.switch_to_frontend(blocking = True):
698 return None
699
700 return cGelbeListeCSVFile(filename = self.default_csv_filename)
701 #--------------------------------------------------------
703
704 selected_drugs = self.select_drugs()
705 if selected_drugs is None:
706 return None
707
708 new_substances = []
709
710 for drug in selected_drugs:
711 atc = None # hopefully MMI eventually supports atc-per-substance in a drug...
712 if len(drug['wirkstoffe']) == 1:
713 atc = drug['atc']
714 for wirkstoff in drug['wirkstoffe']:
715 new_substances.append(create_consumable_substance(substance = wirkstoff, atc = atc, amount = amount, unit = unit))
716
717 selected_drugs.close()
718
719 return new_substances
720 #--------------------------------------------------------
722
723 selected_drugs = self.select_drugs()
724 if selected_drugs is None:
725 return None
726
727 data_src_pk = self.create_data_source_entry()
728
729 new_drugs = []
730 new_substances = []
731
732 for entry in selected_drugs:
733
734 _log.debug('importing drug: %s %s', entry['name'], entry['darreichungsform'])
735
736 if entry[u'hilfsmittel']:
737 _log.debug('skipping Hilfsmittel')
738 continue
739
740 if entry[u'erstattbares_medizinprodukt']:
741 _log.debug('skipping sonstiges Medizinprodukt')
742 continue
743
744 # create branded drug (or get it if it already exists)
745 drug = create_branded_drug(brand_name = entry['name'], preparation = entry['darreichungsform'])
746 if drug is None:
747 drug = get_drug_by_brand(brand_name = entry['name'], preparation = entry['darreichungsform'])
748 new_drugs.append(drug)
749
750 # update fields
751 drug['is_fake'] = False
752 drug['atc_code'] = entry['atc']
753 drug['external_code_type'] = u'DE-PZN'
754 drug['external_code'] = entry['pzn']
755 drug['fk_data_source'] = data_src_pk
756 drug.save()
757
758 # add components to brand
759 atc = None # hopefully MMI eventually supports atc-per-substance in a drug...
760 if len(entry['wirkstoffe']) == 1:
761 atc = entry['atc']
762 for wirkstoff in entry['wirkstoffe']:
763 drug.add_component(substance = wirkstoff, atc = atc)
764
765 # create as consumable substances, too
766 atc = None # hopefully MMI eventually supports atc-per-substance in a drug...
767 if len(entry['wirkstoffe']) == 1:
768 atc = entry['atc']
769 for wirkstoff in entry['wirkstoffe']:
770 new_substances.append(create_consumable_substance(substance = wirkstoff, atc = atc, amount = amount, unit = unit))
771
772 return new_drugs, new_substances
773 #--------------------------------------------------------
775 """For this to work the BDT interaction check must be configured in the MMI."""
776
777 if drug_ids_list is None:
778 if substances is None:
779 return
780 if len(substances) < 2:
781 return
782 drug_ids_list = [ (s.external_code_type, s.external_code) for s in substances ]
783 drug_ids_list = [ code_value for code_type, code_value in drug_ids_list if (code_value is not None) and (code_type == u'DE-PZN')]
784
785 else:
786 if len(drug_ids_list) < 2:
787 return
788
789 if drug_ids_list < 2:
790 return
791
792 bdt_file = codecs.open(filename = self.interactions_filename, mode = 'wb', encoding = cGelbeListeWindowsInterface.default_encoding)
793
794 for pzn in drug_ids_list:
795 pzn = pzn.strip()
796 lng = cGelbeListeWindowsInterface.bdt_line_base_length + len(pzn)
797 bdt_file.write(cGelbeListeWindowsInterface.bdt_line_template % (lng, pzn))
798
799 bdt_file.close()
800
801 self.switch_to_frontend(blocking = False)
802 #--------------------------------------------------------
804 self.switch_to_frontend(blocking = True)
805 #--------------------------------------------------------
807
808 cmd = None
809
810 if substance.external_code_type == u'DE-PZN':
811 cmd = u'%s -PZN %s' % (self.path_to_binary, substance.external_code)
812
813 if cmd is None:
814 name = gmTools.coalesce (
815 substance['brand'],
816 substance['substance']
817 )
818 cmd = u'%s -NAME %s' % (self.path_to_binary, name)
819
820 # better to clean up interactions file
821 open(self.interactions_filename, 'wb').close()
822
823 self.switch_to_frontend(cmd = cmd)
824 #============================================================
826
828 cGelbeListeWindowsInterface.__init__(self)
829
830 _log.info(u'%s (WINE extension)', cGelbeListeWindowsInterface.version)
831
832 # FIXME: if -CLOSETOTRAY is used GNUmed cannot detect the end of MMI
833 self.path_to_binary = r'wine "C:\Programme\MMI PHARMINDEX\glwin.exe"'
834 self.args = r'"-PRESCRIPTIONFILE %s -KEEPBACKGROUND"'
835
836 paths = gmTools.gmPaths()
837
838 self.default_csv_filename = os.path.join(paths.home_dir, '.wine', 'drive_c', 'windows', 'temp', 'mmi2gm.csv')
839 self.default_csv_filename_arg = r'c:\windows\temp\mmi2gm.csv'
840 self.interactions_filename = os.path.join(paths.home_dir, '.wine', 'drive_c', 'windows', 'temp', 'gm2mmi.bdt')
841 self.data_date_filename = os.path.join(paths.home_dir, '.wine', 'drive_c', 'Programme', 'MMI PHARMINDEX', 'datadate.txt')
842 #============================================================
844 """empirical CSV interface"""
845
848
850
851 try:
852 csv_file = open(filename, 'rb') # FIXME: encoding ?
853 except:
854 _log.exception('cannot access [%s]', filename)
855 csv_file = None
856
857 field_names = u'PZN Handelsname Form Abpackungsmenge Einheit Preis1 Hersteller Preis2 rezeptpflichtig Festbetrag Packungszahl Packungsgr\xf6\xdfe'.split()
858
859 if csv_file is None:
860 return False
861
862 csv_lines = csv.DictReader (
863 csv_file,
864 fieldnames = field_names,
865 delimiter = ';'
866 )
867
868 for line in csv_lines:
869 print "--------------------------------------------------------------------"[:31]
870 for key in field_names:
871 tmp = ('%s ' % key)[:30]
872 print '%s: %s' % (tmp, line[key])
873
874 csv_file.close()
875
876 # narr = u'%sx %s %s %s (\u2258 %s %s) von %s (%s)' % (
877 # line['Packungszahl'].strip(),
878 # line['Handelsname'].strip(),
879 # line['Form'].strip(),
880 # line[u'Packungsgr\xf6\xdfe'].strip(),
881 # line['Abpackungsmenge'].strip(),
882 # line['Einheit'].strip(),
883 # line['Hersteller'].strip(),
884 # line['PZN'].strip()
885 # )
886 #============================================================
887 drug_data_source_interfaces = {
888 'Deutschland: Gelbe Liste/MMI (Windows)': cGelbeListeWindowsInterface,
889 'Deutschland: Gelbe Liste/MMI (WINE)': cGelbeListeWineInterface,
890 'FreeDiams (France, US, Canada)': cFreeDiamsInterface
891 }
892 #============================================================
893 #============================================================
894 # substances in use across all patients
895 #------------------------------------------------------------
896 _SQL_get_consumable_substance = u"""
897 SELECT *, xmin
898 FROM ref.consumable_substance
899 WHERE %s
900 """
901
903
904 _cmd_fetch_payload = _SQL_get_consumable_substance % u"pk = %s"
905 _cmds_store_payload = [
906 u"""UPDATE ref.consumable_substance SET
907 description = %(description)s,
908 atc_code = gm.nullify_empty_string(%(atc_code)s),
909 amount = %(amount)s,
910 unit = gm.nullify_empty_string(%(unit)s)
911 WHERE
912 pk = %(pk)s
913 AND
914 xmin = %(xmin)s
915 AND
916 -- must not currently be used with a patient directly
917 NOT EXISTS (
918 SELECT 1
919 FROM clin.substance_intake
920 WHERE
921 fk_drug_component IS NULL
922 AND
923 fk_substance = %(pk)s
924 LIMIT 1
925 )
926 AND
927 -- must not currently be used with a patient indirectly, either
928 NOT EXISTS (
929 SELECT 1
930 FROM clin.substance_intake
931 WHERE
932 fk_drug_component IS NOT NULL
933 AND
934 fk_drug_component = (
935 SELECT r_ls2b.pk
936 FROM ref.lnk_substance2brand r_ls2b
937 WHERE fk_substance = %(pk)s
938 )
939 LIMIT 1
940 )
941 -- -- must not currently be used with a branded drug
942 -- -- (but this would make it rather hard fixing branded drugs which contain only this substance)
943 -- NOT EXISTS (
944 -- SELECT 1
945 -- FROM ref.lnk_substance2brand
946 -- WHERE fk_substance = %(pk)s
947 -- LIMIT 1
948 -- )
949 RETURNING
950 xmin
951 """
952 ]
953 _updatable_fields = [
954 u'description',
955 u'atc_code',
956 u'amount',
957 u'unit'
958 ]
959 #--------------------------------------------------------
961 success, data = super(self.__class__, self).save_payload(conn = conn)
962
963 if not success:
964 return (success, data)
965
966 if self._payload[self._idx['atc_code']] is not None:
967 atc = self._payload[self._idx['atc_code']].strip()
968 if atc != u'':
969 gmATC.propagate_atc (
970 substance = self._payload[self._idx['description']].strip(),
971 atc = atc
972 )
973
974 return (success, data)
975 #--------------------------------------------------------
976 # properties
977 #--------------------------------------------------------
979 cmd = u"""
980 SELECT
981 EXISTS (
982 SELECT 1
983 FROM clin.substance_intake
984 WHERE
985 fk_drug_component IS NULL
986 AND
987 fk_substance = %(pk)s
988 LIMIT 1
989 ) OR EXISTS (
990 SELECT 1
991 FROM clin.substance_intake
992 WHERE
993 fk_drug_component IS NOT NULL
994 AND
995 fk_drug_component = (
996 SELECT r_ls2b.pk
997 FROM ref.lnk_substance2brand r_ls2b
998 WHERE fk_substance = %(pk)s
999 )
1000 LIMIT 1
1001 )"""
1002 args = {'pk': self.pk_obj}
1003
1004 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False)
1005 return rows[0][0]
1006
1007 is_in_use_by_patients = property(_get_is_in_use_by_patients, lambda x:x)
1008 #--------------------------------------------------------
1010 cmd = u"""
1011 SELECT EXISTS (
1012 SELECT 1
1013 FROM ref.lnk_substance2brand
1014 WHERE fk_substance = %(pk)s
1015 LIMIT 1
1016 )"""
1017 args = {'pk': self.pk_obj}
1018
1019 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False)
1020 return rows[0][0]
1021
1022 is_drug_component = property(_get_is_drug_component, lambda x:x)
1023 #------------------------------------------------------------
1025 if order_by is None:
1026 order_by = u'true'
1027 else:
1028 order_by = u'true ORDER BY %s' % order_by
1029 cmd = _SQL_get_consumable_substance % order_by
1030 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = True)
1031 return [ cConsumableSubstance(row = {'data': r, 'idx': idx, 'pk_field': 'pk'}) for r in rows ]
1032 #------------------------------------------------------------
1034
1035 substance = substance
1036 if atc is not None:
1037 atc = atc.strip()
1038
1039 args = {
1040 'desc': substance.strip(),
1041 'amount': decimal.Decimal(amount),
1042 'unit': unit.strip(),
1043 'atc': atc
1044 }
1045 cmd = u"""
1046 SELECT pk FROM ref.consumable_substance
1047 WHERE
1048 lower(description) = lower(%(desc)s)
1049 AND
1050 amount = %(amount)s
1051 AND
1052 unit = %(unit)s
1053 """
1054 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}])
1055
1056 if len(rows) == 0:
1057 cmd = u"""
1058 INSERT INTO ref.consumable_substance (description, atc_code, amount, unit) VALUES (
1059 %(desc)s,
1060 gm.nullify_empty_string(%(atc)s),
1061 %(amount)s,
1062 gm.nullify_empty_string(%(unit)s)
1063 ) RETURNING pk"""
1064 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True, get_col_idx = False)
1065
1066 gmATC.propagate_atc(substance = substance, atc = atc)
1067
1068 return cConsumableSubstance(aPK_obj = rows[0]['pk'])
1069 #------------------------------------------------------------
1071 args = {'pk': substance}
1072 cmd = u"""
1073 DELETE FROM ref.consumable_substance
1074 WHERE
1075 pk = %(pk)s
1076 AND
1077
1078 -- must not currently be used with a patient
1079 NOT EXISTS (
1080 SELECT 1
1081 FROM clin.v_pat_substance_intake
1082 WHERE pk_substance = %(pk)s
1083 LIMIT 1
1084 )
1085 AND
1086
1087 -- must not currently be used with a branded drug
1088 NOT EXISTS (
1089 SELECT 1
1090 FROM ref.lnk_substance2brand
1091 WHERE fk_substance = %(pk)s
1092 LIMIT 1
1093 )"""
1094 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
1095 return True
1096 #============================================================
1098 """Represents a substance currently taken by a patient."""
1099
1100 _cmd_fetch_payload = u"SELECT * FROM clin.v_pat_substance_intake WHERE pk_substance_intake = %s"
1101 _cmds_store_payload = [
1102 u"""UPDATE clin.substance_intake SET
1103 clin_when = %(started)s,
1104 discontinued = %(discontinued)s,
1105 discontinue_reason = gm.nullify_empty_string(%(discontinue_reason)s),
1106 preparation = %(preparation)s,
1107 schedule = gm.nullify_empty_string(%(schedule)s),
1108 aim = gm.nullify_empty_string(%(aim)s),
1109 narrative = gm.nullify_empty_string(%(notes)s),
1110 intake_is_approved_of = %(intake_is_approved_of)s,
1111
1112 -- is_long_term = %(is_long_term)s,
1113 is_long_term = (
1114 case
1115 when (
1116 (%(is_long_term)s is False)
1117 and
1118 (%(duration)s is NULL)
1119 ) is True then null
1120 else %(is_long_term)s
1121 end
1122 )::boolean,
1123 duration = (
1124 case
1125 when %(is_long_term)s is True then null
1126 else %(duration)s
1127 end
1128 )::interval,
1129
1130 fk_drug_component = %(pk_drug_component)s,
1131 fk_substance = %(pk_substance)s,
1132 fk_episode = %(pk_episode)s
1133 WHERE
1134 pk = %(pk_substance_intake)s
1135 AND
1136 xmin = %(xmin_substance_intake)s
1137 RETURNING
1138 xmin as xmin_substance_intake
1139 """
1140 ]
1141 _updatable_fields = [
1142 u'started',
1143 u'discontinued',
1144 u'discontinue_reason',
1145 u'preparation',
1146 u'intake_is_approved_of',
1147 u'schedule',
1148 u'duration',
1149 u'aim',
1150 u'is_long_term',
1151 u'notes',
1152 u'pk_drug_component',
1153 u'pk_substance',
1154 u'pk_episode'
1155 ]
1156 #--------------------------------------------------------
1158
1159 if self._payload[self._idx['duration']] is None:
1160 duration = gmTools.bool2subst (
1161 self._payload[self._idx['is_long_term']],
1162 _('long-term'),
1163 _('short-term'),
1164 _('?short-term')
1165 )
1166 else:
1167 duration = gmDateTime.format_interval (
1168 self._payload[self._idx['duration']],
1169 accuracy_wanted = gmDateTime.acc_days
1170 )
1171
1172 line = u'%s%s (%s %s): %s %s%s %s (%s)' % (
1173 u' ' * left_margin,
1174 self._payload[self._idx['started']].strftime(date_format),
1175 gmTools.u_right_arrow,
1176 duration,
1177 self._payload[self._idx['substance']],
1178 self._payload[self._idx['amount']],
1179 self._payload[self._idx['unit']],
1180 self._payload[self._idx['preparation']],
1181 gmTools.bool2subst(self._payload[self._idx['is_currently_active']], _('ongoing'), _('inactive'), _('?ongoing'))
1182 )
1183
1184 return line
1185 #--------------------------------------------------------
1187 allg = gmAllergy.create_allergy (
1188 allergene = self._payload[self._idx['substance']],
1189 allg_type = allergy_type,
1190 episode_id = self._payload[self._idx['pk_episode']],
1191 encounter_id = encounter_id
1192 )
1193 allg['substance'] = gmTools.coalesce (
1194 self._payload[self._idx['brand']],
1195 self._payload[self._idx['substance']]
1196 )
1197 allg['reaction'] = self._payload[self._idx['discontinue_reason']]
1198 allg['atc_code'] = gmTools.coalesce(self._payload[self._idx['atc_substance']], self._payload[self._idx['atc_brand']])
1199 if self._payload[self._idx['external_code_brand']] is not None:
1200 allg['substance_code'] = u'%s::::%s' % (self._payload[self._idx['external_code_type_brand']], self._payload[self._idx['external_code_brand']])
1201 allg['allergene'] = self._payload[self._idx['substance']]
1202 comps = [ c['substance'] for c in self.containing_drug.components ]
1203 if len(comps) == 0:
1204 allg['generics'] = self._payload[self._idx['substance']]
1205 else:
1206 allg['generics'] = u'; '.join(comps)
1207
1208 allg.save()
1209 return allg
1210 #--------------------------------------------------------
1211 # properties
1212 #--------------------------------------------------------
1214
1215 try: self.__ddd
1216 except AttributeError: self.__ddd = None
1217
1218 if self.__ddd is not None:
1219 return self.__ddd
1220
1221 if self._payload[self._idx['atc_substance']] is not None:
1222 ddd = gmATC.atc2ddd(atc = self._payload[self._idx['atc_substance']])
1223 if len(ddd) != 0:
1224 self.__ddd = ddd[0]
1225 else:
1226 if self._payload[self._idx['atc_brand']] is not None:
1227 ddd = gmATC.atc2ddd(atc = self._payload[self._idx['atc_brand']])
1228 if len(ddd) != 0:
1229 self.__ddd = ddd[0]
1230
1231 return self.__ddd
1232
1233 ddd = property(_get_ddd, lambda x:x)
1234 #--------------------------------------------------------
1236 drug = self.containing_drug
1237
1238 if drug is None:
1239 return None
1240
1241 return drug.external_code
1242
1243 external_code = property(_get_external_code, lambda x:x)
1244 #--------------------------------------------------------
1246 drug = self.containing_drug
1247
1248 if drug is None:
1249 return None
1250
1251 return drug.external_code_type
1252
1253 external_code_type = property(_get_external_code_type, lambda x:x)
1254 #--------------------------------------------------------
1256 if self._payload[self._idx['pk_brand']] is None:
1257 return None
1258
1259 return cBrandedDrug(aPK_obj = self._payload[self._idx['pk_brand']])
1260
1261 containing_drug = property(_get_containing_drug, lambda x:x)
1262 #--------------------------------------------------------
1264 tests = [
1265 # lead, trail
1266 ' 1-1-1-1 ',
1267 # leading dose
1268 '1-1-1-1',
1269 '22-1-1-1',
1270 '1/3-1-1-1',
1271 '/4-1-1-1'
1272 ]
1273 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}$"
1274 for test in tests:
1275 print test.strip(), ":", regex.match(pattern, test.strip())
1276 #------------------------------------------------------------
1277 -def create_substance_intake(pk_substance=None, pk_component=None, preparation=None, encounter=None, episode=None):
1278
1279 args = {
1280 'enc': encounter,
1281 'epi': episode,
1282 'comp': pk_component,
1283 'subst': pk_substance,
1284 'prep': preparation
1285 }
1286
1287 if pk_component is None:
1288 cmd = u"""
1289 INSERT INTO clin.substance_intake (
1290 fk_encounter,
1291 fk_episode,
1292 intake_is_approved_of,
1293 fk_substance,
1294 preparation
1295 ) VALUES (
1296 %(enc)s,
1297 %(epi)s,
1298 False,
1299 %(subst)s,
1300 %(prep)s
1301 )
1302 RETURNING pk"""
1303 else:
1304 cmd = u"""
1305 INSERT INTO clin.substance_intake (
1306 fk_encounter,
1307 fk_episode,
1308 intake_is_approved_of,
1309 fk_drug_component
1310 ) VALUES (
1311 %(enc)s,
1312 %(epi)s,
1313 False,
1314 %(comp)s
1315 )
1316 RETURNING pk"""
1317
1318 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True)
1319 return cSubstanceIntakeEntry(aPK_obj = rows[0][0])
1320 #------------------------------------------------------------
1321 -def create_substance_intake_old(substance=None, drug_component=None, atc=None, encounter=None, episode=None, preparation=None, amount=None, unit=None):
1322
1323 args = {
1324 'enc': encounter,
1325 'epi': episode,
1326 'prep': preparation,
1327 'comp': drug_component,
1328 'subst': create_consumable_substance(substance = substance, atc = atc, amount = amount, unit = unit)['pk']
1329 }
1330
1331 if drug_component is None:
1332 cmd = u"""
1333 INSERT INTO clin.substance_intake (
1334 fk_encounter,
1335 fk_episode,
1336 intake_is_approved_of,
1337 fk_substance,
1338 preparation
1339 ) VALUES (
1340 %(enc)s,
1341 %(epi)s,
1342 False,
1343 %(subst)s,
1344 gm.nullify_empty_string(%(prep)s)
1345 )
1346 RETURNING pk"""
1347 else:
1348 cmd = u"""
1349 INSERT INTO clin.substance_intake (
1350 fk_encounter,
1351 fk_episode,
1352 intake_is_approved_of.
1353 fk_drug_component
1354 ) VALUES (
1355 %(enc)s,
1356 %(epi)s,
1357 False,
1358 %(comp)s
1359 )
1360 RETURNING pk"""
1361
1362 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True)
1363 return cSubstanceIntakeEntry(aPK_obj = rows[0][0])
1364 #------------------------------------------------------------
1366 cmd = u'delete from clin.substance_intake where pk = %(pk)s'
1367 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': {'pk': substance}}])
1368 #------------------------------------------------------------
1370
1371 tex = u'\n{\\small\n'
1372 tex += u'\\noindent %s\n' % _('Additional notes')
1373 tex += u'\n'
1374 tex += u'\\noindent \\begin{tabular}{|l|l|l|l|}\n'
1375 tex += u'\\hline\n'
1376 tex += u'%s & %s & %s & \\\\ \n' % (_('Substance'), _('Strength'), _('Brand'))
1377 tex += u'\\hline\n'
1378 tex += u'%s\n'
1379 tex += u'\n'
1380 tex += u'\\end{tabular}\n'
1381 tex += u'}\n'
1382
1383 current_meds = emr.get_current_substance_intake (
1384 include_inactive = False,
1385 include_unapproved = False,
1386 order_by = u'brand, substance'
1387 )
1388
1389 # create lines
1390 lines = []
1391 for med in current_meds:
1392
1393 lines.append(u'%s & %s%s & %s %s & {\\scriptsize %s} \\\\ \n \\hline \n' % (
1394 med['substance'],
1395 med['amount'],
1396 med['unit'],
1397 gmTools.coalesce(med['brand'], u''),
1398 med['preparation'],
1399 gmTools.coalesce(med['notes'], u'')
1400 ))
1401
1402 return tex % u' \n'.join(lines)
1403
1404 #------------------------------------------------------------
1406
1407 tex = u'\\noindent %s {\\tiny (%s)\\par}\n' % (_('Medication list'), _('ordered by brand'))
1408 tex += u'\n'
1409 tex += u'\\noindent \\begin{tabular}{|l|l|}\n'
1410 tex += u'\\hline\n'
1411 tex += u'%s & %s \\\\ \n' % (_('Drug'), _('Regimen'))
1412 tex += u'\\hline\n'
1413 tex += u'\n'
1414 tex += u'\\hline\n'
1415 tex += u'%s\n'
1416 tex += u'\n'
1417 tex += u'\\end{tabular}\n'
1418
1419 current_meds = emr.get_current_substance_intake (
1420 include_inactive = False,
1421 include_unapproved = False,
1422 order_by = u'brand, substance'
1423 )
1424
1425 # aggregate data
1426 line_data = {}
1427 for med in current_meds:
1428 identifier = gmTools.coalesce(med['brand'], med['substance'])
1429
1430 try:
1431 line_data[identifier]
1432 except KeyError:
1433 line_data[identifier] = {'brand': u'', 'preparation': u'', 'schedule': u'', 'aims': [], 'strengths': []}
1434
1435 line_data[identifier]['brand'] = identifier
1436 line_data[identifier]['strengths'].append(u'%s%s' % (med['amount'].strip(), med['unit'].strip()))
1437 line_data[identifier]['preparation'] = med['preparation']
1438 line_data[identifier]['schedule'] = gmTools.coalesce(med['schedule'], u'')
1439 if med['aim'] not in line_data[identifier]['aims']:
1440 line_data[identifier]['aims'].append(med['aim'])
1441
1442 # create lines
1443 already_seen = []
1444 lines = []
1445 line1_template = u'%s %s & %s \\\\'
1446 line2_template = u' & {\\scriptsize %s\\par} \\\\'
1447
1448 for med in current_meds:
1449 identifier = gmTools.coalesce(med['brand'], med['substance'])
1450
1451 if identifier in already_seen:
1452 continue
1453
1454 already_seen.append(identifier)
1455
1456 lines.append (line1_template % (
1457 line_data[identifier]['brand'],
1458 line_data[identifier]['preparation'],
1459 line_data[identifier]['schedule']
1460 ))
1461
1462 strengths = u'/'.join(line_data[identifier]['strengths'])
1463 if strengths == u'':
1464 template = u' & {\\scriptsize %s\\par} \\\\'
1465 for aim in line_data[identifier]['aims']:
1466 lines.append(template % aim)
1467 else:
1468 if len(line_data[identifier]['aims']) == 0:
1469 template = u'%s & \\\\'
1470 lines.append(template % strengths)
1471 else:
1472 template = u'%s & {\\scriptsize %s\\par} \\\\'
1473 lines.append(template % (strengths, line_data[identifier]['aims'][0]))
1474 template = u' & {\\scriptsize %s\\par} \\\\'
1475 for aim in line_data[identifier]['aims'][1:]:
1476 lines.append(template % aim)
1477
1478 lines.append(u'\\hline')
1479
1480 return tex % u' \n'.join(lines)
1481 #============================================================
1482 _SQL_get_drug_components = u'SELECT * FROM ref.v_drug_components WHERE %s'
1483
1485
1486 _cmd_fetch_payload = _SQL_get_drug_components % u'pk_component = %s'
1487 _cmds_store_payload = [
1488 u"""UPDATE ref.lnk_substance2brand SET
1489 fk_brand = %(pk_brand)s,
1490 fk_substance = %(pk_consumable_substance)s
1491 WHERE
1492 NOT EXISTS (
1493 SELECT 1
1494 FROM clin.substance_intake
1495 WHERE fk_drug_component = %(pk_component)s
1496 LIMIT 1
1497 )
1498 AND
1499 pk = %(pk_component)s
1500 AND
1501 xmin = %(xmin_lnk_substance2brand)s
1502 RETURNING
1503 xmin AS xmin_lnk_substance2brand
1504 """
1505 ]
1506 _updatable_fields = [
1507 u'pk_brand',
1508 u'pk_consumable_substance'
1509 ]
1510 #--------------------------------------------------------
1511 # properties
1512 #--------------------------------------------------------
1514 return cBrandedDrug(aPK_obj = self._payload[self._idx['pk_brand']])
1515
1516 containing_drug = property(_get_containing_drug, lambda x:x)
1517 #--------------------------------------------------------
1520
1521 is_in_use_by_patients = property(_get_is_in_use_by_patients, lambda x:x)
1522 #--------------------------------------------------------
1524 return cConsumableSubstance(aPK_obj = self._payload[self._idx['pk_consumable_substance']])
1525
1526 substance = property(_get_substance, lambda x:x)
1527 #------------------------------------------------------------
1529 cmd = _SQL_get_drug_components % u'true ORDER BY brand, substance'
1530 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = True)
1531 return [ cDrugComponent(row = {'data': r, 'idx': idx, 'pk_field': 'pk_component'}) for r in rows ]
1532 #============================================================
1534 """Represents a drug as marketed by a manufacturer."""
1535
1536 _cmd_fetch_payload = u"SELECT * FROM ref.v_branded_drugs WHERE pk_brand = %s"
1537 _cmds_store_payload = [
1538 u"""UPDATE ref.branded_drug SET
1539 description = %(brand)s,
1540 preparation = %(preparation)s,
1541 atc_code = gm.nullify_empty_string(%(atc)s),
1542 external_code = gm.nullify_empty_string(%(external_code)s),
1543 external_code_type = gm.nullify_empty_string(%(external_code_type)s),
1544 is_fake = %(is_fake_brand)s,
1545 fk_data_source = %(pk_data_source)s
1546 WHERE
1547 pk = %(pk_brand)s
1548 AND
1549 xmin = %(xmin_branded_drug)s
1550 RETURNING
1551 xmin AS xmin_branded_drug
1552 """
1553 ]
1554 _updatable_fields = [
1555 u'brand',
1556 u'preparation',
1557 u'atc',
1558 u'is_fake_brand',
1559 u'external_code',
1560 u'external_code_type',
1561 u'pk_data_source'
1562 ]
1563 #--------------------------------------------------------
1565 success, data = super(self.__class__, self).save_payload(conn = conn)
1566
1567 if not success:
1568 return (success, data)
1569
1570 if self._payload[self._idx['atc']] is not None:
1571 atc = self._payload[self._idx['atc']].strip()
1572 if atc != u'':
1573 gmATC.propagate_atc (
1574 substance = self._payload[self._idx['brand']].strip(),
1575 atc = atc
1576 )
1577
1578 return (success, data)
1579 #--------------------------------------------------------
1581
1582 if self._payload[self._idx['is_in_use']]:
1583 return False
1584
1585 args = {'brand': self._payload[self._idx['pk_brand']]}
1586
1587 queries = [{'cmd': u"DELETE FROM ref.lnk_substance2brand WHERE fk_brand = %(brand)s", 'args': args}]
1588 cmd = u'INSERT INTO ref.lnk_substance2brand (fk_brand, fk_substance) VALUES (%%(brand)s, %s)'
1589 for s in substances:
1590 queries.append({'cmd': cmd % s['pk'], 'args': args})
1591
1592 gmPG2.run_rw_queries(queries = queries)
1593 self.refetch_payload()
1594
1595 return True
1596 #--------------------------------------------------------
1597 - def add_component(self, substance=None, atc=None, amount=None, unit=None, pk_substance=None):
1598
1599 args = {
1600 'brand': self.pk_obj,
1601 'subst': consumable['description'],
1602 'atc': consumable['atc_code'],
1603 'pk_subst': pk_substance
1604 }
1605
1606 if pk_substance is None:
1607 consumable = create_consumable_substance(substance = substance, atc = atc, amount = amount, unit = unit)
1608 args['pk_subst'] = consumable['pk']
1609
1610 # already a component
1611 cmd = u"""
1612 SELECT pk_component
1613 FROM ref.v_drug_components
1614 WHERE
1615 pk_brand = %(brand)s
1616 AND
1617 ((
1618 (lower(substance) = lower(%(subst)s))
1619 OR
1620 (lower(atc_substance) = lower(%(atc)s))
1621 OR
1622 (pk_consumable_substance = %(pk_subst)s)
1623 ) IS TRUE)
1624 """
1625 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False)
1626
1627 if len(rows) > 0:
1628 return
1629
1630 # create it
1631 cmd = u"""
1632 INSERT INTO ref.lnk_substance2brand (fk_brand, fk_substance)
1633 VALUES (%(brand)s, %(pk_subst)s)
1634 """
1635 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
1636 #------------------------------------------------------------
1638 if len(self._payload[self._idx['components']]) == 1:
1639 _log.error('cannot remove the only component of a drug')
1640 return False
1641
1642 args = {'brand': self.pk_obj, 'comp': substance}
1643 cmd = u"""
1644 DELETE FROM ref.lnk_substance2brand
1645 WHERE
1646 fk_brand = %(brand)s
1647 AND
1648 fk_substance = %(comp)s
1649 AND
1650 NOT EXISTS (
1651 SELECT 1
1652 FROM clin.substance_intake
1653 WHERE fk_drug_component = %(comp)s
1654 LIMIT 1
1655 )
1656 """
1657 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
1658 return True
1659 #--------------------------------------------------------
1660 # properties
1661 #--------------------------------------------------------
1663 if self._payload[self._idx['external_code']] is None:
1664 return None
1665
1666 return self._payload[self._idx['external_code']]
1667
1668 external_code = property(_get_external_code, lambda x:x)
1669 #--------------------------------------------------------
1671
1672 # FIXME: maybe evaluate fk_data_source ?
1673 if self._payload[self._idx['external_code_type']] is None:
1674 return None
1675
1676 return self._payload[self._idx['external_code_type']]
1677
1678 external_code_type = property(_get_external_code_type, lambda x:x)
1679 #--------------------------------------------------------
1681 cmd = _SQL_get_drug_components % u'pk_brand = %(brand)s'
1682 args = {'brand': self._payload[self._idx['pk_brand']]}
1683 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True)
1684 return [ cDrugComponent(row = {'data': r, 'idx': idx, 'pk_field': 'pk_component'}) for r in rows ]
1685
1686 components = property(_get_components, lambda x:x)
1687 #--------------------------------------------------------
1689 if self._payload[self._idx['pk_substances']] is None:
1690 return []
1691 cmd = _SQL_get_consumable_substance % u'pk IN %(pks)s'
1692 args = {'pks': tuple(self._payload[self._idx['pk_substances']])}
1693 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True)
1694 return [ cConsumableSubstance(row = {'data': r, 'idx': idx, 'pk_field': 'pk'}) for r in rows ]
1695
1696 components_as_substances = property(_get_components_as_substances, lambda x:x)
1697 #--------------------------------------------------------
1699 cmd = u'SELECT EXISTS (SELECT 1 FROM clin.vaccine WHERE fk_brand = %(fk_brand)s)'
1700 args = {'fk_brand': self._payload[self._idx['pk_brand']]}
1701 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False)
1702 return rows[0][0]
1703
1704 is_vaccine = property(_get_is_vaccine, lambda x:x)
1705 #------------------------------------------------------------
1707 cmd = u'SELECT pk FROM ref.branded_drug ORDER BY description'
1708 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = False)
1709 return [ cBrandedDrug(aPK_obj = r['pk']) for r in rows ]
1710 #------------------------------------------------------------
1712 args = {'brand': brand_name, 'prep': preparation}
1713
1714 cmd = u'SELECT pk FROM ref.branded_drug WHERE lower(description) = lower(%(brand)s) AND lower(preparation) = lower(%(prep)s)'
1715 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False)
1716
1717 if len(rows) == 0:
1718 return None
1719
1720 return cBrandedDrug(aPK_obj = rows[0]['pk'])
1721 #------------------------------------------------------------
1723
1724 if preparation is None:
1725 preparation = _('units')
1726
1727 if preparation.strip() == u'':
1728 preparation = _('units')
1729
1730 if return_existing:
1731 drug = get_drug_by_brand(brand_name = brand_name, preparation = preparation)
1732 if drug is not None:
1733 return drug
1734
1735 cmd = u'INSERT INTO ref.branded_drug (description, preparation) VALUES (%(brand)s, %(prep)s) RETURNING pk'
1736 args = {'brand': brand_name, 'prep': preparation}
1737 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True, get_col_idx = False)
1738
1739 return cBrandedDrug(aPK_obj = rows[0]['pk'])
1740 #------------------------------------------------------------
1742 queries = []
1743 args = {'pk': brand}
1744
1745 # delete components
1746 cmd = u"""
1747 DELETE FROM ref.lnk_substance2brand
1748 WHERE
1749 fk_brand = %(pk)s
1750 AND
1751 NOT EXISTS (
1752 SELECT 1
1753 FROM clin.v_pat_substance_intake
1754 WHERE pk_brand = %(pk)s
1755 LIMIT 1
1756 )
1757 """
1758 queries.append({'cmd': cmd, 'args': args})
1759
1760 # delete drug
1761 cmd = u"""
1762 DELETE FROM ref.branded_drug
1763 WHERE
1764 pk = %(pk)s
1765 AND
1766 NOT EXISTS (
1767 SELECT 1
1768 FROM clin.v_pat_substance_intake
1769 WHERE pk_brand = %(pk)s
1770 LIMIT 1
1771 )
1772 """
1773 queries.append({'cmd': cmd, 'args': args})
1774
1775 gmPG2.run_rw_queries(queries = queries)
1776 #============================================================
1777 # main
1778 #------------------------------------------------------------
1779 if __name__ == "__main__":
1780
1781 if len(sys.argv) < 2:
1782 sys.exit()
1783
1784 if sys.argv[1] != 'test':
1785 sys.exit()
1786
1787 from Gnumed.pycommon import gmLog2
1788 from Gnumed.pycommon import gmI18N
1789 from Gnumed.business import gmPerson
1790
1791 gmI18N.activate_locale()
1792 # gmDateTime.init()
1793 #--------------------------------------------------------
1795 mmi = cGelbeListeWineInterface()
1796 print mmi
1797 print "interface definition:", mmi.version
1798 print "database versions: ", mmi.get_data_source_version()
1799 #--------------------------------------------------------
1801 mmi_file = cGelbeListeCSVFile(filename = sys.argv[2])
1802 for drug in mmi_file:
1803 print "-------------"
1804 print '"%s" (ATC: %s / PZN: %s)' % (drug['name'], drug['atc'], drug['pzn'])
1805 for stoff in drug['wirkstoffe']:
1806 print " Wirkstoff:", stoff
1807 raw_input()
1808 if mmi_file.has_unknown_fields is not None:
1809 print "has extra data under [%s]" % gmTools.default_csv_reader_rest_key
1810 for key in mmi_file.csv_fieldnames:
1811 print key, '->', drug[key]
1812 raw_input()
1813 mmi_file.close()
1814 #--------------------------------------------------------
1818 #--------------------------------------------------------
1820 mmi = cGelbeListeWineInterface()
1821 mmi_file = mmi.select_drugs()
1822 for drug in mmi_file:
1823 print "-------------"
1824 print '"%s" (ATC: %s / PZN: %s)' % (drug['name'], drug['atc'], drug['pzn'])
1825 for stoff in drug['wirkstoffe']:
1826 print " Wirkstoff:", stoff
1827 print drug
1828 mmi_file.close()
1829 #--------------------------------------------------------
1833 #--------------------------------------------------------
1835 mmi = cGelbeListeInterface()
1836 print mmi
1837 print "interface definition:", mmi.version
1838 # Metoprolol + Hct vs Citalopram
1839 diclofenac = '7587712'
1840 phenprocoumon = '4421744'
1841 mmi.check_drug_interactions(drug_ids_list = [diclofenac, phenprocoumon])
1842 #--------------------------------------------------------
1843 # FreeDiams
1844 #--------------------------------------------------------
1846 gmPerson.set_active_patient(patient = gmPerson.cIdentity(aPK_obj = 12))
1847 fd = cFreeDiamsInterface()
1848 fd.patient = gmPerson.gmCurrentPatient()
1849 fd.switch_to_frontend(blocking = True)
1850 fd.import_fd2gm_file()
1851 #--------------------------------------------------------
1853 gmPerson.set_active_patient(patient = gmPerson.cIdentity(aPK_obj = 12))
1854 fd = cFreeDiamsInterface()
1855 fd.patient = gmPerson.gmCurrentPatient()
1856 fd.check_drug_interactions(substances = fd.patient.get_emr().get_current_substance_intake(include_unapproved = True))
1857 #--------------------------------------------------------
1858 # generic
1859 #--------------------------------------------------------
1861 drug = create_substance_intake (
1862 substance = u'Whiskey',
1863 encounter = 1,
1864 episode = 1
1865 )
1866 print drug
1867 #--------------------------------------------------------
1872 #--------------------------------------------------------
1876 #--------------------------------------------------------
1877 # MMI/Gelbe Liste
1878 #test_MMI_interface()
1879 #test_MMI_file()
1880 #test_mmi_switch_to()
1881 #test_mmi_select_drugs()
1882 #test_mmi_import_substances()
1883 #test_mmi_import_drugs()
1884
1885 # FreeDiams
1886 #test_fd_switch_to()
1887 test_fd_show_interactions()
1888
1889 # generic
1890 #test_interaction_check()
1891 #test_create_substance_intake()
1892 #test_show_components()
1893 #test_get_consumable_substances()
1894 #============================================================
1895
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Mon Jan 10 03:56:17 2011 | http://epydoc.sourceforge.net |