Beispiel #1
0
	def test_generic_codes_prw():
		gmPG2.get_connection()
		app = wx.PyWidgetTester(size = (500, 40))
		pw = cGenericCodesPhraseWheel(app.frame, -1)
		#pw.set_context(context = u'zip', val = u'04318')
		app.frame.Show(True)
		app.MainLoop()
Beispiel #2
0
def create_vaccine(pk_drug_product=None, product_name=None, indications=None, is_live=None):

	assert (is_live is not None), '<is_live> must not be <None>'

	conn = gmPG2.get_connection(readonly = False)
	if pk_drug_product is None:
		#prep = _('vaccine')
		prep = 'vaccine'
		_log.debug('creating vaccine drug product [%s %s]', product_name, prep)
		vacc_prod = gmMedication.create_drug_product (
			product_name = product_name,
			preparation = prep,
			return_existing = True,
			# indications are ref.dose rows
			doses = indications,
			link_obj = conn
		)
		#conn.commit()
		vacc_prod['atc'] = 'J07'
		vacc_prod.save(conn = conn)
		pk_drug_product = vacc_prod['pk_drug_product']
	cmd = 'INSERT INTO ref.vaccine (fk_drug_product, is_live) values (%(pk_drug_product)s, %(live)s) RETURNING pk'
	queries = [{'cmd': cmd, 'args': {'pk_drug_product': pk_drug_product, 'live': is_live}}]
	rows, idx = gmPG2.run_rw_queries(link_obj = conn, queries = queries, get_col_idx = False, return_data = True, end_tx = True)
	conn.close()
	return cVaccine(aPK_obj = rows[0]['pk'])
Beispiel #3
0
	def set(self, workplace = None, cookie = None, option = None, value = None):
		"""Set (insert or update) option value in database.

		Any parameter that is None will be set to the database default.

		Note: you can't change the type of a parameter once it has been
		created in the backend. If you want to change the type you will
		have to delete the parameter and recreate it using the new type.
		"""
		# sanity checks
		if None in [option, value]:
			raise ValueError('invalid arguments (option=<%s>, value=<%s>)' % (option, value))

		rw_conn = gmPG2.get_connection(readonly=False)

		alias = self.__make_alias(workplace, 'CURRENT_USER', cookie, option)

		opt_value = value
		sql_type_cast = u''
		if isinstance(value, basestring):
			sql_type_cast = u'::text'
		elif isinstance(value, types.BooleanType):
			opt_value = int(opt_value)
		elif isinstance(value, (types.FloatType, types.IntType, types.LongType, decimal.Decimal, types.BooleanType)):
			sql_type_cast = u'::numeric'
		elif isinstance(value, types.ListType):
			# there can be different syntaxes for list types so don't try to cast them
			pass
		elif isinstance(value, types.BufferType):
			# can go directly into bytea
			pass
		else:
			try:
				opt_value = gmPG2.dbapi.Binary(pickle.dumps(value))
				sql_type_cast = '::bytea'
			except pickle.PicklingError:
				_log.error("cannot pickle option of type [%s] (key: %s, value: %s)", type(value), alias, str(value))
				raise
			except:
				_log.error("don't know how to store option of type [%s] (key: %s, value: %s)", type(value), alias, str(value))
				raise

		cmd = u'select cfg.set_option(%%(opt)s, %%(val)s%s, %%(wp)s, %%(cookie)s, NULL)' % sql_type_cast
		args = {
			'opt': option,
			'val': opt_value,
			'wp': workplace,
			'cookie': cookie
		}
		try:
			rows, idx = gmPG2.run_rw_queries(link_obj=rw_conn, queries=[{'cmd': cmd, 'args': args}], return_data=True)
			result = rows[0][0]
		except:
			_log.exception('cannot set option')
			result = False

		rw_conn.commit()		# will rollback if transaction failed
		rw_conn.close()

		return result
Beispiel #4
0
	def test():
		conn = gmPG2.get_connection()
		app = wx.PyWidgetTester(size = (600, 600))
		dlg = cOrganizationManagerDlg(app.frame, -1, size = (600, 600))
		dlg.SetSize((600, 600))
		dlg.ShowModal()
	#	app.SetWidget(dlg, -1)
		app.MainLoop()
Beispiel #5
0
	def add_items(self, items=None):
		"""Requires no pending changes within the bill itself."""
		# should check for item consistency first
		conn = gmPG2.get_connection(readonly = False)
		for item in items:
			item['pk_bill'] = self._payload[self._idx['pk_bill']]
			item.save(conn = conn)
		conn.commit()
		self.refetch_payload()		# make sure aggregates are re-filled from view
Beispiel #6
0
def get_hints_for_patient(pk_identity=None, include_suppressed_needing_invalidation=False):
	conn = gmPG2.get_connection()
	curs = conn.cursor()
	curs.callproc('clin.get_hints_for_patient', [pk_identity])
	rows = curs.fetchall()
	idx = gmPG2.get_col_indices(curs)
	curs.close()
	conn.rollback()
	if not include_suppressed_needing_invalidation:
		return [ cDynamicHint(row = {'data': r, 'idx': idx, 'pk_field': 'pk_auto_hint'}) for r in rows if r['rationale4suppression'] != 'magic_tag::please_invalidate_suppression' ]
	return [ cDynamicHint(row = {'data': r, 'idx': idx, 'pk_field': 'pk_auto_hint'}) for r in rows ]
Beispiel #7
0
def get_dbowner_connection(procedure=None, dbo_password=None, dbo_account='gm-dbo'):
	if procedure is None:
		procedure = _('<restricted procedure>')

	# 1) get password for gm-dbo
	if dbo_password is None:
		dbo_password = wx.GetPasswordFromUser (
			message = _("""
 [%s]

This is a restricted procedure. We need the
current password for the GNUmed database owner.

Please enter the current password for <%s>:""") % (
				procedure,
				dbo_account
			),
			caption = procedure
		)
		if dbo_password == '':
			return None

	gmLog2.add_word2hide(dbo_password)

	# 2) connect as gm-dbo
	login = gmPG2.get_default_login()
	dsn = gmPG2.make_psycopg2_dsn (
		database = login.database,
		host = login.host,
		port = login.port,
		user = dbo_account,
		password = dbo_password
	)
	try:
		conn = gmPG2.get_connection (
			dsn = dsn,
			readonly = False,
			verbose = True,
			pooled = False
		)
	except:
		_log.exception('cannot connect')
		gmGuiHelpers.gm_show_error (
			aMessage = _('Cannot connect as the GNUmed database owner <%s>.') % dbo_account,
			aTitle = procedure
		)
		gmPG2.log_database_access(action = 'failed to connect as database owner for [%s]' % procedure)
		return None

	return conn
