Loading client/CHANGELOG +19 −0 Original line number Diff line number Diff line Loading @@ -6,6 +6,18 @@ # rel-1-7-patches ------------------------------------------------ 1.7.7 FIX: EMR/tree: exception on showing visual progress note FIX: lab/result EA: exception when no previous result available FIX: meds/substance EA: exception when no LOINC selected FIX: data/ATC: fix reference data import FIX: meds/dose EA: exception on saving FIX: meds/product EA: exception on creating new product FIX: dist: fix appdata.xml [thanks Andreas] NEW: configurable invoice ID template [thanks Marc] 1.7.6 FIX: application metadata files Loading Loading @@ -1997,6 +2009,13 @@ FIX: missing cast to ::text in dem.date_trunc_utc() calls # gnumed_v22 ------------------------------------------------ 22.7 IMPROVED: lab results plotting scripts for gnuplot IMPROVED: bills tables grants for invoice ID generation NEW: multi-results plotting script for gnuplot 22.6 FIX: properly include fixups in v21-v22 upgrade Loading client/appdata.xml +1 −1 Original line number Diff line number Diff line Loading @@ -35,7 +35,7 @@ <screenshot type="default"> <image>https://screenshots.debian.net/screenshots/000/002/117/large.png</image> <caption>The main window showing one of the ways to enter Progress Notes during a patient encounter</caption> </screenshot </screenshot> </screenshots> <url type="homepage">https://www.gnumed.de</url> <update_contact>gnumed-devel_AT_gnu.org</update_contact> Loading client/business/gmATC.py +68 −46 Original line number Diff line number Diff line Loading @@ -148,28 +148,35 @@ def atc_import(cfg_fname=None, conn=None): args = {'ver': version, 'desc': desc, 'url': url, 'name_long': name_long, 'name_short': name_short, 'lang': lang} # create data source record queries = [ { 'cmd': u"""delete from ref.data_source where name_short = %(name_short)s and version = %(ver)s""", 'args': args }, { 'cmd': u""" insert into ref.data_source (name_long, name_short, version, description, lang, source) values ( # find or create data source record cmd = u"select pk from ref.data_source where name_short = %(name_short)s and version = %(ver)s" rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}]) if len(rows) > 0: data_src_pk = rows[0][0] _log.debug('ATC data source record existed, pk is #%s, refreshing fields', data_src_pk) # exists - update args['pk'] = data_src_pk cmd = u"""UPDATE ref.data_source SET name_long = %(name_long)s, description = %(desc)s, lang = %(lang)s, source = %(url)s WHERE pk = %(pk)s """ rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}]) else: _log.debug('ATC data source record not found, creating') # create cmd = u"""insert into ref.data_source (name_long, name_short, version, description, lang, source) values ( %(name_long)s, %(name_short)s, %(ver)s, %(desc)s, %(lang)s, %(url)s )""", 'args': args }, { 'cmd': u"""select pk from ref.data_source where name_short = %(name_short)s and version = %(ver)s""", 'args': args } ] rows, idx = gmPG2.run_rw_queries(queries = queries, return_data = True) ) returning pk""" rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True) data_src_pk = rows[0][0] _log.debug('ATC data source record created, pk is #%s', data_src_pk) Loading Loading @@ -235,30 +242,45 @@ insert into ref.data_source (name_long, name_short, version, description, lang, _log.debug('ATC staging table loaded') # from staging table to real table curs = conn.cursor() args = {'src_pk': data_src_pk} queries = [] # transfer new records cmd = u""" insert into ref.atc ( fk_data_source, code, term, comment, unit, administration_route ) select %(src_pk)s, atc, name, nullif(comment, ''), nullif(unit, ''), nullif(adro, '') from FROM ref.atc_staging WHERE not exists ( select 1 FROM ref.atc WHERE fk_data_source = %(src_pk)s AND code = ref.atc_staging.atc ) """ gmPG2.run_rw_queries(link_obj = curs, queries = [{'cmd': cmd, 'args': args}]) queries.append({'cmd': cmd, 'args': args}) # update records so pre-existing ones are refreshed cmd = u""" UPDATE ref.atc SET code = r_as.atc, term = r_as.name, comment = nullif(r_as.comment, ''), administration_route = nullif(r_as.adro, '') FROM (SELECT atc, name, comment, adro FROM ref.atc_staging) AS r_as WHERE fk_data_source = %(src_pk)s """ queries.append({'cmd': cmd, 'args': args}) curs = conn.cursor() gmPG2.run_rw_queries(link_obj = curs, queries = queries) curs.close() conn.commit() _log.debug('transfer from ATC staging table to real ATC table done') Loading client/business/gmBilling.py +150 −8 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ __license__ = 'GPL v2 or later (details at http://www.gnu.org)' import sys import logging import zlib if __name__ == '__main__': Loading @@ -17,12 +18,14 @@ from Gnumed.pycommon import gmPG2 from Gnumed.pycommon import gmBusinessDBObject from Gnumed.pycommon import gmTools from Gnumed.pycommon import gmDateTime from Gnumed.business import gmDemographicRecord from Gnumed.business import gmDocuments _log = logging.getLogger('gm.bill') INVOICE_DOCUMENT_TYPE = u'invoice' #============================================================ # billables #------------------------------------------------------------ Loading Loading @@ -540,14 +543,114 @@ def get_bill_receiver(pk_patient=None): pass #------------------------------------------------------------ def get_invoice_id(pk_patient=None): return u'GM%s / %s' % ( pk_patient, gmDateTime.pydt_strftime ( gmDateTime.pydt_now_here(), '%Y-%m-%d / %H%M%S' ) ) def generate_invoice_id(template=None, pk_patient=None, person=None, date_format='%Y-%m-%d', time_format='%H%M%S'): """Generate invoice ID string, based on template. No template given -> generate old style fixed format invoice ID. Placeholders: %(pk_pat)s %(date)s %(time)s if included, $counter$ is not *needed* (but still possible) %(firstname)s %(lastname)s %(dob)s #counter# will be replaced by a counter, counting up from 1 until the invoice id is unique, max 999999 """ assert (None in [pk_patient, person]), u'either of <pk_patient> or <person> can be defined, but not both' if (template is None) or (template.strip() == u''): # force old style template = u'GM%(pk_pat)s / %(date)s / %(time)s' date_format = '%Y-%m-%d' time_format = '%H%M%S' template = template.strip() _log.debug('invoice ID template: %s', template) if pk_patient is None: if person is not None: pk_patient = person.ID now = gmDateTime.pydt_now_here() data = {} data['pk_pat'] = gmTools.coalesce(pk_patient, '?') data['date'] = gmDateTime.pydt_strftime(now, date_format).strip() data['time'] = gmDateTime.pydt_strftime(now, time_format).strip() if person is None: data['firstname'] = u'?' data['lastname'] = u'?' data['dob'] = u'?' else: data['firstname'] = person['firstnames'].replace(' ', gmTools.u_space_as_open_box).strip() data['lastname'] = person['lastnames'].replace(' ', gmTools.u_space_as_open_box).strip() data['dob'] = person.get_formatted_dob ( format = date_format, encoding = 'utf8', none_string = u'?', honor_estimation = False ).strip() candidate_invoice_id = template % data if u'#counter#' not in candidate_invoice_id: if u'%(time)s' in template: return candidate_invoice_id candidate_invoice_id = candidate_invoice_id + u' [##counter#]' _log.debug('invoice id candidate: %s', candidate_invoice_id) # get existing invoice IDs consistent with candidate search_term = u'^\s*%s\s*$' % gmPG2.sanitize_pg_regex(expression = candidate_invoice_id).replace(u'#counter#', '\d+') cmd = u'SELECT invoice_id FROM bill.bill WHERE invoice_id ~* %(search_term)s UNION ALL SELECT invoice_id FROM audit.log_bill WHERE invoice_id ~* %(search_term)s' args = {'search_term': search_term} rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}]) if len(rows) == 0: return candidate_invoice_id.replace(u'#counter#', u'1') existing_invoice_ids = [ r['invoice_id'].strip() for r in rows ] counter = None counter_max = 999999 for idx in range(1, counter_max): candidate = candidate_invoice_id.replace(u'#counter#', '%s' % idx) if candidate not in existing_invoice_ids: counter = idx break if counter is None: # exhausted the range, unlikely (1 million bills are possible # even w/o any other invoice ID data) but technically possible _log.debug('exhausted uniqueness space of [%s] invoice IDs per template', counter_max) counter = '>%s[%s]' % (counter_max, data['time']) return candidate_invoice_id.replace(u'#counter#', '%s' % counter) #------------------------------------------------------------ def lock_invoice_id(invoice_id): _log.debug('locking invoice ID: %s', invoice_id) crc32 = zlib.crc32(invoice_id) adler32 = zlib.adler32(invoice_id) _log.debug('crc32: %s', crc32) _log.debug('adler32: %s', adler32) cmd = u"""SELECT pg_try_advisory_lock(%s, %s)""" % (crc32, adler32) rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}]) if rows[0][0]: return True _log.warning('cannot lock invoice ID: [%s] (%s/%s)', invoice_id, crc32, adler32) return False #------------------------------------------------------------ def unlock_invoice_id(invoice_id): _log.debug('unlocking invoice ID: %s', invoice_id) crc32 = zlib.crc32(invoice_id) adler32 = zlib.adler32(invoice_id) _log.debug('crc32: %s', crc32) _log.debug('adler32: %s', adler32) cmd = u"""SELECT pg_advisory_unlock(%s, %s)""" % (crc32, adler32) rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}]) if rows[0][0]: return True _log.warning('cannot unlock invoice ID: [%s] (%s/%s)', invoice_id, crc32, adler32) return False #============================================================ # main Loading @@ -572,6 +675,7 @@ if __name__ == "__main__": first_bill = bills[0] print first_bill.default_address #-------------------------------------------------- def test_me(): print "--------------" me = cBillable(aPK_obj=1) Loading @@ -580,6 +684,44 @@ if __name__ == "__main__": print field, ':', me[field] print "updatable:", me.get_updatable_fields() #me['vat']=4; me.store_payload() #-------------------------------------------------- def test_generate_invoice_id(): from Gnumed.pycommon import gmI18N gmI18N.activate_locale() gmI18N.install_domain() import gmPerson for idx in range(1,15): print '' print 'classic:', generate_invoice_id(pk_patient = idx) pat = gmPerson.cPerson(idx) template = u'%(firstname).4s%(lastname).4s%(date)s' print 'new: template = "%s" => %s' % ( template, generate_invoice_id ( template = template, pk_patient = None, person = pat, date_format='%d%m%Y', time_format='%H%M%S' ) ) template = u'%(firstname).4s%(lastname).4s%(date)s-#counter#' print 'new: template = "%s" => %s' % ( template, generate_invoice_id ( template = template, pk_patient = None, person = pat, date_format='%d%m%Y', time_format='%H%M%S' ) ) #generate_invoice_id(template=None, pk_patient=None, person=None, date_format='%Y-%m-%d', time_format='%H%M%S') #-------------------------------------------------- #test_me() test_default_address() test_generate_invoice_id() client/business/gmMedication.py +9 −4 Original line number Diff line number Diff line Loading @@ -1739,25 +1739,30 @@ def get_drug_by_atc(atc=None, preparation=None, link_obj=None): #------------------------------------------------------------ def create_drug_product(product_name=None, preparation=None, return_existing=False, link_obj=None, doses=None): if preparation is None: preparation = _('units') if preparation.strip() == u'': preparation = _('units') if return_existing: drug = get_drug_by_name(product_name = product_name, preparation = preparation, link_obj = link_obj) if drug is not None: return drug if link_obj is None: link_obj = gmPG2.get_connection(readonly = False) conn_commit = link_obj.commit conn_close = link_obj.close else: conn_commit = lambda x:x conn_close = lambda x:x cmd = u'INSERT INTO ref.drug_product (description, preparation) VALUES (%(prod_name)s, %(prep)s) RETURNING pk' args = {'prod_name': product_name, 'prep': preparation} rows, idx = gmPG2.run_rw_queries(link_obj = link_obj, queries = [{'cmd': cmd, 'args': args}], return_data = True, get_col_idx = False) product = cDrugProduct(aPK_obj = rows[0]['pk'], link_obj = link_obj) if doses is not None: product.set_substance_doses_as_components(substance_doses = doses, link_obj = link_obj) conn_commit() conn_close() return product #------------------------------------------------------------ Loading Loading
client/CHANGELOG +19 −0 Original line number Diff line number Diff line Loading @@ -6,6 +6,18 @@ # rel-1-7-patches ------------------------------------------------ 1.7.7 FIX: EMR/tree: exception on showing visual progress note FIX: lab/result EA: exception when no previous result available FIX: meds/substance EA: exception when no LOINC selected FIX: data/ATC: fix reference data import FIX: meds/dose EA: exception on saving FIX: meds/product EA: exception on creating new product FIX: dist: fix appdata.xml [thanks Andreas] NEW: configurable invoice ID template [thanks Marc] 1.7.6 FIX: application metadata files Loading Loading @@ -1997,6 +2009,13 @@ FIX: missing cast to ::text in dem.date_trunc_utc() calls # gnumed_v22 ------------------------------------------------ 22.7 IMPROVED: lab results plotting scripts for gnuplot IMPROVED: bills tables grants for invoice ID generation NEW: multi-results plotting script for gnuplot 22.6 FIX: properly include fixups in v21-v22 upgrade Loading
client/appdata.xml +1 −1 Original line number Diff line number Diff line Loading @@ -35,7 +35,7 @@ <screenshot type="default"> <image>https://screenshots.debian.net/screenshots/000/002/117/large.png</image> <caption>The main window showing one of the ways to enter Progress Notes during a patient encounter</caption> </screenshot </screenshot> </screenshots> <url type="homepage">https://www.gnumed.de</url> <update_contact>gnumed-devel_AT_gnu.org</update_contact> Loading
client/business/gmATC.py +68 −46 Original line number Diff line number Diff line Loading @@ -148,28 +148,35 @@ def atc_import(cfg_fname=None, conn=None): args = {'ver': version, 'desc': desc, 'url': url, 'name_long': name_long, 'name_short': name_short, 'lang': lang} # create data source record queries = [ { 'cmd': u"""delete from ref.data_source where name_short = %(name_short)s and version = %(ver)s""", 'args': args }, { 'cmd': u""" insert into ref.data_source (name_long, name_short, version, description, lang, source) values ( # find or create data source record cmd = u"select pk from ref.data_source where name_short = %(name_short)s and version = %(ver)s" rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}]) if len(rows) > 0: data_src_pk = rows[0][0] _log.debug('ATC data source record existed, pk is #%s, refreshing fields', data_src_pk) # exists - update args['pk'] = data_src_pk cmd = u"""UPDATE ref.data_source SET name_long = %(name_long)s, description = %(desc)s, lang = %(lang)s, source = %(url)s WHERE pk = %(pk)s """ rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}]) else: _log.debug('ATC data source record not found, creating') # create cmd = u"""insert into ref.data_source (name_long, name_short, version, description, lang, source) values ( %(name_long)s, %(name_short)s, %(ver)s, %(desc)s, %(lang)s, %(url)s )""", 'args': args }, { 'cmd': u"""select pk from ref.data_source where name_short = %(name_short)s and version = %(ver)s""", 'args': args } ] rows, idx = gmPG2.run_rw_queries(queries = queries, return_data = True) ) returning pk""" rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True) data_src_pk = rows[0][0] _log.debug('ATC data source record created, pk is #%s', data_src_pk) Loading Loading @@ -235,30 +242,45 @@ insert into ref.data_source (name_long, name_short, version, description, lang, _log.debug('ATC staging table loaded') # from staging table to real table curs = conn.cursor() args = {'src_pk': data_src_pk} queries = [] # transfer new records cmd = u""" insert into ref.atc ( fk_data_source, code, term, comment, unit, administration_route ) select %(src_pk)s, atc, name, nullif(comment, ''), nullif(unit, ''), nullif(adro, '') from FROM ref.atc_staging WHERE not exists ( select 1 FROM ref.atc WHERE fk_data_source = %(src_pk)s AND code = ref.atc_staging.atc ) """ gmPG2.run_rw_queries(link_obj = curs, queries = [{'cmd': cmd, 'args': args}]) queries.append({'cmd': cmd, 'args': args}) # update records so pre-existing ones are refreshed cmd = u""" UPDATE ref.atc SET code = r_as.atc, term = r_as.name, comment = nullif(r_as.comment, ''), administration_route = nullif(r_as.adro, '') FROM (SELECT atc, name, comment, adro FROM ref.atc_staging) AS r_as WHERE fk_data_source = %(src_pk)s """ queries.append({'cmd': cmd, 'args': args}) curs = conn.cursor() gmPG2.run_rw_queries(link_obj = curs, queries = queries) curs.close() conn.commit() _log.debug('transfer from ATC staging table to real ATC table done') Loading
client/business/gmBilling.py +150 −8 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ __license__ = 'GPL v2 or later (details at http://www.gnu.org)' import sys import logging import zlib if __name__ == '__main__': Loading @@ -17,12 +18,14 @@ from Gnumed.pycommon import gmPG2 from Gnumed.pycommon import gmBusinessDBObject from Gnumed.pycommon import gmTools from Gnumed.pycommon import gmDateTime from Gnumed.business import gmDemographicRecord from Gnumed.business import gmDocuments _log = logging.getLogger('gm.bill') INVOICE_DOCUMENT_TYPE = u'invoice' #============================================================ # billables #------------------------------------------------------------ Loading Loading @@ -540,14 +543,114 @@ def get_bill_receiver(pk_patient=None): pass #------------------------------------------------------------ def get_invoice_id(pk_patient=None): return u'GM%s / %s' % ( pk_patient, gmDateTime.pydt_strftime ( gmDateTime.pydt_now_here(), '%Y-%m-%d / %H%M%S' ) ) def generate_invoice_id(template=None, pk_patient=None, person=None, date_format='%Y-%m-%d', time_format='%H%M%S'): """Generate invoice ID string, based on template. No template given -> generate old style fixed format invoice ID. Placeholders: %(pk_pat)s %(date)s %(time)s if included, $counter$ is not *needed* (but still possible) %(firstname)s %(lastname)s %(dob)s #counter# will be replaced by a counter, counting up from 1 until the invoice id is unique, max 999999 """ assert (None in [pk_patient, person]), u'either of <pk_patient> or <person> can be defined, but not both' if (template is None) or (template.strip() == u''): # force old style template = u'GM%(pk_pat)s / %(date)s / %(time)s' date_format = '%Y-%m-%d' time_format = '%H%M%S' template = template.strip() _log.debug('invoice ID template: %s', template) if pk_patient is None: if person is not None: pk_patient = person.ID now = gmDateTime.pydt_now_here() data = {} data['pk_pat'] = gmTools.coalesce(pk_patient, '?') data['date'] = gmDateTime.pydt_strftime(now, date_format).strip() data['time'] = gmDateTime.pydt_strftime(now, time_format).strip() if person is None: data['firstname'] = u'?' data['lastname'] = u'?' data['dob'] = u'?' else: data['firstname'] = person['firstnames'].replace(' ', gmTools.u_space_as_open_box).strip() data['lastname'] = person['lastnames'].replace(' ', gmTools.u_space_as_open_box).strip() data['dob'] = person.get_formatted_dob ( format = date_format, encoding = 'utf8', none_string = u'?', honor_estimation = False ).strip() candidate_invoice_id = template % data if u'#counter#' not in candidate_invoice_id: if u'%(time)s' in template: return candidate_invoice_id candidate_invoice_id = candidate_invoice_id + u' [##counter#]' _log.debug('invoice id candidate: %s', candidate_invoice_id) # get existing invoice IDs consistent with candidate search_term = u'^\s*%s\s*$' % gmPG2.sanitize_pg_regex(expression = candidate_invoice_id).replace(u'#counter#', '\d+') cmd = u'SELECT invoice_id FROM bill.bill WHERE invoice_id ~* %(search_term)s UNION ALL SELECT invoice_id FROM audit.log_bill WHERE invoice_id ~* %(search_term)s' args = {'search_term': search_term} rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}]) if len(rows) == 0: return candidate_invoice_id.replace(u'#counter#', u'1') existing_invoice_ids = [ r['invoice_id'].strip() for r in rows ] counter = None counter_max = 999999 for idx in range(1, counter_max): candidate = candidate_invoice_id.replace(u'#counter#', '%s' % idx) if candidate not in existing_invoice_ids: counter = idx break if counter is None: # exhausted the range, unlikely (1 million bills are possible # even w/o any other invoice ID data) but technically possible _log.debug('exhausted uniqueness space of [%s] invoice IDs per template', counter_max) counter = '>%s[%s]' % (counter_max, data['time']) return candidate_invoice_id.replace(u'#counter#', '%s' % counter) #------------------------------------------------------------ def lock_invoice_id(invoice_id): _log.debug('locking invoice ID: %s', invoice_id) crc32 = zlib.crc32(invoice_id) adler32 = zlib.adler32(invoice_id) _log.debug('crc32: %s', crc32) _log.debug('adler32: %s', adler32) cmd = u"""SELECT pg_try_advisory_lock(%s, %s)""" % (crc32, adler32) rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}]) if rows[0][0]: return True _log.warning('cannot lock invoice ID: [%s] (%s/%s)', invoice_id, crc32, adler32) return False #------------------------------------------------------------ def unlock_invoice_id(invoice_id): _log.debug('unlocking invoice ID: %s', invoice_id) crc32 = zlib.crc32(invoice_id) adler32 = zlib.adler32(invoice_id) _log.debug('crc32: %s', crc32) _log.debug('adler32: %s', adler32) cmd = u"""SELECT pg_advisory_unlock(%s, %s)""" % (crc32, adler32) rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}]) if rows[0][0]: return True _log.warning('cannot unlock invoice ID: [%s] (%s/%s)', invoice_id, crc32, adler32) return False #============================================================ # main Loading @@ -572,6 +675,7 @@ if __name__ == "__main__": first_bill = bills[0] print first_bill.default_address #-------------------------------------------------- def test_me(): print "--------------" me = cBillable(aPK_obj=1) Loading @@ -580,6 +684,44 @@ if __name__ == "__main__": print field, ':', me[field] print "updatable:", me.get_updatable_fields() #me['vat']=4; me.store_payload() #-------------------------------------------------- def test_generate_invoice_id(): from Gnumed.pycommon import gmI18N gmI18N.activate_locale() gmI18N.install_domain() import gmPerson for idx in range(1,15): print '' print 'classic:', generate_invoice_id(pk_patient = idx) pat = gmPerson.cPerson(idx) template = u'%(firstname).4s%(lastname).4s%(date)s' print 'new: template = "%s" => %s' % ( template, generate_invoice_id ( template = template, pk_patient = None, person = pat, date_format='%d%m%Y', time_format='%H%M%S' ) ) template = u'%(firstname).4s%(lastname).4s%(date)s-#counter#' print 'new: template = "%s" => %s' % ( template, generate_invoice_id ( template = template, pk_patient = None, person = pat, date_format='%d%m%Y', time_format='%H%M%S' ) ) #generate_invoice_id(template=None, pk_patient=None, person=None, date_format='%Y-%m-%d', time_format='%H%M%S') #-------------------------------------------------- #test_me() test_default_address() test_generate_invoice_id()
client/business/gmMedication.py +9 −4 Original line number Diff line number Diff line Loading @@ -1739,25 +1739,30 @@ def get_drug_by_atc(atc=None, preparation=None, link_obj=None): #------------------------------------------------------------ def create_drug_product(product_name=None, preparation=None, return_existing=False, link_obj=None, doses=None): if preparation is None: preparation = _('units') if preparation.strip() == u'': preparation = _('units') if return_existing: drug = get_drug_by_name(product_name = product_name, preparation = preparation, link_obj = link_obj) if drug is not None: return drug if link_obj is None: link_obj = gmPG2.get_connection(readonly = False) conn_commit = link_obj.commit conn_close = link_obj.close else: conn_commit = lambda x:x conn_close = lambda x:x cmd = u'INSERT INTO ref.drug_product (description, preparation) VALUES (%(prod_name)s, %(prep)s) RETURNING pk' args = {'prod_name': product_name, 'prep': preparation} rows, idx = gmPG2.run_rw_queries(link_obj = link_obj, queries = [{'cmd': cmd, 'args': args}], return_data = True, get_col_idx = False) product = cDrugProduct(aPK_obj = rows[0]['pk'], link_obj = link_obj) if doses is not None: product.set_substance_doses_as_components(substance_doses = doses, link_obj = link_obj) conn_commit() conn_close() return product #------------------------------------------------------------ Loading