Loading client/CHANGELOG +28 −0 Original line number Diff line number Diff line Loading @@ -6,6 +6,29 @@ # rel-1-7-patches ------------------------------------------------ 1.7.4 NEW: placeholders now nest with $2<>2$ $3<>3$ rather than $<<>>$ $<<<>>>$ NEW: placeholder $<patient_mcf>$ NEW: placeholder $<praxis_mcf>$ NEW: placehodler $<qrcode>$ NEW: placeholder $<if_debugging>$ NEW: LaTeX letter template example NEW: Begleitbrief mit Diagnosen (LaTeX) FIX: map None to '' in address parts placeholder FIX: export area export-to-media FIX: $<vaccination_history::%(l10n_indications)s::>$ field FIX: vaccine creation FIX: error in closing expired episodes FIX: date formatting in document tree IMPROVED: AppStream and desktop metadata IMPROVED: add "preset" option to $<free_text>$ placeholder IMPROVED: include MCF in export area metadata IMPROVED: Begleitbrief template 1.7.3 FIX: failure to merge patients under some conditions [thanks Marc] Loading Loading @@ -1960,6 +1983,11 @@ FIX: missing cast to ::text in dem.date_trunc_utc() calls # gnumed_v22 ------------------------------------------------ 22.4 FIX: LaTeX-Template for Begleitbrief FIX: 2nd/3rd level placeholders in LaTeX templates 22.2 FIX: staff/v_staff plausibility check [thanks Marc] Loading client/appdata.xml +4 −5 Original line number Diff line number Diff line Loading @@ -3,11 +3,11 @@ <!-- Thanks to Carsten Grohmann <mail@carstengrohmann.de> --> <!-- Thanks to Richard Hughes (https://people.freedesktop.org/~hughsient/appdata/) --> <component type="desktop"> <id>gnumed-client.desktop</id> <id>gnumed_client.desktop</id> <metadata_license>CC0-1.0</metadata_license> <project_license>GPL-2.0+ and GFDL-1.3</project_license> <name>GNUmed EMR</name> <summary>An Electronic Medical Record for community care.</summary> <summary>An Electronic Medical Record for community care</summary> <description> <p> GNUmed enables doctors to keep a medically sound record Loading @@ -32,11 +32,10 @@ <caption>http://wiki.gnumed.de</caption> </screenshot> <!--<screenshot type="default"> <image>http://www.hughsie.com/en_US/main.png</image> <image>https://screenshots.debian.net/screenshots/000/002/117/large.png</image> <caption>The main window showing the application in action</caption> </screenshot>--> </screenshots> <url type="homepage">http://www.gnumed.de</url> <updatecontact>gnumed-devel_at_gnu.org</updatecontact> <!--<project_group>GNOME</project_group>--> <update_contact>gnumed-devel_AT_gnu.org</update_contact> </component> client/business/gmAMTS_BMP.py 0 → 100644 +376 −0 Original line number Diff line number Diff line # -*- coding: utf-8 -*- """Manage German AMTS BMP data.""" #============================================================ __author__ = "K.Hilbert <Karsten.Hilbert@gmx.net>" __license__ = "GPL v2" # std lib import sys import os import logging import decimal import datetime as pyDT #from xml.etree import ElementTree as py_etree import typing # 3rd party #lxml_etree = None import lxml.etree as lxml_etree # GNUmed if __name__ == '__main__': sys.path.insert(0, '../../') from Gnumed.pycommon import gmLog2 from Gnumed.pycommon import gmI18N gmI18N.activate_locale() gmI18N.install_domain() from Gnumed.pycommon import gmTools from Gnumed.pycommon import gmDateTime from Gnumed.business import gmPerson AMTS_BMP_ENCODING = 'latin1' AMTS_BMP_DOB_FORMAT = '%Y%m%d' AMTS_BMP_DOB_FORMAT_NO_DAY = '%Y%m' AMTS_BMP_DOB_FORMAT_YEAR_ONLY = '%Y' AMTS2GMD_GENDER_MAP = { 'W': 'f', 'M': 'm', 'X': None } # the attribute # # <xs:attribute name="p" use="prohibited"> # <xs:annotation> # <xs:documentation>Name: Patchnummer # # Beschreibung: Patchnummer des zugrunde liegenden BMP (zusätzlich zum Attribut Version) # </xs:documentation> # </xs:annotation> # </xs:attribute> # # needs to be removed from the XSDs or else lxml will # choke on the <use="prohibited"> part AMTS_BMP_XSDs = { '2.5': 'bmp_V2.5.xsd', '2.4.1': 'bmp_V2.4.1.xsd', '2.3': 'bmp023.xsd' } _log = logging.getLogger('AMTS_BMP') #============================================================ class cDTO_AmtsBmp(gmPerson.cDTO_person): def __init__(self): super().__init__() self.dob_formats = [ AMTS_BMP_DOB_FORMAT, AMTS_BMP_DOB_FORMAT_NO_DAY, AMTS_BMP_DOB_FORMAT_YEAR_ONLY ] self.dob_tz = gmDateTime.pydt_now_here().tzinfo self.gender_map = AMTS2GMD_GENDER_MAP #-------------------------------------------------------- # internal helpers #-------------------------------------------------------- def _get_unambiguous_identity(self) -> typing.Union[None, gmPerson.cPerson]: egk_tag = 'eGK' egk_issuer = 'Krankenkasse' egk_id = None for ext_id in self.external_ids: if ext_id['name'] == egk_tag and ext_id['issuer'] == egk_issuer: egk_id = ext_id['value'] break if egk_id is None: _log.debug('cannot search for patient by eGK ID') return None candidates = gmPerson.get_persons_by_external_id ( external_id = egk_id, external_id_type = egk_tag, issuer = egk_issuer ) if len(candidates) != 1: _log.debug('cannot uniquely identify person by eGK ID [%s]', egk_id) return None return candidates[0] #============================================================ class cAmtsBmpFile: # take up to three filenames (or more, in non-strict mode) def __init__(self, filename) -> None: self.__filename:str = filename self.__xml_schema:lxml_etree.XMLSchema = None self.xml_doc = None self.bmp_version = None #-------------------------------------------------------- # version=..., strict=True/False def valid(self): for bmp_version in AMTS_BMP_XSDs: xsd_filename = os.path.join(gmTools.gmPaths().system_app_data_dir, 'resources', 'amts', AMTS_BMP_XSDs[bmp_version]) try: self.__xml_schema = lxml_etree.XMLSchema(file = xsd_filename) except lxml_etree.XMLSchemaParseError: _log.exception('cannot find [%s], trying local base dir', xsd_filename) # retry, maybe in dev tree xsd_filename = os.path.join(gmTools.gmPaths().local_base_dir, 'resources', 'amts', AMTS_BMP_XSDs[bmp_version]) self.__xml_schema = lxml_etree.XMLSchema(file = xsd_filename) with open(self.__filename, encoding = 'iso-8859-1') as bmp_file: try: self.xml_doc = lxml_etree.parse(bmp_file) except lxml_etree.XMLSyntaxError: _log.exception('[%s] does not parse as XML', self.__filename) break validated = self.__xml_schema.validate(self.xml_doc) if validated: self.bmp_version = bmp_version _log.debug('[%s] validates as AMTS BMP v%s', self.__filename, self.bmp_version) # check for second/third file ! return True _log.debug('[%s] does not validate against [%s]', self.__filename, xsd_filename) _log.debug('[%s] does not validate as AMTS BMP', self.__filename) return False #-------------------------------------------------------- def format(self, eol:str=None, verbose:bool=False) -> typing.Union[str, typing.List[str]]: assert (self.xml_doc is not None), 'self.xml_doc is None, forgot to call valid() before' lines = [] lines.append(_('AMTS BMP file: %s') % self.__filename) lines.append(_('Created: %s') % self.created_when) lines.append(_('Version: %s') % self.bmp_version) lines.append(_('UID: %s') % self.uid) lines.append(_('Creator:')) lines.append(' ' + str(self.originator)) lines.append(_('Patient:')) lines.append(' ' + str(self.patient_as_dto)) lines.append(_('Clinical data:')) lines.append(' ' + str(self.clinical_data)) if verbose: lines.append(_('Raw data:')) lines.extend(lxml_etree.tostring(self.xml_doc, encoding = 'unicode', pretty_print = True, method = 'xml').split('\n')) if eol is None: return lines return eol.join(lines) #-------------------------------------------------------- # properties #-------------------------------------------------------- def _patient_as_dto(self) -> cDTO_AmtsBmp: assert (self.xml_doc is not None), 'self.xml_doc is None, forgot to call valid() before' pat = self.xml_doc.find('P').attrib dto = cDTO_AmtsBmp() # lastname parts dto.lastnames = pat['f'] try: dto.lastnames = u'%s %s' % (pat['v'], dto.lastnames) except KeyError: pass try: dto.lastnames = u'%s %s' % (pat['z'], dto.lastnames) except KeyError: pass # firstnames dto.firstnames = pat['g'] # title try: dto.title = pat['t'] except KeyError: pass # gender try: dto.gender = pat['s'] except KeyError: pass # DOB dob_str = pat['b'] while dob_str.endswith('00'): dto.dob_is_estimated = True dob_str = dob_str[:-2] dto.dob = dob_str source = 'AMTS BMP v%s [uid=%s]' % (self.bmp_version, self.uid) # eGK try: dto.remember_external_id(name = 'eGK', value = pat['egk'], issuer = 'Krankenkasse', comment = source) except KeyError: pass dto.source = source return dto patient_as_dto = property(_patient_as_dto) #-------------------------------------------------------- def _get_clinical_data(self) -> dict: assert (self.xml_doc is not None), 'self.xml_doc is None, forgot to call valid() before' O_tag = self.xml_doc.find('O') if O_tag is None: return {} clinical_data = {'valid_when': self.created_when} O = O_tag.attrib try: clinical_data['allergies'] = O['ai'].split(',') except KeyError: pass try: clinical_data['pregnant'] = (O['p'] == '1') except KeyError: pass try: clinical_data['breast_feeding'] = (O['b'] == '1') except KeyError: pass try: clinical_data['weight'] = (decimal.Decimal(O['w']), 'kg') except KeyError: pass try: clinical_data['height'] = (int(O['h']), 'cm') except KeyError: pass try: clinical_data['creatinine'] = (decimal.Decimal(O['c']), 'mg/dl') except KeyError: pass try: clinical_data['comment'] = O['x'].strip() except KeyError: pass return clinical_data clinical_data = property(_get_clinical_data) #-------------------------------------------------------- def _get_created_when(self) -> pyDT.datetime: assert (self.xml_doc is not None), 'self.xml_doc is None, forgot to call valid() before' return pyDT.datetime.strptime ( self.xml_doc.find('A').attrib['t'], '%Y-%m-%dT%H:%M:%S' ) created_when = property(_get_created_when) #-------------------------------------------------------- def _get_uid(self) -> str: assert (self.xml_doc is not None), 'self.xml_doc is None, forgot to call valid() before' return self.xml_doc.getroot().attrib['U'] uid = property(_get_uid) #-------------------------------------------------------- #dto.remember_comm_channel(channel=None, url=None): #dto.remember_address(number=None, street=None, urb=None, region_code=None, zip=None, country_code=None, adr_type=None, subunit=None) def _get_originator(self) -> dict: assert (self.xml_doc is not None), 'self.xml_doc is None, forgot to call valid() before' A_tag = self.xml_doc.find('A') if A_tag is None: return {} originator = {} A = A_tag.attrib try: originator['id'] = (A['lanr'].strip(), 'lanr') except KeyError: pass try: originator['id'] = (A['idf'].strip(), 'idf') except KeyError: pass try: originator['id'] = (A['kik'].strip(), 'kik') except KeyError: pass try: originator['name'] = A['n'].strip() except KeyError: pass try: originator['street'] = A['s'].strip() except KeyError: pass try: originator['zip'] = A['z'].strip() except KeyError: pass try: originator['city'] = A['c'].strip() except KeyError: pass try: originator['phone'] = A['p'].strip() except KeyError: pass try: originator['email'] = A['e'].strip() except KeyError: pass return originator originator = property(_get_originator) #============================================================ #============================================================ #============================================================ #============================================================ # main/testing #============================================================ if __name__ == '__main__': if len(sys.argv) == 1: sys.exit() if sys.argv[1] != 'test': sys.exit() print('log file:', gmLog2._logfile_name) gmDateTime.init() #------------------------------------------------------- def test_validate_files(): for fname in sys.argv[2:]: print(fname) bmp = cAmtsBmpFile(fname) if not bmp.valid(): print('-> failed') continue print('-> conformant with version', bmp.bmp_version) #------------------------------------------------------- def test(): print(sys.argv[2]) print() bmp = cAmtsBmpFile(sys.argv[2]) if not bmp.valid(): print('failed') return print('validated as version', bmp.bmp_version) print(lxml_etree.tostring(bmp.xml_doc, encoding = 'unicode', pretty_print = True, method = 'xml')) dto = bmp.patient_as_dto print(dto) print(dto.external_ids) print(bmp.created_when) print('clinical data:', bmp.clinical_data) print('originator:', bmp.originator) # print('exists:', dto.exists) # cands = dto.get_candidate_identities(can_create=False) # print('candidates:') # for cand in cands: # print(cand) #------------------------------------------------------- test_validate_files() #test() client/business/gmBilling.py +4 −4 Original line number Diff line number Diff line Loading @@ -174,11 +174,11 @@ def delete_billable(pk_billable=None): #============================================================ # bill items #------------------------------------------------------------ _SQL_fetch_bill_item_fields = u"SELECT * FROM bill.v_bill_items WHERE %s" _SQL_get_bill_item_fields = u"SELECT * FROM bill.v_bill_items WHERE %s" class cBillItem(gmBusinessDBObject.cBusinessDBObject): _cmd_fetch_payload = _SQL_fetch_bill_item_fields % u"pk_bill_item = %s" _cmd_fetch_payload = _SQL_get_bill_item_fields % u"pk_bill_item = %s" _cmds_store_payload = [ u"""UPDATE bill.bill_item SET fk_provider = %(pk_provider)s, Loading Loading @@ -287,9 +287,9 @@ class cBillItem(gmBusinessDBObject.cBusinessDBObject): #------------------------------------------------------------ def get_bill_items(pk_patient=None, non_invoiced_only=False): if non_invoiced_only: cmd = _SQL_fetch_bill_item_fields % u"pk_patient = %(pat)s AND pk_bill IS NULL" cmd = _SQL_get_bill_item_fields % u"pk_patient = %(pat)s AND pk_bill IS NULL" else: cmd = _SQL_fetch_bill_item_fields % u"pk_patient = %(pat)s" cmd = _SQL_get_bill_item_fields % u"pk_patient = %(pat)s" args = {'pat': pk_patient} rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True) return [ cBillItem(row = {'data': r, 'idx': idx, 'pk_field': 'pk_bill_item'}) for r in rows ] Loading client/business/gmClinicalRecord.py +1 −1 Original line number Diff line number Diff line Loading @@ -1962,7 +1962,7 @@ WHERE args['encs'] = tuple(encounters) cmd = u'%s %s' % ( gmVaccination.sql_fetch_vaccination % u'\nAND '.join(where_parts), gmVaccination._SQL_get_vaccination_fields % u'\nAND '.join(where_parts), order_by ) rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True) Loading Loading
client/CHANGELOG +28 −0 Original line number Diff line number Diff line Loading @@ -6,6 +6,29 @@ # rel-1-7-patches ------------------------------------------------ 1.7.4 NEW: placeholders now nest with $2<>2$ $3<>3$ rather than $<<>>$ $<<<>>>$ NEW: placeholder $<patient_mcf>$ NEW: placeholder $<praxis_mcf>$ NEW: placehodler $<qrcode>$ NEW: placeholder $<if_debugging>$ NEW: LaTeX letter template example NEW: Begleitbrief mit Diagnosen (LaTeX) FIX: map None to '' in address parts placeholder FIX: export area export-to-media FIX: $<vaccination_history::%(l10n_indications)s::>$ field FIX: vaccine creation FIX: error in closing expired episodes FIX: date formatting in document tree IMPROVED: AppStream and desktop metadata IMPROVED: add "preset" option to $<free_text>$ placeholder IMPROVED: include MCF in export area metadata IMPROVED: Begleitbrief template 1.7.3 FIX: failure to merge patients under some conditions [thanks Marc] Loading Loading @@ -1960,6 +1983,11 @@ FIX: missing cast to ::text in dem.date_trunc_utc() calls # gnumed_v22 ------------------------------------------------ 22.4 FIX: LaTeX-Template for Begleitbrief FIX: 2nd/3rd level placeholders in LaTeX templates 22.2 FIX: staff/v_staff plausibility check [thanks Marc] Loading
client/appdata.xml +4 −5 Original line number Diff line number Diff line Loading @@ -3,11 +3,11 @@ <!-- Thanks to Carsten Grohmann <mail@carstengrohmann.de> --> <!-- Thanks to Richard Hughes (https://people.freedesktop.org/~hughsient/appdata/) --> <component type="desktop"> <id>gnumed-client.desktop</id> <id>gnumed_client.desktop</id> <metadata_license>CC0-1.0</metadata_license> <project_license>GPL-2.0+ and GFDL-1.3</project_license> <name>GNUmed EMR</name> <summary>An Electronic Medical Record for community care.</summary> <summary>An Electronic Medical Record for community care</summary> <description> <p> GNUmed enables doctors to keep a medically sound record Loading @@ -32,11 +32,10 @@ <caption>http://wiki.gnumed.de</caption> </screenshot> <!--<screenshot type="default"> <image>http://www.hughsie.com/en_US/main.png</image> <image>https://screenshots.debian.net/screenshots/000/002/117/large.png</image> <caption>The main window showing the application in action</caption> </screenshot>--> </screenshots> <url type="homepage">http://www.gnumed.de</url> <updatecontact>gnumed-devel_at_gnu.org</updatecontact> <!--<project_group>GNOME</project_group>--> <update_contact>gnumed-devel_AT_gnu.org</update_contact> </component>
client/business/gmAMTS_BMP.py 0 → 100644 +376 −0 Original line number Diff line number Diff line # -*- coding: utf-8 -*- """Manage German AMTS BMP data.""" #============================================================ __author__ = "K.Hilbert <Karsten.Hilbert@gmx.net>" __license__ = "GPL v2" # std lib import sys import os import logging import decimal import datetime as pyDT #from xml.etree import ElementTree as py_etree import typing # 3rd party #lxml_etree = None import lxml.etree as lxml_etree # GNUmed if __name__ == '__main__': sys.path.insert(0, '../../') from Gnumed.pycommon import gmLog2 from Gnumed.pycommon import gmI18N gmI18N.activate_locale() gmI18N.install_domain() from Gnumed.pycommon import gmTools from Gnumed.pycommon import gmDateTime from Gnumed.business import gmPerson AMTS_BMP_ENCODING = 'latin1' AMTS_BMP_DOB_FORMAT = '%Y%m%d' AMTS_BMP_DOB_FORMAT_NO_DAY = '%Y%m' AMTS_BMP_DOB_FORMAT_YEAR_ONLY = '%Y' AMTS2GMD_GENDER_MAP = { 'W': 'f', 'M': 'm', 'X': None } # the attribute # # <xs:attribute name="p" use="prohibited"> # <xs:annotation> # <xs:documentation>Name: Patchnummer # # Beschreibung: Patchnummer des zugrunde liegenden BMP (zusätzlich zum Attribut Version) # </xs:documentation> # </xs:annotation> # </xs:attribute> # # needs to be removed from the XSDs or else lxml will # choke on the <use="prohibited"> part AMTS_BMP_XSDs = { '2.5': 'bmp_V2.5.xsd', '2.4.1': 'bmp_V2.4.1.xsd', '2.3': 'bmp023.xsd' } _log = logging.getLogger('AMTS_BMP') #============================================================ class cDTO_AmtsBmp(gmPerson.cDTO_person): def __init__(self): super().__init__() self.dob_formats = [ AMTS_BMP_DOB_FORMAT, AMTS_BMP_DOB_FORMAT_NO_DAY, AMTS_BMP_DOB_FORMAT_YEAR_ONLY ] self.dob_tz = gmDateTime.pydt_now_here().tzinfo self.gender_map = AMTS2GMD_GENDER_MAP #-------------------------------------------------------- # internal helpers #-------------------------------------------------------- def _get_unambiguous_identity(self) -> typing.Union[None, gmPerson.cPerson]: egk_tag = 'eGK' egk_issuer = 'Krankenkasse' egk_id = None for ext_id in self.external_ids: if ext_id['name'] == egk_tag and ext_id['issuer'] == egk_issuer: egk_id = ext_id['value'] break if egk_id is None: _log.debug('cannot search for patient by eGK ID') return None candidates = gmPerson.get_persons_by_external_id ( external_id = egk_id, external_id_type = egk_tag, issuer = egk_issuer ) if len(candidates) != 1: _log.debug('cannot uniquely identify person by eGK ID [%s]', egk_id) return None return candidates[0] #============================================================ class cAmtsBmpFile: # take up to three filenames (or more, in non-strict mode) def __init__(self, filename) -> None: self.__filename:str = filename self.__xml_schema:lxml_etree.XMLSchema = None self.xml_doc = None self.bmp_version = None #-------------------------------------------------------- # version=..., strict=True/False def valid(self): for bmp_version in AMTS_BMP_XSDs: xsd_filename = os.path.join(gmTools.gmPaths().system_app_data_dir, 'resources', 'amts', AMTS_BMP_XSDs[bmp_version]) try: self.__xml_schema = lxml_etree.XMLSchema(file = xsd_filename) except lxml_etree.XMLSchemaParseError: _log.exception('cannot find [%s], trying local base dir', xsd_filename) # retry, maybe in dev tree xsd_filename = os.path.join(gmTools.gmPaths().local_base_dir, 'resources', 'amts', AMTS_BMP_XSDs[bmp_version]) self.__xml_schema = lxml_etree.XMLSchema(file = xsd_filename) with open(self.__filename, encoding = 'iso-8859-1') as bmp_file: try: self.xml_doc = lxml_etree.parse(bmp_file) except lxml_etree.XMLSyntaxError: _log.exception('[%s] does not parse as XML', self.__filename) break validated = self.__xml_schema.validate(self.xml_doc) if validated: self.bmp_version = bmp_version _log.debug('[%s] validates as AMTS BMP v%s', self.__filename, self.bmp_version) # check for second/third file ! return True _log.debug('[%s] does not validate against [%s]', self.__filename, xsd_filename) _log.debug('[%s] does not validate as AMTS BMP', self.__filename) return False #-------------------------------------------------------- def format(self, eol:str=None, verbose:bool=False) -> typing.Union[str, typing.List[str]]: assert (self.xml_doc is not None), 'self.xml_doc is None, forgot to call valid() before' lines = [] lines.append(_('AMTS BMP file: %s') % self.__filename) lines.append(_('Created: %s') % self.created_when) lines.append(_('Version: %s') % self.bmp_version) lines.append(_('UID: %s') % self.uid) lines.append(_('Creator:')) lines.append(' ' + str(self.originator)) lines.append(_('Patient:')) lines.append(' ' + str(self.patient_as_dto)) lines.append(_('Clinical data:')) lines.append(' ' + str(self.clinical_data)) if verbose: lines.append(_('Raw data:')) lines.extend(lxml_etree.tostring(self.xml_doc, encoding = 'unicode', pretty_print = True, method = 'xml').split('\n')) if eol is None: return lines return eol.join(lines) #-------------------------------------------------------- # properties #-------------------------------------------------------- def _patient_as_dto(self) -> cDTO_AmtsBmp: assert (self.xml_doc is not None), 'self.xml_doc is None, forgot to call valid() before' pat = self.xml_doc.find('P').attrib dto = cDTO_AmtsBmp() # lastname parts dto.lastnames = pat['f'] try: dto.lastnames = u'%s %s' % (pat['v'], dto.lastnames) except KeyError: pass try: dto.lastnames = u'%s %s' % (pat['z'], dto.lastnames) except KeyError: pass # firstnames dto.firstnames = pat['g'] # title try: dto.title = pat['t'] except KeyError: pass # gender try: dto.gender = pat['s'] except KeyError: pass # DOB dob_str = pat['b'] while dob_str.endswith('00'): dto.dob_is_estimated = True dob_str = dob_str[:-2] dto.dob = dob_str source = 'AMTS BMP v%s [uid=%s]' % (self.bmp_version, self.uid) # eGK try: dto.remember_external_id(name = 'eGK', value = pat['egk'], issuer = 'Krankenkasse', comment = source) except KeyError: pass dto.source = source return dto patient_as_dto = property(_patient_as_dto) #-------------------------------------------------------- def _get_clinical_data(self) -> dict: assert (self.xml_doc is not None), 'self.xml_doc is None, forgot to call valid() before' O_tag = self.xml_doc.find('O') if O_tag is None: return {} clinical_data = {'valid_when': self.created_when} O = O_tag.attrib try: clinical_data['allergies'] = O['ai'].split(',') except KeyError: pass try: clinical_data['pregnant'] = (O['p'] == '1') except KeyError: pass try: clinical_data['breast_feeding'] = (O['b'] == '1') except KeyError: pass try: clinical_data['weight'] = (decimal.Decimal(O['w']), 'kg') except KeyError: pass try: clinical_data['height'] = (int(O['h']), 'cm') except KeyError: pass try: clinical_data['creatinine'] = (decimal.Decimal(O['c']), 'mg/dl') except KeyError: pass try: clinical_data['comment'] = O['x'].strip() except KeyError: pass return clinical_data clinical_data = property(_get_clinical_data) #-------------------------------------------------------- def _get_created_when(self) -> pyDT.datetime: assert (self.xml_doc is not None), 'self.xml_doc is None, forgot to call valid() before' return pyDT.datetime.strptime ( self.xml_doc.find('A').attrib['t'], '%Y-%m-%dT%H:%M:%S' ) created_when = property(_get_created_when) #-------------------------------------------------------- def _get_uid(self) -> str: assert (self.xml_doc is not None), 'self.xml_doc is None, forgot to call valid() before' return self.xml_doc.getroot().attrib['U'] uid = property(_get_uid) #-------------------------------------------------------- #dto.remember_comm_channel(channel=None, url=None): #dto.remember_address(number=None, street=None, urb=None, region_code=None, zip=None, country_code=None, adr_type=None, subunit=None) def _get_originator(self) -> dict: assert (self.xml_doc is not None), 'self.xml_doc is None, forgot to call valid() before' A_tag = self.xml_doc.find('A') if A_tag is None: return {} originator = {} A = A_tag.attrib try: originator['id'] = (A['lanr'].strip(), 'lanr') except KeyError: pass try: originator['id'] = (A['idf'].strip(), 'idf') except KeyError: pass try: originator['id'] = (A['kik'].strip(), 'kik') except KeyError: pass try: originator['name'] = A['n'].strip() except KeyError: pass try: originator['street'] = A['s'].strip() except KeyError: pass try: originator['zip'] = A['z'].strip() except KeyError: pass try: originator['city'] = A['c'].strip() except KeyError: pass try: originator['phone'] = A['p'].strip() except KeyError: pass try: originator['email'] = A['e'].strip() except KeyError: pass return originator originator = property(_get_originator) #============================================================ #============================================================ #============================================================ #============================================================ # main/testing #============================================================ if __name__ == '__main__': if len(sys.argv) == 1: sys.exit() if sys.argv[1] != 'test': sys.exit() print('log file:', gmLog2._logfile_name) gmDateTime.init() #------------------------------------------------------- def test_validate_files(): for fname in sys.argv[2:]: print(fname) bmp = cAmtsBmpFile(fname) if not bmp.valid(): print('-> failed') continue print('-> conformant with version', bmp.bmp_version) #------------------------------------------------------- def test(): print(sys.argv[2]) print() bmp = cAmtsBmpFile(sys.argv[2]) if not bmp.valid(): print('failed') return print('validated as version', bmp.bmp_version) print(lxml_etree.tostring(bmp.xml_doc, encoding = 'unicode', pretty_print = True, method = 'xml')) dto = bmp.patient_as_dto print(dto) print(dto.external_ids) print(bmp.created_when) print('clinical data:', bmp.clinical_data) print('originator:', bmp.originator) # print('exists:', dto.exists) # cands = dto.get_candidate_identities(can_create=False) # print('candidates:') # for cand in cands: # print(cand) #------------------------------------------------------- test_validate_files() #test()
client/business/gmBilling.py +4 −4 Original line number Diff line number Diff line Loading @@ -174,11 +174,11 @@ def delete_billable(pk_billable=None): #============================================================ # bill items #------------------------------------------------------------ _SQL_fetch_bill_item_fields = u"SELECT * FROM bill.v_bill_items WHERE %s" _SQL_get_bill_item_fields = u"SELECT * FROM bill.v_bill_items WHERE %s" class cBillItem(gmBusinessDBObject.cBusinessDBObject): _cmd_fetch_payload = _SQL_fetch_bill_item_fields % u"pk_bill_item = %s" _cmd_fetch_payload = _SQL_get_bill_item_fields % u"pk_bill_item = %s" _cmds_store_payload = [ u"""UPDATE bill.bill_item SET fk_provider = %(pk_provider)s, Loading Loading @@ -287,9 +287,9 @@ class cBillItem(gmBusinessDBObject.cBusinessDBObject): #------------------------------------------------------------ def get_bill_items(pk_patient=None, non_invoiced_only=False): if non_invoiced_only: cmd = _SQL_fetch_bill_item_fields % u"pk_patient = %(pat)s AND pk_bill IS NULL" cmd = _SQL_get_bill_item_fields % u"pk_patient = %(pat)s AND pk_bill IS NULL" else: cmd = _SQL_fetch_bill_item_fields % u"pk_patient = %(pat)s" cmd = _SQL_get_bill_item_fields % u"pk_patient = %(pat)s" args = {'pat': pk_patient} rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True) return [ cBillItem(row = {'data': r, 'idx': idx, 'pk_field': 'pk_bill_item'}) for r in rows ] Loading
client/business/gmClinicalRecord.py +1 −1 Original line number Diff line number Diff line Loading @@ -1962,7 +1962,7 @@ WHERE args['encs'] = tuple(encounters) cmd = u'%s %s' % ( gmVaccination.sql_fetch_vaccination % u'\nAND '.join(where_parts), gmVaccination._SQL_get_vaccination_fields % u'\nAND '.join(where_parts), order_by ) rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True) Loading