Beispiel #8
0
def create_progress_note(soap=None, episode_id=None, encounter_id=None, link_obj=None):
	"""Create clinical narrative entries.

	<soap>
		must be a dict, the keys being SOAP categories (including U and
		None=admin) and the values being text (possibly multi-line)

	Existing but empty ('' or None) categories are skipped.
	"""
	if soap is None:
		return True

	if not gmSoapDefs.are_valid_soap_cats(soap.keys(), allow_upper = True):
		raise ValueError('invalid SOAP category in <soap> dictionary: %s', soap)

	if link_obj is None:
		link_obj = gmPG2.get_connection(readonly = False)
		conn_rollback = link_obj.rollback
		conn_commit = link_obj.commit
		conn_close = link_obj.close
	else:
		conn_rollback = lambda x:x
		conn_commit = lambda x:x
		conn_close = lambda x:x

	instances = {}
	for cat in soap:
		val = soap[cat]
		if val is None:
			continue
		if ''.join([ v.strip() for v in val ]) == '':
			continue
		instance = create_narrative_item (
			narrative = '\n'.join([ v.strip() for v in val ]),
			soap_cat = cat,
			episode_id = episode_id,
			encounter_id = encounter_id,
			link_obj = link_obj
		)
		if instance is None:
			continue
		instances[cat] = instance

	conn_commit()
	conn_close()
	return instances
Beispiel #9
0
def connect_to_database(max_attempts=3,
                        expected_version=None,
                        require_version=True):
    """Display the login dialog and try to log into the backend.

	- up to max_attempts times
	- returns True/False
	"""
    # force programmer to set a valid expected_version
    gmPG2.known_schema_hashes[expected_version]
    client_version = _cfg.get(option='client_version')
    global current_db_name
    current_db_name = 'gnumed_v%s' % expected_version
    attempt = 0
    dlg = cLoginDialog(None, -1, client_version=client_version)
    dlg.Centre(wx.BOTH)

    while attempt < max_attempts:
        _log.debug('login attempt %s of %s', (attempt + 1), max_attempts)
        connected = False
        dlg.ShowModal()
        login = dlg.panel.GetLoginInfo()
        if login is None:
            _log.info("user cancelled login dialog")
            break

        # obscure unconditionally, it could be a valid password
        gmLog2.add_word2hide(login.password)
        # try getting a connection to verify the parameters do work
        creds = gmConnectionPool.cPGCredentials()
        creds.database = login.database
        creds.host = login.host
        creds.port = login.port
        creds.user = login.user
        creds.password = login.password
        pool = gmConnectionPool.gmConnectionPool()
        pool.credentials = creds
        try:
            conn = gmPG2.get_raw_connection(verbose=True, readonly=True)
            _log.info('successfully connected: %s', conn)
            connected = True

        except gmPG2.cAuthenticationError as exc:
            _log.exception('login attempt failed')
            gmPG2.log_pg_exception_details(exc)
            attempt += 1
            if attempt < max_attempts:
                if ('host=127.0.0.1' in ('%s' % exc)) or ('host='
                                                          not in ('%s' % exc)):
                    msg = msg_auth_error_local
                else:
                    msg = msg_auth_error
                msg = msg % exc
                msg = regex.sub(
                    r'password=[^\s]+',
                    'password=%s' % gmTools.u_replacement_character, msg)
                gmGuiHelpers.gm_show_error(msg, _('Connecting to backend'))
            del exc
            continue

        except gmPG2.dbapi.OperationalError as exc:
            _log.exception('login attempt failed')
            gmPG2.log_pg_exception_details(exc)
            msg = msg_login_problem_generic % exc
            msg = regex.sub(r'password=[^\s]+',
                            'password=%s' % gmTools.u_replacement_character,
                            msg)
            gmGuiHelpers.gm_show_error(msg, _('Connecting to backend'))
            del exc
            continue

        conn.close()

        if not __database_is_acceptable_for_use(
                require_version=require_version,
                expected_version=expected_version,
                login=login):
            _log.info('database not suitable for use')
            connected = False
            break

        dlg.panel.save_state()
        gmExceptionHandlingWidgets.set_is_public_database(
            _cfg.get(option='is_public_db'))
        gmExceptionHandlingWidgets.set_helpdesk(_cfg.get(option='helpdesk'))
        _log.debug('establishing DB listener connection')
        conn = gmPG2.get_connection(
            verbose=True,
            connection_name='GNUmed-[DbListenerThread]',
            pooled=False)
        gmBackendListener.gmBackendListener(conn=conn)
        break

    dlg.DestroyLater()
    return connected
Beispiel #10
0
def __import_single_PID_hl7_file(filename, emr=None):
	"""Assumes single-PID/single-MSH HL7 file."""

	_log.debug('importing single-PID single-MSH HL7 data from [%s]', filename)

	# read the file
	MSH_file = io.open(filename, mode = 'rt', encoding = 'utf-8-sig', newline = '')
	HL7 = pyhl7.parse(MSH_file.read(1024 * 1024 * 5))	# 5 MB max
	MSH_file.close()

	# sanity checks
	if len(HL7.segments('MSH')) != 1:
		_log.error('more than one MSH segment')
		return False
	if len(HL7.segments('PID')) != 1:
		_log.error('more than one PID segment')
		return False

	# ensure lab is in database
	hl7_lab = HL7.extract_field('MSH', field_num = MSH_field__sending_lab)
	gm_lab = __find_or_create_lab(hl7_lab)

	# ensure test types exist
	conn = gmPG2.get_connection(readonly = False)
	__ensure_hl7_test_types_exist_in_gnumed(link_obj = conn, hl7_data = HL7, pk_test_org = gm_lab['pk_test_org'])

	# find patient
	if emr is None:
		#PID = HL7.segment('PID')
		pats = __PID2dto(HL7 = HL7)
		if len(pats) == 0:
			conn.rollback()
			return False
		if len(pats) > 1:
			conn.rollback()
			return False
		emr = pats[0].emr

	# import values: loop over segments
	when_list = {}
	current_result = None
	previous_segment = None
	had_errors = False
	msh_seen = False
	#pid_seen = False
	last_obr = None
	obr = {}
	for seg_idx in range(len(HL7)):
		seg = HL7[seg_idx]
		seg_type = seg[0][0]

		_log.debug('processing line #%s = segment of type <%s>', seg_idx, seg_type)

		if seg_type == 'MSH':
			msh_seen = True

		if seg_type == 'PID':
			if not msh_seen:
				conn.rollback()
				_log.error('PID segment before MSH segment')
				return False
			#pid_seen = True

		if seg_type in ['MSH', 'PID']:
			_log.info('segment already handled')
			previous_segment = seg_type
			obr = {}
			current_result = None
			continue

		if seg_type in ['ORC']:
			_log.info('currently ignoring %s segments', seg_type)
			previous_segment = seg_type
			obr = {}
			current_result = None
			continue

		if seg_type == 'OBR':
			previous_segment = seg_type
			last_obr = seg
			current_result = None
			obr['abbrev'] = ('%s' % seg[OBR_field__service_name][0]).strip()
			try:
				obr['name'] = ('%s' % seg[OBR_field__service_name][1]).strip()
			except IndexError:
				obr['name'] = obr['abbrev']
			for field_name in [OBR_field__ts_ended, OBR_field__ts_started, OBR_field__ts_specimen_received, OBR_field__ts_requested]:
				obr['clin_when'] = seg[field_name][0].strip()
				if obr['clin_when'] != '':
					break
			continue

		if seg_type == 'OBX':
			current_result = None
			# determine value
			val_alpha = seg[OBX_field__value][0].strip()
			is_num, val_num = gmTools.input2decimal(initial = val_alpha)
			if is_num:
				val_alpha = None
			else:
				val_num = None
				val_alpha = val_alpha.replace('\.br\\', '\n')
			# determine test type
			unit = seg[OBX_field__unit][0].strip()
			if unit == '':
				if is_num:
					unit = '1/1'
				else:
					unit = None
			test_type = __find_or_create_test_type (
				loinc = '%s' % seg[OBX_field__type][0][OBX_component__loinc-1],
				name = '%s' % seg[OBX_field__type][0][OBX_component__name-1],
				pk_lab = gm_lab['pk_test_org'],
				unit = unit,
				link_obj = conn
			)
			# eventually, episode should be read from lab_request
			epi = emr.add_episode (
				link_obj = conn,
				episode_name = 'administrative',
				is_open = False,
				allow_dupes = False
			)
			current_result = emr.add_test_result (
				link_obj = conn,
				episode = epi['pk_episode'],
				type = test_type['pk_test_type'],
				intended_reviewer = gmStaff.gmCurrentProvider()['pk_staff'],
				val_num = val_num,
				val_alpha = val_alpha,
				unit = unit
			)
			# handle range information et al
			ref_range = seg[OBX_field__range][0].strip()
			if ref_range != '':
				current_result.reference_range = ref_range
			flag = seg[OBX_field__abnormal_flag][0].strip()
			if flag != '':
				current_result['abnormality_indicator'] = flag
			current_result['status'] = seg[OBX_field__status][0].strip()
			current_result['val_grouping'] = seg[OBX_field__subid][0].strip()
			current_result['source_data'] = ''
			if last_obr is not None:
				current_result['source_data'] += str(last_obr)
				current_result['source_data'] += '\n'
			current_result['source_data'] += str(seg)
			clin_when = seg[OBX_field__timestamp][0].strip()
			if clin_when == '':
				_log.warning('no <Observation timestamp> in OBX, trying OBR timestamp')
				clin_when = obr['clin_when']
			try:
				clin_when = __hl7dt2pydt(clin_when)
			except ValueError:
				_log.exception('clin_when from OBX or OBR not useable, assuming <today>')
			if clin_when is not None:
				current_result['clin_when'] = clin_when
			current_result.save(conn = conn)
			when_list[gmDateTime.pydt_strftime(current_result['clin_when'], '%Y %b %d')] = 1
			previous_segment = seg_type
			continue

		if seg_type == 'NTE':
			note = seg[NET_field__note][0].strip().replace('\.br\\', '\n')
			if note == '':
				_log.debug('empty NTE segment')
				previous_segment = seg_type			# maybe not ? (HL7 providers happen to use empty NTE segments to "structure" raw HL7 |-)
				continue

			# if this is an NTE following an OBR (IOW an order-related
			# comment): make this a test result all of its own :-)
			if previous_segment == 'OBR':
				_log.debug('NTE following OBR: general note, using OBR timestamp [%s]', obr['clin_when'])
				current_result = None
				name = obr['name']
				if name == '':
					name = _('Comment')
				# FIXME: please suggest a LOINC for "order comment"
				test_type = __find_or_create_test_type(name = name, pk_lab = gm_lab['pk_test_org'], abbrev = obr['abbrev'], link_obj = conn)
				# eventually, episode should be read from lab_request
				epi = emr.add_episode (
					link_obj = conn,
					episode_name = 'administrative',
					is_open = False,
					allow_dupes = False
				)
				nte_result = emr.add_test_result (
					link_obj = conn,
					episode = epi['pk_episode'],
					type = test_type['pk_test_type'],
					intended_reviewer = gmStaff.gmCurrentProvider()['pk_staff'],
					val_alpha = note
				)
				#nte_result['val_grouping'] = seg[OBX_field__subid][0].strip()
				nte_result['source_data'] = str(seg)
				try:
					nte_result['clin_when'] = __hl7dt2pydt(obr['clin_when'])
				except ValueError:
					_log.exception('no .clin_when from OBR for NTE pseudo-OBX available')
				nte_result.save(conn = conn)
				continue

			if (previous_segment == 'OBX') and (current_result is not None):
				current_result['source_data'] += '\n'
				current_result['source_data'] += str(seg)
				current_result['note_test_org'] = gmTools.coalesce (
					current_result['note_test_org'],
					note,
					'%%s\n%s' % note
				)
				current_result.save(conn = conn)
				previous_segment = seg_type
				continue

			_log.error('unexpected NTE segment')
			had_errors = True
			break

		_log.error('unknown segment, aborting')
		_log.debug('line: %s', seg)
		had_errors = True
		break

	if had_errors:
		conn.rollback()
		return False

	conn.commit()

	# record import in chart
	try:
		no_results = len(HL7.segments('OBX'))
	except KeyError:
		no_results = '?'
	soap = _(
		'Imported HL7 file [%s]:\n'
		' lab "%s" (%s@%s), %s results (%s)'
	) % (
		filename,
		hl7_lab,
		gm_lab['unit'],
		gm_lab['organization'],
		no_results,
		' / '.join(list(when_list))
	)
	epi = emr.add_episode (
		episode_name = 'administrative',
		is_open = False,
		allow_dupes = False
	)
	emr.add_clin_narrative (
		note = soap,
		soap_cat = None,
		episode = epi
	)

	# keep copy of HL7 data in document archive
	folder = gmPerson.cPatient(emr.pk_patient).document_folder
	hl7_docs = folder.get_documents (
		doc_type = 'HL7 data',
		pk_episodes = [epi['pk_episode']],
		order_by = 'ORDER BY clin_when DESC'
	)
	if len(hl7_docs) > 0:
		# there should only ever be one unless the user manually creates more,
		# also, it should always be the latest since "ORDER BY clin_when DESC"
		hl7_doc = hl7_docs[0]
	else:
		hl7_doc = folder.add_document (
			document_type = 'HL7 data',
			encounter = emr.active_encounter['pk_encounter'],
			episode = epi['pk_episode']
		)
		hl7_doc['comment'] = _('list of imported HL7 data files')
		hl7_doc['pk_org_unit'] = gmPraxis.gmCurrentPraxisBranch()['pk_org_unit']
	hl7_doc['clin_when'] = gmDateTime.pydt_now_here()
	hl7_doc.save()
	part = hl7_doc.add_part(file = filename)
	part['obj_comment'] = _('Result dates: %s') % ' / '.join(list(when_list))
	part.save()
	hl7_doc.set_reviewed(technically_abnormal = False, clinically_relevant = False)

	return True
Beispiel #11
0
def connect_to_database(max_attempts=3,
                        expected_version=None,
                        require_version=True):
    """Display the login dialog and try to log into the backend.

	- up to max_attempts times
	- returns True/False
	"""
    # force programmer to set a valid expected_version
    expected_hash = gmPG2.known_schema_hashes[expected_version]
    client_version = _cfg.get(option='client_version')
    global current_db_name
    current_db_name = 'gnumed_v%s' % expected_version

    attempt = 0

    dlg = cLoginDialog(None, -1, client_version=client_version)
    dlg.Centre(wx.BOTH)

    while attempt < max_attempts:

        _log.debug('login attempt %s of %s', (attempt + 1), max_attempts)

        connected = False

        dlg.ShowModal()
        login = dlg.panel.GetLoginInfo()
        if login is None:
            _log.info("user cancelled login dialog")
            break

        gmLog2.add_word2hide(login.password)

        # try getting a connection to verify the parameters work
        creds = gmConnectionPool.cPGCredentials()
        creds.database = login.database
        creds.host = login.host
        creds.port = login.port
        creds.user = login.user
        creds.password = login.password
        pool = gmConnectionPool.gmConnectionPool()
        pool.credentials = creds
        try:
            conn = gmPG2.get_raw_connection(verbose=True, readonly=True)
            connected = True

        except gmPG2.cAuthenticationError as e:
            attempt += 1
            _log.error("login attempt failed: %s", e)
            if attempt < max_attempts:
                if ('host=127.0.0.1' in ('%s' % e)) or ('host='
                                                        not in ('%s' % e)):
                    msg = _(
                        'Unable to connect to database:\n\n'
                        '%s\n\n'
                        "Are you sure you have got a local database installed ?\n"
                        '\n'
                        "Please retry with proper credentials or cancel.\n"
                        '\n'
                        ' (for the public and any new GNUmed data-\n'
                        '  bases the default user name and password\n'
                        '  are {any-doc, any-doc})\n'
                        '\n'
                        'You may also need to check the PostgreSQL client\n'
                        'authentication configuration in pg_hba.conf. For\n'
                        'details see:\n'
                        '\n'
                        'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL')
                else:
                    msg = _(
                        "Unable to connect to database:\n\n"
                        "%s\n\n"
                        "Please retry with proper credentials or cancel.\n"
                        "\n"
                        "For the public and any new GNUmed databases the\n"
                        "default user name and password are {any-doc, any-doc}.\n"
                        "\n"
                        'You may also need to check the PostgreSQL client\n'
                        'authentication configuration in pg_hba.conf. For\n'
                        'details see:\n'
                        '\n'
                        'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL')
                msg = msg % e
                msg = regex.sub(
                    r'password=[^\s]+',
                    'password=%s' % gmTools.u_replacement_character, msg)
                gmGuiHelpers.gm_show_error(msg, _('Connecting to backend'))
            del e
            continue

        except gmPG2.dbapi.OperationalError as exc:
            _log.exception('login attempt failed')
            gmPG2.log_pg_exception_details(exc)
            msg = _(
                "Unable to connect to database:\n\n"
                "%s\n\n"
                "Please retry another backend / user / password combination !\n"
                "\n"
                " (for the public and any new GNUmed databases\n"
                "  the default user name and password are\n"
                "  {any-doc, any-doc})\n"
                "\n") % exc
            msg = regex.sub(r'password=[^\s]+',
                            'password=%s' % gmTools.u_replacement_character,
                            msg)
            gmGuiHelpers.gm_show_error(msg, _('Connecting to backend'))
            del exc
            continue

        conn.close()

        seems_bootstrapped = gmPG2.schema_exists(schema='gm')
        if not seems_bootstrapped:
            _log.error(
                'schema [gm] does not exist - database not bootstrapped ?')
            msg = _('The database you connected to does not seem\n'
                    'to have been boostrapped properly.\n'
                    '\n'
                    'Make sure you have run the GNUmed database\n'
                    'bootstrapper tool to create a new database.\n'
                    '\n'
                    'Further help can be found on the website at\n'
                    '\n'
                    '  http://wiki.gnumed.de\n'
                    '\n'
                    'or on the GNUmed mailing list.')
            gmGuiHelpers.gm_show_error(msg, _('Verifying database'))
            connected = False
            break

        compatible = gmPG2.database_schema_compatible(version=expected_version)
        if compatible or not require_version:
            dlg.panel.save_state()

        if not compatible:
            connected_db_version = gmPG2.get_schema_version()
            msg = msg_generic % (client_version, connected_db_version,
                                 expected_version,
                                 gmTools.coalesce(login.host, '<localhost>'),
                                 login.database, login.user)
            if require_version:
                gmGuiHelpers.gm_show_error(msg + msg_fail,
                                           _('Verifying database version'))
                connected = False
                continue
            gmGuiHelpers.gm_show_info(msg + msg_override,
                                      _('Verifying database version'))

        # FIXME: make configurable
        max_skew = 1  # minutes
        if _cfg.get(option='debug'):
            max_skew = 10
        if not gmPG2.sanity_check_time_skew(tolerance=(max_skew * 60)):
            if _cfg.get(option='debug'):
                gmGuiHelpers.gm_show_warning(msg_time_skew_warn % max_skew,
                                             _('Verifying database settings'))
            else:
                gmGuiHelpers.gm_show_error(msg_time_skew_fail % max_skew,
                                           _('Verifying database settings'))
                connected = False
                continue

        sanity_level, message = gmPG2.sanity_check_database_settings()
        if sanity_level != 0:
            gmGuiHelpers.gm_show_error((msg_insanity % message),
                                       _('Verifying database settings'))
            if sanity_level == 2:
                connected = False
                continue

        gmExceptionHandlingWidgets.set_is_public_database(
            _cfg.get(option='is_public_db'))
        gmExceptionHandlingWidgets.set_helpdesk(_cfg.get(option='helpdesk'))

        gmLog2.log_multiline(logging.DEBUG,
                             message='fingerprint',
                             text=gmPG2.get_db_fingerprint(eol='\n'))

        conn = gmPG2.get_connection(
            verbose=True,
            connection_name='GNUmed-[DbListenerThread]',
            pooled=False)
        listener = gmBackendListener.gmBackendListener(conn=conn)
        break

    dlg.DestroyLater()

    return connected
cmd = """
SELECT
	soap_cat,
	narrative,
	src_table,
	(SELECT rank FROM clin.soap_cat_ranks scr WHERE scr.soap_cat = vn4s.soap_cat) AS rank
FROM
	clin.v_narrative4search vn4s
WHERE
	pk_patient = %(pat)s
ORDER BY
	pk_encounter			-- sort of chronologically sorted
	, pk_health_issue
	, pk_episode
	, rank
	, src_table
"""

conn = gmPG2.get_connection(encoding='utf8')

rows, idx = gmPG2.run_ro_queries(link_obj=conn, queries=[{'cmd': cmd, 'args': {'pat': sys.argv[1]}}])

f = io.open('emr-%s-narrative-dump.txt' % sys.argv[1], mode = 'wt', encoding = 'utf8', errors = 'strict')

for row in rows:
	f.write('%s: %s (%s)\n'.encode('utf8') % (row['soap_cat'], row['narrative'], row['src_table']))

f.close()

#============================================================
Beispiel #13
0
    def set(self, workplace=None, cookie=None, option=None, value=None):
        """Set (insert or update) option value in database.

		Any parameter that is None will be set to the database default.

		Note: you can't change the type of a parameter once it has been
		created in the backend. If you want to change the type you will
		have to delete the parameter and recreate it using the new type.
		"""
        # sanity checks
        if None in [option, value]:
            raise ValueError('invalid arguments (option=<%s>, value=<%s>)' %
                             (option, value))

        rw_conn = gmPG2.get_connection(readonly=False)

        alias = self.__make_alias(workplace, 'CURRENT_USER', cookie, option)

        opt_value = value
        sql_type_cast = ''
        if isinstance(value, str):
            sql_type_cast = '::text'
        elif isinstance(value, bool):
            opt_value = int(opt_value)
        elif isinstance(value, (float, int, decimal.Decimal, bool)):
            sql_type_cast = '::numeric'
        elif isinstance(value, list):
            # there can be different syntaxes for list types so don't try to cast them
            pass
        elif isinstance(value, buffer):
            # can go directly into bytea
            pass
        else:
            try:
                opt_value = gmPG2.dbapi.Binary(pickle.dumps(value))
                sql_type_cast = '::bytea'
            except pickle.PicklingError:
                _log.error(
                    "cannot pickle option of type [%s] (key: %s, value: %s)",
                    type(value), alias, str(value))
                raise
            except:
                _log.error(
                    "don't know how to store option of type [%s] (key: %s, value: %s)",
                    type(value), alias, str(value))
                raise

        cmd = 'select cfg.set_option(%%(opt)s, %%(val)s%s, %%(wp)s, %%(cookie)s, NULL)' % sql_type_cast
        args = {
            'opt': option,
            'val': opt_value,
            'wp': workplace,
            'cookie': cookie
        }
        try:
            rows, idx = gmPG2.run_rw_queries(link_obj=rw_conn,
                                             queries=[{
                                                 'cmd': cmd,
                                                 'args': args
                                             }],
                                             return_data=True)
            result = rows[0][0]
        except:
            _log.exception('cannot set option')
            result = False

        rw_conn.commit()  # will rollback if transaction failed
        rw_conn.close()

        return result
	narrative,
	src_table,
	(SELECT rank FROM clin.soap_cat_ranks scr WHERE scr.soap_cat = vn4s.soap_cat) AS rank
FROM
	clin.v_narrative4search vn4s
WHERE
	pk_patient = %(pat)s
ORDER BY
	pk_encounter			-- sort of chronologically sorted
	, pk_health_issue
	, pk_episode
	, rank
	, src_table
"""

conn = gmPG2.get_connection(encoding='utf8')

rows, idx = gmPG2.run_ro_queries(link_obj=conn,
                                 queries=[{
                                     'cmd': cmd,
                                     'args': {
                                         'pat': sys.argv[1]
                                     }
                                 }])

f = io.open('emr-%s-narrative-dump.txt' % sys.argv[1],
            mode='wt',
            encoding='utf8',
            errors='strict')

for row in rows:
Beispiel #15
0
	def __init__(self):
		self._generate_queries = self._generate_queries_de
		# make a cursor
		self.conn = gmPG2.get_connection()
		self.curs = self.conn.cursor()
Beispiel #16
0
def connect_to_database(max_attempts=3, expected_version=None, require_version=True):
	"""Display the login dialog and try to log into the backend.

	- up to max_attempts times
	- returns True/False
	"""
	# force programmer to set a valid expected_version
	expected_hash = gmPG2.known_schema_hashes[expected_version]
	client_version = _cfg.get(option = 'client_version')
	global current_db_name
	current_db_name = 'gnumed_v%s' % expected_version

	attempt = 0

	dlg = cLoginDialog(None, -1, client_version = client_version)
	dlg.Centre(wx.BOTH)

	while attempt < max_attempts:

		_log.debug('login attempt %s of %s', (attempt+1), max_attempts)

		connected = False

		dlg.ShowModal()
		login = dlg.panel.GetLoginInfo()
		if login is None:
			_log.info("user cancelled login dialog")
			break

		gmLog2.add_word2hide(login.password)

		# try getting a connection to verify the DSN works
		dsn = gmPG2.make_psycopg2_dsn (
			database = login.database,
			host = login.host,
			port = login.port,
			user = login.user,
			password = login.password
		)
		try:
			conn = gmPG2.get_raw_connection(dsn = dsn, verbose = True, readonly = True)
			connected = True

		except gmPG2.cAuthenticationError as e:
			attempt += 1
			_log.error("login attempt failed: %s", e)
			if attempt < max_attempts:
				if ('host=127.0.0.1' in ('%s' % e)) or ('host=' not in ('%s' % e)):
					msg = _(
						'Unable to connect to database:\n\n'
						'%s\n\n'
						"Are you sure you have got a local database installed ?\n"
						'\n'
						"Please retry with proper credentials or cancel.\n"
						'\n'
						' (for the public and any new GNUmed data-\n'
						'  bases the default user name and password\n'
						'  are {any-doc, any-doc})\n'
						'\n'
						'You may also need to check the PostgreSQL client\n'
						'authentication configuration in pg_hba.conf. For\n'
						'details see:\n'
						'\n'
						'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL'
					)
				else:
					msg = _(
						"Unable to connect to database:\n\n"
						"%s\n\n"
						"Please retry with proper credentials or cancel.\n"
						"\n"
						"For the public and any new GNUmed databases the\n"
						"default user name and password are {any-doc, any-doc}.\n"
						"\n"
						'You may also need to check the PostgreSQL client\n'
						'authentication configuration in pg_hba.conf. For\n'
						'details see:\n'
						'\n'
						'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL'
					)
				msg = msg % e
				msg = regex.sub(r'password=[^\s]+', 'password=%s' % gmTools.u_replacement_character, msg)
				gmGuiHelpers.gm_show_error (
					msg,
					_('Connecting to backend')
				)
			del e
			continue

		except gmPG2.dbapi.OperationalError as exc:
			_log.exception('login attempt failed')
			gmPG2.log_pg_exception_details(exc)
			msg = _(
				"Unable to connect to database:\n\n"
				"%s\n\n"
				"Please retry another backend / user / password combination !\n"
				"\n"
				" (for the public and any new GNUmed databases\n"
				"  the default user name and password are\n"
				"  {any-doc, any-doc})\n"
				"\n"
			) % exc
			msg = regex.sub(r'password=[^\s]+', 'password=%s' % gmTools.u_replacement_character, msg)
			gmGuiHelpers.gm_show_error(msg, _('Connecting to backend'))
			del exc
			continue

		conn.close()

		# connect was successful
		gmPG2.set_default_login(login = login)
		gmPG2.set_default_client_encoding(encoding = dlg.panel.backend_profile.encoding)

		seems_bootstrapped = gmPG2.schema_exists(schema = 'gm')
		if not seems_bootstrapped:
			_log.error('schema [gm] does not exist - database not bootstrapped ?')
			msg = _(
				'The database you connected to does not seem\n'
				'to have been boostrapped properly.\n'
				'\n'
				'Make sure you have run the GNUmed database\n'
				'bootstrapper tool to create a new database.\n'
				'\n'
				'Further help can be found on the website at\n'
				'\n'
				'  http://wiki.gnumed.de\n'
				'\n'
				'or on the GNUmed mailing list.'
			)
			gmGuiHelpers.gm_show_error(msg, _('Verifying database'))
			connected = False
			break

		compatible = gmPG2.database_schema_compatible(version = expected_version)
		if compatible or not require_version:
			dlg.panel.save_state()

		if not compatible:
			connected_db_version = gmPG2.get_schema_version()
			msg = msg_generic % (
				client_version,
				connected_db_version,
				expected_version,
				gmTools.coalesce(login.host, '<localhost>'),
				login.database,
				login.user
			)
			if require_version:
				gmGuiHelpers.gm_show_error(msg + msg_fail, _('Verifying database version'))
				connected = False
				continue
			gmGuiHelpers.gm_show_info(msg + msg_override, _('Verifying database version'))

		# FIXME: make configurable
		max_skew = 1		# minutes
		if _cfg.get(option = 'debug'):
			max_skew = 10
		if not gmPG2.sanity_check_time_skew(tolerance = (max_skew * 60)):
			if _cfg.get(option = 'debug'):
				gmGuiHelpers.gm_show_warning(msg_time_skew_warn % max_skew, _('Verifying database settings'))
			else:
				gmGuiHelpers.gm_show_error(msg_time_skew_fail % max_skew, _('Verifying database settings'))
				connected = False
				continue

		sanity_level, message = gmPG2.sanity_check_database_settings()
		if sanity_level != 0:
			gmGuiHelpers.gm_show_error((msg_insanity % message), _('Verifying database settings'))
			if sanity_level == 2:
				connected = False
				continue

		gmExceptionHandlingWidgets.set_is_public_database(login.public_db)
		gmExceptionHandlingWidgets.set_helpdesk(login.helpdesk)

		conn = gmPG2.get_connection(verbose = True, connection_name = 'GNUmed-[DbListenerThread]', pooled = False)
		listener = gmBackendListener.gmBackendListener(conn = conn)
		break

	dlg.DestroyLater()

	return connected
Beispiel #17
0
	def test_atc_import():
		atc_import(cfg_fname = sys.argv[2], conn = gmPG2.get_connection(readonly = False))
Beispiel #18
0
	def save_payload(self, conn=None):
		"""Store updated values (if any) in database.

		Optionally accepts a pre-existing connection
		- returns a tuple (<True|False>, <data>)
		- True: success
		- False: an error occurred
			* data is (error, message)
			* for error meanings see gmPG2.run_rw_queries()
		"""
		if not self._is_modified:
			return (True, None)

		args = {}
		for field in self._idx.keys():
			args[field] = self._payload[self._idx[field]]
		self.modified_payload = args

		close_conn = self.__noop
		if conn is None:
			conn = gmPG2.get_connection(readonly=False)
			close_conn = conn.close

		queries = []
		for query in self.__class__._cmds_store_payload:
			queries.append({'cmd': query, 'args': args})
		rows, idx = gmPG2.run_rw_queries (
			link_obj = conn,
			queries = queries,
			return_data = True,
			get_col_idx = True
		)

		# this can happen if:
		# - someone else updated the row so XMIN does not match anymore
		# - the PK went away (rows were deleted from under us)
		# - another WHERE condition of the UPDATE did not produce any rows to update
		# - savepoints are used since subtransactions may relevantly change the xmin/xmax ...
		if len(rows) == 0:
			return (False, (u'cannot update row', _('[%s:%s]: row not updated (nothing returned), row in use ?') % (self.__class__.__name__, self.pk_obj)))

		# update cached values from should-be-first-and-only result
		# row of last query,
		# update all fields returned such that computed
		# columns see their new values
		row = rows[0]
		for key in idx:
			try:
				self._payload[self._idx[key]] = row[idx[key]]
			except KeyError:
				conn.rollback()
				close_conn()
				_log.error('[%s:%s]: cannot update instance, XMIN refetch key mismatch on [%s]' % (self.__class__.__name__, self.pk_obj, key))
				_log.error('payload keys: %s' % str(self._idx))
				_log.error('XMIN refetch keys: %s' % str(idx))
				_log.error(args)
				raise

		conn.commit()
		close_conn()

		self._is_modified = False
		# update to new "original" payload
		self.original_payload = {}
		for field in self._idx.keys():
			self.original_payload[field] = self._payload[self._idx[field]]

		return (True, None)
    pass


l = login()
l.database = 'gnumed_v9'
l.host = 'publicdb.gnumed.de'
l.port = '5432'
l.user = '******'
l.password = '******'

gmPG2.set_default_login(l)

gmPG2.set_default_client_timezone(timezone='Asia/Colombo')
gmPG2.set_default_client_timezone(timezone='Asia/Calcutta')

conn = gmPG2.get_connection()

cmd = """select * from dem.v_staff where db_user = CURRENT_USER"""

try:
    rows, idx = gmPG2.run_ro_queries(queries=[{'cmd': cmd}], verbose=True)
    for row in rows:
        _log.info(row)
    print rows
    print "==> success"
except Exception:
    _log.exception('query failed')
    gmLog2.log_stack_trace('query failed')
    print "==> failure"

# =======================================================================
Beispiel #20
0
 def __init__(self):
     self._generate_queries = self._generate_queries_de
     # make a cursor
     self.conn = gmPG2.get_connection()
     self.curs = self.conn.cursor()
Beispiel #21
0
	def __init__(self):
		self.ro_conn = gmPG2.get_connection()
Beispiel #22
0
		ddl.append('-- ----------------------------------------------')

	return ddl
#==================================================================
# main
#------------------------------------------------------------------
if __name__ == "__main__" :
	tmp = ''
	try:
		tmp = raw_input("audit trail parent table [%s]: " % audit_trail_parent_table)
	except KeyboardError:
		pass
	if tmp != '':
		audit_trail_parent_table = tmp

	conn = gmPG2.get_connection(readonly=False, pooled=False)
	curs = conn.cursor()

	schema = create_audit_ddl(curs)

	curs.close()
	conn.close()

	if schema is None:
		print "error creating schema"
		sys.exit(-1)

	file = io.open('audit-trail-schema.sql', mode = 'wb', encoding = 'utf8')
	for line in schema:
		file.write("%s;\n" % line)
	file.close()
Beispiel #23
0
    def save_payload(self, conn=None):
        """Store updated values (if any) in database.

		Optionally accepts a pre-existing connection
		- returns a tuple (<True|False>, <data>)
		- True: success
		- False: an error occurred
			* data is (error, message)
			* for error meanings see gmPG2.run_rw_queries()
		"""
        if not self._is_modified:
            return (True, None)

        args = {}
        for field in self._idx.keys():
            args[field] = self._payload[self._idx[field]]
        self.payload_most_recently_attempted_to_store = args

        close_conn = self.__noop
        if conn is None:
            conn = gmPG2.get_connection(readonly=False)
            close_conn = conn.close

        queries = []
        for query in self.__class__._cmds_store_payload:
            queries.append({'cmd': query, 'args': args})
        rows, idx = gmPG2.run_rw_queries(link_obj=conn,
                                         queries=queries,
                                         return_data=True,
                                         get_col_idx=True)

        # success ?
        if len(rows) == 0:
            # nothing updated - this can happen if:
            # - someone else updated the row so XMIN does not match anymore
            # - the PK went away (rows were deleted from under us)
            # - another WHERE condition of the UPDATE did not produce any rows to update
            # - savepoints are used since subtransactions may relevantly change the xmin/xmax ...
            return (False, (
                'cannot update row',
                _('[%s:%s]: row not updated (nothing returned), row in use ?')
                % (self.__class__.__name__, self.pk_obj)))

        # update cached values from should-be-first-and-only
        # result row of last query,
        # update all fields returned such that computed
        # columns see their new values (given they are
        # returned by the query)
        row = rows[0]
        for key in idx:
            try:
                self._payload[self._idx[key]] = row[idx[key]]
            except KeyError:
                conn.rollback()
                close_conn()
                _log.error(
                    '[%s:%s]: cannot update instance, XMIN refetch key mismatch on [%s]'
                    % (self.__class__.__name__, self.pk_obj, key))
                _log.error('payload keys: %s' % str(self._idx))
                _log.error('XMIN refetch keys: %s' % str(idx))
                _log.error(args)
                raise

        # only at conn.commit() time will data actually
        # get committed (and thusly trigger based notifications
        # be sent out), so reset the local modification flag
        # right before that
        self._is_modified = False
        conn.commit()
        close_conn()

        # update to new "original" payload
        self.payload_most_recently_fetched = {}
        for field in self._idx.keys():
            self.payload_most_recently_fetched[field] = self._payload[
                self._idx[field]]

        return (True, None)
Beispiel #24
0
def __import_single_PID_hl7_file(filename, emr=None):
	"""Assumes single-PID/single-MSH HL7 file."""

	_log.debug('importing single-PID single-MSH HL7 data from [%s]', filename)

	# read the file
	MSH_file = io.open(filename, mode = 'rt', encoding = 'utf8')
	HL7 = pyhl7.parse(MSH_file.read(1024 * 1024 * 5))	# 5 MB max
	MSH_file.close()

	# sanity checks
	if len(HL7.segments('MSH')) != 1:
		_log.error('more than one MSH segment')
		return False
	if len(HL7.segments('PID')) != 1:
		_log.error('more than one PID segment')
		return False

	# ensure lab is in database
	hl7_lab = HL7.extract_field('MSH', field_num = MSH_field__sending_lab)
	gm_lab = __find_or_create_lab(hl7_lab)

	# ensure test types exist
	conn = gmPG2.get_connection(readonly = False)
	__ensure_hl7_test_types_exist_in_gnumed(link_obj = conn, hl7_data = HL7, pk_test_org = gm_lab['pk_test_org'])

	# find patient
	if emr is None:
		#PID = HL7.segment('PID')
		pats = __PID2dto(HL7 = HL7)
		if len(pats) == 0:
			conn.rollback()
			return False
		if len(pats) > 1:
			conn.rollback()
			return False
		emr = pats[0].emr

	# import values: loop over segments
	when_list = {}
	current_result = None
	previous_segment = None
	had_errors = False
	msh_seen = False
	pid_seen = False
	last_obr = None
	obr = {}
	for seg_idx in range(len(HL7)):
		seg = HL7[seg_idx]
		seg_type = seg[0][0]

		_log.debug('processing line #%s = segment of type <%s>', seg_idx, seg_type)

		if seg_type == u'MSH':
			msh_seen = True

		if seg_type == u'PID':
			if not msh_seen:
				conn.rollback()
				_log.error('PID segment before MSH segment')
				return False
			pid_seen = True

		if seg_type in [u'MSH', u'PID']:
			_log.info('segment already handled')
			previous_segment = seg_type
			obr = {}
			current_result = None
			continue

		if seg_type in [u'ORC']:
			_log.info('currently ignoring %s segments', seg_type)
			previous_segment = seg_type
			obr = {}
			current_result = None
			continue

		if seg_type == u'OBR':
			previous_segment = seg_type
			last_obr = seg
			current_result = None
			obr['abbrev'] = (u'%s' % seg[OBR_field__service_name][0]).strip()
			try:
				obr['name'] = (u'%s' % seg[OBR_field__service_name][1]).strip()
			except IndexError:
				obr['name'] = obr['abbrev']
			for field_name in [OBR_field__ts_ended, OBR_field__ts_started, OBR_field__ts_specimen_received, OBR_field__ts_requested]:
				obr['clin_when'] = seg[field_name][0].strip()
				if obr['clin_when'] != u'':
					break
			continue

		if seg_type == u'OBX':
			current_result = None
			# determine value
			val_alpha = seg[OBX_field__value][0].strip()
			is_num, val_num = gmTools.input2decimal(initial = val_alpha)
			if is_num:
				val_alpha = None
			else:
				val_num = None
				val_alpha = val_alpha.replace('\.br\\', u'\n')
			# determine test type
			unit = seg[OBX_field__unit][0].strip()
			if unit == u'':
				if is_num:
					unit = u'1/1'
				else:
					unit = None
			test_type = __find_or_create_test_type (
				loinc = u'%s' % seg[OBX_field__type][0][OBX_component__loinc-1],
				name = u'%s' % seg[OBX_field__type][0][OBX_component__name-1],
				pk_lab = gm_lab['pk_test_org'],
				unit = unit
			)
			# eventually, episode should be read from lab_request
			epi = emr.add_episode (
				link_obj = conn,
				episode_name = u'administrative',
				is_open = False,
				allow_dupes = False
			)
			current_result = emr.add_test_result (
				link_obj = conn,
				episode = epi['pk_episode'],
				type = test_type['pk_test_type'],
				intended_reviewer = gmStaff.gmCurrentProvider()['pk_staff'],
				val_num = val_num,
				val_alpha = val_alpha,
				unit = unit
			)
			# handle range information et al
			ref_range = seg[OBX_field__range][0].strip()
			if ref_range != u'':
				current_result.reference_range = ref_range
			flag = seg[OBX_field__abnormal_flag][0].strip()
			if flag != u'':
				current_result['abnormality_indicator'] = flag
			current_result['status'] = seg[OBX_field__status][0].strip()
			current_result['val_grouping'] = seg[OBX_field__subid][0].strip()
			current_result['source_data'] = u''
			if last_obr is not None:
				current_result['source_data'] += unicode(last_obr)
				current_result['source_data'] += u'\n'
			current_result['source_data'] += unicode(seg)
			clin_when = seg[OBX_field__timestamp][0].strip()
			if clin_when == u'':
				_log.warning('no <Observation timestamp> in OBX, trying OBR timestamp')
				clin_when = obr['clin_when']
			try:
				clin_when = __hl7dt2pydt(clin_when)
			except ValueError:
				_log.exception('clin_when from OBX or OBR not useable, assuming <today>')
			if clin_when is not None:
				current_result['clin_when'] = clin_when
			current_result.save(conn = conn)
			when_list[gmDateTime.pydt_strftime(current_result['clin_when'], '%Y %b %d')] = 1
			previous_segment = seg_type
			continue

		if seg_type == u'NTE':
			note = seg[NET_field__note][0].strip().replace('\.br\\', u'\n')
			if note == u'':
				_log.debug('empty NTE segment')
				previous_segment = seg_type			# maybe not ? (HL7 providers happen to use empty NTE segments to "structure" raw HL7 |-)
				continue

			# if this is an NTE following an OBR (IOW an order-related
			# comment): make this a test result all of its own :-)
			if previous_segment == u'OBR':
				_log.debug('NTE following OBR: general note, using OBR timestamp [%s]', obr['clin_when'])
				current_result = None
				name = obr['name']
				if name == u'':
					name = _('Comment')
				# FIXME: please suggest a LOINC for "order comment"
				test_type = __find_or_create_test_type(name = name, pk_lab = gm_lab['pk_test_org'], abbrev = obr['abbrev'])
				# eventually, episode should be read from lab_request
				epi = emr.add_episode (
					link_obj = conn,
					episode_name = u'administrative',
					is_open = False,
					allow_dupes = False
				)
				nte_result = emr.add_test_result (
					link_obj = conn,
					episode = epi['pk_episode'],
					type = test_type['pk_test_type'],
					intended_reviewer = gmStaff.gmCurrentProvider()['pk_staff'],
					val_alpha = note
				)
				#nte_result['val_grouping'] = seg[OBX_field__subid][0].strip()
				nte_result['source_data'] = unicode(seg)
				try:
					nte_result['clin_when'] = __hl7dt2pydt(obr['clin_when'])
				except ValueError:
					_log.exception('no .clin_when from OBR for NTE pseudo-OBX available')
				nte_result.save(conn = conn)
				continue

			if (previous_segment == u'OBX') and (current_result is not None):
				current_result['source_data'] += u'\n'
				current_result['source_data'] += unicode(seg)
				current_result['note_test_org'] = gmTools.coalesce (
					current_result['note_test_org'],
					note,
					u'%%s\n%s' % note
				)
				current_result.save(conn = conn)
				previous_segment = seg_type
				continue

			_log.error(u'unexpected NTE segment')
			had_errors = True
			break

		_log.error('unknown segment, aborting')
		_log.debug('line: %s', seg)
		had_errors = True
		break

	if had_errors:
		conn.rollback()
		return False

	conn.commit()

	# record import in chart
	try:
		no_results = len(HL7.segments('OBX'))
	except KeyError:
		no_results = u'?'
	soap = _(
		'Imported HL7 file [%s]:\n'
		' lab "%s" (%s@%s), %s results (%s)'
	) % (
		filename,
		hl7_lab,
		gm_lab['unit'],
		gm_lab['organization'],
		no_results,
		u' / '.join(when_list.keys())
	)
	epi = emr.add_episode (
		episode_name = u'administrative',
		is_open = False,
		allow_dupes = False
	)
	emr.add_clin_narrative (
		note = soap,
		soap_cat = None,
		episode = epi
	)

	# keep copy of HL7 data in document archive
	folder = gmPerson.cPatient(emr.pk_patient).document_folder
	hl7_docs = folder.get_documents (
		doc_type = u'HL7 data',
		episodes = [epi['pk_episode']],
		order_by = u'ORDER BY clin_when DESC'
	)
	if len(hl7_docs) > 0:
		# there should only ever be one unless the user manually creates more,
		# also, it should always be the latest since "ORDER BY clin_when DESC"
		hl7_doc = hl7_docs[0]
	else:
		hl7_doc = folder.add_document (
			document_type = u'HL7 data',
			encounter = emr.active_encounter['pk_encounter'],
			episode = epi['pk_episode']
		)
		hl7_doc['comment'] = _('list of imported HL7 data files')
	hl7_doc['clin_when'] = gmDateTime.pydt_now_here()
	hl7_doc.save()
	part = hl7_doc.add_part(file = filename)
	part['obj_comment'] = _('Result dates: %s') % u' / '.join(when_list.keys())
	part.save()
	hl7_doc.set_reviewed(technically_abnormal = False, clinically_relevant = False)

	return True
Beispiel #25
0
 def test_atc_import():
     atc_import(cfg_fname=sys.argv[2],
                conn=gmPG2.get_connection(readonly=False))
Beispiel #26
0
	def __init__(self, *args, **kwargs):

		gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs)
		mp = gmLOINC.cLOINCMatchProvider()
		mp.setThresholds(1, 2, 4)
		#mp.print_queries = True
		#mp.word_separators = '[ \t:@]+'
		self.matcher = mp
		self.selection_only = False
		self.final_regex = r'\d{1,5}-\d{1}$'
		self.SetToolTip(_('Select a LOINC (Logical Observation Identifiers Names and Codes).'))

#================================================================
# main
#----------------------------------------------------------------
if __name__ == '__main__':

	if len(sys.argv) < 2:
		sys.exit()

	if sys.argv[1] != 'test':
		sys.exit()

	from Gnumed.pycommon import gmPG2

	#----------------------------------------
	gmPG2.get_connection()
	app = wx.PyWidgetTester(size = (600, 80))
	app.SetWidget(cLOINCPhraseWheel, -1)
	app.MainLoop()
Beispiel #27
0

#==================================================================
# main
#------------------------------------------------------------------
if __name__ == "__main__":
    tmp = ''
    try:
        tmp = raw_input("audit trail parent table [%s]: " %
                        AUDIT_TRAIL_PARENT_TABLE)
    except KeyboardError:
        pass
    if tmp != '':
        AUDIT_TRAIL_PARENT_TABLE = tmp

    conn = gmPG2.get_connection(readonly=False, pooled=False)
    curs = conn.cursor()

    schema = create_audit_ddl(curs)

    curs.close()
    conn.close()

    if schema is None:
        print "error creating schema"
        sys.exit(-1)

    f = io.open('audit-trail-schema.sql', mode='wb', encoding='utf8')
    for line in schema:
        f.write("%s;\n" % line)
    f.close()