def _refresh_from_existing(self): self._TCTRL_subject.SetValue( gmTools.coalesce(self.data['comment'], u'')) self._PRW_type.SetData(data=self.data['pk_type']) curr_prov = gmStaff.gmCurrentProvider() curr_pat = gmPerson.gmCurrentPatient() if curr_prov['pk_staff'] == self.data['pk_staff']: self._CHBOX_send_to_me.SetValue(True) self._PRW_receiver.Enable(False) self._PRW_receiver.SetData( data=gmStaff.gmCurrentProvider()['pk_staff']) else: self._CHBOX_send_to_me.SetValue(False) self._PRW_receiver.Enable(True) self._PRW_receiver.SetData(data=self.data['pk_staff']) self._TCTRL_message.SetValue(gmTools.coalesce(self.data['data'], u'')) if curr_pat.connected: self._CHBOX_active_patient.Enable(True) if curr_pat.ID == self.data['pk_patient']: self._CHBOX_active_patient.SetValue(True) self._PRW_patient.Enable(False) self._PRW_patient.person = None else: self._CHBOX_active_patient.SetValue(False) self._PRW_patient.Enable(True) if self.data['pk_patient'] is None: self._PRW_patient.person = None else: self._PRW_patient.person = gmPerson.cPerson( aPK_obj=self.data['pk_patient']) else: self._CHBOX_active_patient.Enable(False) self._CHBOX_active_patient.SetValue(False) self._PRW_patient.Enable(True) if self.data['pk_patient'] is None: self._PRW_patient.person = None else: self._PRW_patient.person = gmPerson.cPerson( aPK_obj=self.data['pk_patient']) self._PRW_due.SetText(data=self.data['due_date']) self._PRW_expiry.SetText(data=self.data['expiry_date']) self._RBTN_normal.SetValue(False) self._RBTN_high.SetValue(False) self._RBTN_low.SetValue(False) { -1: self._RBTN_low, 0: self._RBTN_normal, 1: self._RBTN_high }[self.data['importance']].SetValue(True) self._TCTRL_subject.SetFocus()
def _refresh_from_existing(self): self._TCTRL_subject.SetValue(gmTools.coalesce(self.data['comment'], u'')) self._PRW_type.SetData(data = self.data['pk_type']) curr_prov = gmStaff.gmCurrentProvider() curr_pat = gmPerson.gmCurrentPatient() if curr_prov['pk_staff'] == self.data['pk_staff']: self._CHBOX_send_to_me.SetValue(True) self._PRW_receiver.Enable(False) self._PRW_receiver.SetData(data = gmStaff.gmCurrentProvider()['pk_staff']) else: self._CHBOX_send_to_me.SetValue(False) self._PRW_receiver.Enable(True) self._PRW_receiver.SetData(data = self.data['pk_staff']) self._TCTRL_message.SetValue(gmTools.coalesce(self.data['data'], u'')) if curr_pat.connected: self._CHBOX_active_patient.Enable(True) if curr_pat.ID == self.data['pk_patient']: self._CHBOX_active_patient.SetValue(True) self._PRW_patient.Enable(False) self._PRW_patient.person = None else: self._CHBOX_active_patient.SetValue(False) self._PRW_patient.Enable(True) if self.data['pk_patient'] is None: self._PRW_patient.person = None else: self._PRW_patient.person = gmPerson.cPerson(aPK_obj = self.data['pk_patient']) else: self._CHBOX_active_patient.Enable(False) self._CHBOX_active_patient.SetValue(False) self._PRW_patient.Enable(True) if self.data['pk_patient'] is None: self._PRW_patient.person = None else: self._PRW_patient.person = gmPerson.cPerson(aPK_obj = self.data['pk_patient']) self._PRW_due.SetText(data = self.data['due_date']) self._PRW_expiry.SetText(data = self.data['expiry_date']) self._RBTN_normal.SetValue(False) self._RBTN_high.SetValue(False) self._RBTN_low.SetValue(False) { -1: self._RBTN_low, 0: self._RBTN_normal, 1: self._RBTN_high }[self.data['importance']].SetValue(True) self._TCTRL_subject.SetFocus()
def _on_delete_focussed_msg(self, evt): if self.__focussed_msg['is_virtual']: gmDispatcher.send(signal = 'statustext', msg = _('You must deal with the reason for this message to remove it from your inbox.'), beep = True) return False # if not "to" current provider, then don't delete if self.__focussed_msg['pk_staff'] != gmStaff.gmCurrentProvider()['pk_staff']: gmDispatcher.send(signal = 'statustext', msg = _('This message can only be deleted by [%s].') % self.__focussed_msg['provider'], beep = True) return False pk_patient = self.__focussed_msg['pk_patient'] if pk_patient is not None: emr = gmClinicalRecord.cClinicalRecord(aPKey = pk_patient) epi = emr.add_episode(episode_name = 'administrative', is_open = False) soap_cat = gmTools.bool2subst ( (self.__focussed_msg['category'] == 'clinical'), 'u', None ) narr = _('Deleted inbox message:\n%s') % self.__focussed_msg.format(with_patient = False) emr.add_clin_narrative(note = narr, soap_cat = soap_cat, episode = epi) gmDispatcher.send(signal = 'statustext', msg = _('Recorded deletion of inbox message in EMR.'), beep = False) if not self.provider.inbox.delete_message(self.__focussed_msg['pk_inbox_message']): gmDispatcher.send(signal='statustext', msg=_('Problem removing message from Inbox.')) return False return True
def _on_send_to_me_checked(self, event): if self._CHBOX_send_to_me.IsChecked(): self._PRW_receiver.Enable(False) self._PRW_receiver.SetData(data = gmStaff.gmCurrentProvider()['pk_staff']) else: self._PRW_receiver.Enable(True) self._PRW_receiver.SetText(value = '', data = None)
def _save_as_update(self): self.data['comment'] = self._TCTRL_subject.GetValue().strip() self.data['pk_type'] = self._PRW_type.GetData(can_create=True) if self._CHBOX_send_to_me.IsChecked(): self.data['pk_staff'] = gmStaff.gmCurrentProvider()['pk_staff'] else: self.data['pk_staff'] = self._PRW_receiver.GetData() self.data['data'] = self._TCTRL_message.GetValue().strip() if self._CHBOX_active_patient.GetValue() is True: self.data['pk_patient'] = gmPerson.gmCurrentPatient().ID else: if self._PRW_patient.person is None: self.data['pk_patient'] = None else: self.data['pk_patient'] = self._PRW_patient.person.ID if self._PRW_due.is_valid_timestamp(): self.data['due_date'] = self._PRW_due.date if self._PRW_expiry.is_valid_timestamp(): self.data['expiry_date'] = self._PRW_expiry.date if self._RBTN_normal.GetValue() is True: self.data['importance'] = 0 elif self._RBTN_high.GetValue() is True: self.data['importance'] = 1 else: self.data['importance'] = -1 self.data.save() return True
def _refresh_as_new(self): self._TCTRL_subject.SetValue(u'') self._PRW_type.SetText(value = u'', data = None) self._CHBOX_send_to_me.SetValue(True) self._PRW_receiver.Enable(False) self._PRW_receiver.SetData(data = gmStaff.gmCurrentProvider()['pk_staff']) self._TCTRL_message.SetValue(u'') self._PRW_due.SetText(data = None) self._PRW_expiry.SetText(data = None) self._RBTN_normal.SetValue(True) self._RBTN_high.SetValue(False) self._RBTN_low.SetValue(False) self._PRW_patient.person = None if gmPerson.gmCurrentPatient().connected: self._CHBOX_active_patient.Enable(True) self._CHBOX_active_patient.SetValue(True) self._PRW_patient.Enable(False) else: self._CHBOX_active_patient.Enable(False) self._CHBOX_active_patient.SetValue(False) self._PRW_patient.Enable(True) self._TCTRL_subject.SetFocus()
def create_dynamic_hint(link_obj=None, query=None, title=None, hint=None, source=None): args = { u'query': query, u'title': title, u'hint': hint, u'source': source, u'usr': gmStaff.gmCurrentProvider()['db_user'] } cmd = u""" INSERT INTO ref.auto_hint ( query, title, hint, source, lang ) VALUES ( gm.nullify_empty_string(%(query)s), gm.nullify_empty_string(%(title)s), gm.nullify_empty_string(%(hint)s), gm.nullify_empty_string(%(source)s), i18n.get_curr_lang(%(usr)s) ) RETURNING pk """ rows, idx = gmPG2.run_rw_queries(link_obj = link_obj, queries = [{'cmd': cmd, 'args': args}], return_data = True, get_col_idx = True) return cDynamicHint(aPK_obj = rows[0]['pk'], link_obj = link_obj)
def _save_as_update(self): self.data['comment'] = self._TCTRL_subject.GetValue().strip() self.data['pk_type'] = self._PRW_type.GetData(can_create = True) if self._CHBOX_send_to_me.IsChecked(): self.data['pk_staff'] = gmStaff.gmCurrentProvider()['pk_staff'] else: self.data['pk_staff'] = self._PRW_receiver.GetData() self.data['data'] = self._TCTRL_message.GetValue().strip() if self._CHBOX_active_patient.GetValue() is True: self.data['pk_patient'] = gmPerson.gmCurrentPatient().ID else: if self._PRW_patient.person is None: self.data['pk_patient'] = None else: self.data['pk_patient'] = self._PRW_patient.person.ID if self._PRW_due.is_valid_timestamp(): self.data['due_date'] = self._PRW_due.date if self._PRW_expiry.is_valid_timestamp(): self.data['expiry_date'] = self._PRW_expiry.date if self._RBTN_normal.GetValue() is True: self.data['importance'] = 0 elif self._RBTN_high.GetValue() is True: self.data['importance'] = 1 else: self.data['importance'] = -1 self.data.save() return True
def _on_delete_focussed_msg(self, evt): if self.__focussed_msg['is_virtual']: gmDispatcher.send(signal = 'statustext', msg = _('You must deal with the reason for this message to remove it from your inbox.'), beep = True) return False # if not "to" current provider, then don't delete if self.__focussed_msg['pk_staff'] != gmStaff.gmCurrentProvider()['pk_staff']: gmDispatcher.send(signal = 'statustext', msg = _('This message can only be deleted by [%s].') % self.__focussed_msg['provider'], beep = True) return False pk_patient = self.__focussed_msg['pk_patient'] if pk_patient is not None: #emr = gmClinicalRecord.cClinicalRecord(aPKey = pk_patient, allow_user_interaction = False) from Gnumed.wxpython import gmChartPullingWidgets emr = gmChartPullingWidgets.pull_chart(gmPerson.cPerson(pk_patient)) if emr is None: return False epi = emr.add_episode(episode_name = 'administrative', is_open = False) soap_cat = gmTools.bool2subst ( (self.__focussed_msg['category'] == u'clinical'), u'U', None ) narr = _('Deleted inbox message:\n%s') % self.__focussed_msg.format(with_patient = False) emr.add_clin_narrative(note = narr, soap_cat = soap_cat, episode = epi) gmDispatcher.send(signal = 'statustext', msg = _('Recorded deletion of inbox message in EMR.'), beep = False) if not self.provider.inbox.delete_message(self.__focussed_msg['pk_inbox_message']): gmDispatcher.send(signal='statustext', msg=_('Problem removing message from Inbox.')) return False return True
def _on_send_to_me_checked(self, event): if self._CHBOX_send_to_me.IsChecked(): self._PRW_receiver.Enable(False) self._PRW_receiver.SetData(data = gmStaff.gmCurrentProvider()['pk_staff']) else: self._PRW_receiver.Enable(True) self._PRW_receiver.SetText(value = u'', data = None)
def create_dynamic_hint(link_obj=None, query=None, title=None, hint=None, source=None): args = { 'query': query, 'title': title, 'hint': hint, 'source': source, 'usr': gmStaff.gmCurrentProvider()['db_user'] } cmd = """ INSERT INTO ref.auto_hint ( query, title, hint, source, lang ) VALUES ( gm.nullify_empty_string(%(query)s), gm.nullify_empty_string(%(title)s), gm.nullify_empty_string(%(hint)s), gm.nullify_empty_string(%(source)s), i18n.get_curr_lang(%(usr)s) ) RETURNING pk """ rows, idx = gmPG2.run_rw_queries(link_obj = link_obj, queries = [{'cmd': cmd, 'args': args}], return_data = True, get_col_idx = True) return cDynamicHint(aPK_obj = rows[0]['pk'], link_obj = link_obj)
def _refresh_as_new(self): self._TCTRL_subject.SetValue(u'') self._PRW_type.SetText(value=u'', data=None) self._CHBOX_send_to_me.SetValue(True) self._PRW_receiver.Enable(False) self._PRW_receiver.SetData( data=gmStaff.gmCurrentProvider()['pk_staff']) self._TCTRL_message.SetValue(u'') self._PRW_due.SetText(data=None) self._PRW_expiry.SetText(data=None) self._RBTN_normal.SetValue(True) self._RBTN_high.SetValue(False) self._RBTN_low.SetValue(False) self._PRW_patient.person = None if gmPerson.gmCurrentPatient().connected: self._CHBOX_active_patient.Enable(True) self._CHBOX_active_patient.SetValue(True) self._PRW_patient.Enable(False) else: self._CHBOX_active_patient.Enable(False) self._CHBOX_active_patient.SetValue(False) self._PRW_patient.Enable(True) self._TCTRL_subject.SetFocus()
def _on_delete_focussed_msg(self, evt): if self.__focussed_msg['is_virtual']: gmDispatcher.send(signal = 'statustext', msg = _('You must deal with the reason for this message to remove it from your inbox.'), beep = True) return False # message to a certain provider ? if self.__focussed_msg['pk_staff'] is not None: # do not delete messages to *other* providers if self.__focussed_msg['pk_staff'] != gmStaff.gmCurrentProvider()['pk_staff']: gmDispatcher.send(signal = 'statustext', msg = _('This message can only be deleted by [%s].') % self.__focussed_msg['provider'], beep = True) return False pk_patient = self.__focussed_msg['pk_patient'] if pk_patient is not None: emr = gmClinicalRecord.cClinicalRecord(aPKey = pk_patient) epi = emr.add_episode(episode_name = 'administrative', is_open = False) soap_cat = gmTools.bool2subst ( (self.__focussed_msg['category'] == 'clinical'), 'u', None ) narr = _('Deleted inbox message:\n%s') % self.__focussed_msg.format(with_patient = False) emr.add_clin_narrative(note = narr, soap_cat = soap_cat, episode = epi) gmDispatcher.send(signal = 'statustext', msg = _('Recorded deletion of inbox message in EMR.'), beep = False) if not self.provider.inbox.delete_message(self.__focussed_msg['pk_inbox_message']): gmDispatcher.send(signal='statustext', msg=_('Problem removing message from Inbox.')) return False return True
def GetWidget(self, parent): # get current workplace name workplace = gmPraxis.gmCurrentPraxisBranch().active_workplace currUser = gmStaff.gmCurrentProvider()['db_user'] _log.info("ConfigReg: %s@%s" % (currUser, workplace)) self._widget = gmConfigEditorPanel(parent, currUser, workplace) return self._widget
def import_fd2gm_file_as_prescription(self, filename=None): if filename is None: filename = self.__fd2gm_filename _log.debug('importing FreeDiams prescription information from [%s]', filename) fd2gm_xml = etree.ElementTree() fd2gm_xml.parse(filename) pdfs = fd2gm_xml.findall('ExtraDatas/Printed') if len(pdfs) == 0: _log.debug('no PDF prescription files listed') return fd_filenames = [] for pdf in pdfs: fd_filenames.append(pdf.attrib['file']) _log.debug('listed PDF prescription files: %s', fd_filenames) docs = self.patient.get_document_folder() emr = self.patient.emr prescription = docs.add_prescription ( encounter = emr.active_encounter['pk_encounter'], episode = emr.add_episode ( episode_name = gmMedication.DEFAULT_MEDICATION_HISTORY_EPISODE, is_open = False )['pk_episode'] ) prescription['ext_ref'] = 'FreeDiams' prescription.save() fd_filenames.append(filename) success, msg, parts = prescription.add_parts_from_files(files = fd_filenames) if not success: _log.error(msg) return for part in parts: part['obj_comment'] = _('copy of printed prescription') part.save() xml_part = parts[-1] xml_part['filename'] = 'freediams-prescription.xml' xml_part['obj_comment'] = _('prescription data') xml_part.save() # are we the intended reviewer ? from Gnumed.business.gmStaff import gmCurrentProvider me = gmCurrentProvider() # if so: auto-sign the prescription if xml_part['pk_intended_reviewer'] == me['pk_staff']: prescription.set_reviewed(technically_abnormal = False, clinically_relevant = False)
def import_fd2gm_file_as_prescription(self, filename=None): if filename is None: filename = self.__fd2gm_filename _log.debug('importing FreeDiams prescription information from [%s]', filename) fd2gm_xml = etree.ElementTree() fd2gm_xml.parse(filename) pdfs = fd2gm_xml.findall('ExtraDatas/Printed') if len(pdfs) == 0: _log.debug('no PDF prescription files listed') return fd_filenames = [] for pdf in pdfs: fd_filenames.append(pdf.attrib['file']) _log.debug('listed PDF prescription files: %s', fd_filenames) docs = self.patient.get_document_folder() emr = self.patient.emr prescription = docs.add_prescription ( encounter = emr.active_encounter['pk_encounter'], episode = emr.add_episode ( episode_name = DEFAULT_MEDICATION_HISTORY_EPISODE, is_open = False )['pk_episode'] ) prescription['ext_ref'] = 'FreeDiams' prescription.save() fd_filenames.append(filename) success, msg, parts = prescription.add_parts_from_files(files = fd_filenames) if not success: _log.error(msg) return for part in parts: part['obj_comment'] = _('copy of printed prescription') part.save() xml_part = parts[-1] xml_part['filename'] = 'freediams-prescription.xml' xml_part['obj_comment'] = _('prescription data') xml_part.save() # are we the intended reviewer ? from Gnumed.business.gmStaff import gmCurrentProvider me = gmCurrentProvider() # if so: auto-sign the prescription if xml_part['pk_intended_reviewer'] == me['pk_staff']: prescription.set_reviewed(technically_abnormal = False, clinically_relevant = False)
def refresh(lctrl): notes = emr.get_clin_narrative( encounters=encounters, episodes=episodes, providers=[gmStaff.gmCurrentProvider()['short_alias']]) lctrl.set_string_items(items=[[ narr['date'].strftime('%x %H:%M'), gmSoapDefs.soap_cat2l10n[ narr['soap_cat']], narr['narrative'].replace( '\n', '/').replace('\r', '/') ] for narr in notes]) lctrl.set_data(data=notes)
def refresh(lctrl): notes = emr.get_clin_narrative ( encounters = encounters, episodes = episodes, providers = [ gmStaff.gmCurrentProvider()['short_alias'] ] ) lctrl.set_string_items(items = [ [ narr['date'].strftime('%x %H:%M'), gmSoapDefs.soap_cat2l10n[narr['soap_cat']], narr['narrative'].replace('\n', '/').replace('\r', '/') ] for narr in notes ]) lctrl.set_data(data = notes)
def __init__(self, *args, **kwds): wxgProviderInboxPnl.wxgProviderInboxPnl.__init__(self, *args, **kwds) gmRegetMixin.cRegetOnPaintMixin.__init__(self) self.provider = gmStaff.gmCurrentProvider() self.__init_ui() cProviderInboxPnl._item_handlers['clinical.review docs'] = self._goto_doc_review cProviderInboxPnl._item_handlers['clinical.review results'] = self._goto_measurements_review cProviderInboxPnl._item_handlers['clinical.review lab'] = self._goto_measurements_review cProviderInboxPnl._item_handlers['clinical.review vaccs'] = self._goto_vaccination_review self.__register_interests()
def _check_for_provider_chart_access(person): curr_prov = gmStaff.gmCurrentProvider() # can view my own chart if person.ID == curr_prov['pk_identity']: return True # primary provider can view patient if person['pk_primary_provider'] == curr_prov['pk_staff']: return True # is the patient a provider ? if person.ID not in [ s['pk_identity'] for s in gmStaff.get_staff_list() ]: return True prov = u'%s (%s%s %s)' % ( curr_prov['short_alias'], gmTools.coalesce(curr_prov['title'], u'', u'%s '), curr_prov['firstnames'], curr_prov['lastnames'] ) pat = u'%s%s %s' % ( gmTools.coalesce(person['title'], u'', u'%s '), person['firstnames'], person['lastnames'] ) # notify the staff member gmProviderInbox.create_inbox_message ( staff = person.staff_id, message_type = _('Privacy notice'), message_category = u'administrative', subject = _('%s: Your chart has been accessed by %s (without user interaction, probably by a script).') % (pat, prov), patient = person.ID ) # notify /me about the staff member notification gmProviderInbox.create_inbox_message ( staff = curr_prov['pk_staff'], message_type = _('Privacy notice'), message_category = u'administrative', subject = _('%s: Staff member %s has been notified of your chart access.') % (prov, pat) ) return True
def _save_as_new(self): pat_id = None if self._CHBOX_active_patient.GetValue() is True: pat_id = gmPerson.gmCurrentPatient().ID else: if self._PRW_patient.person is not None: pat_id = self._PRW_patient.person.ID receiver = None if self._CHBOX_send_to_me.IsChecked(): receiver = gmStaff.gmCurrentProvider()['pk_staff'] else: if self._PRW_receiver.GetData() is not None: receiver = self._PRW_receiver.GetData() msg = gmProviderInbox.create_inbox_message ( patient = pat_id, staff = receiver, message_type = self._PRW_type.GetData(can_create = True), subject = self._TCTRL_subject.GetValue().strip() ) msg['data'] = self._TCTRL_message.GetValue().strip() if self._PRW_due.is_valid_timestamp(): msg['due_date'] = self._PRW_due.date if self._PRW_expiry.is_valid_timestamp(): msg['expiry_date'] = self._PRW_expiry.date if self._RBTN_normal.GetValue() is True: msg['importance'] = 0 elif self._RBTN_high.GetValue() is True: msg['importance'] = 1 else: msg['importance'] = -1 msg.save() self.data = msg return True
def __init_ui(self): self._PRW_lastname.final_regex = '.+' self._PRW_firstnames.final_regex = '.+' self._PRW_address_searcher.selection_only = False # only if we would support None on selection_only's: # self._PRW_external_id_type.selection_only = True if self.default_country is not None: match = self._PRW_country._data2match(data = self.default_country) if match is not None: self._PRW_country.SetText(value = match['field_label'], data = match['data']) if self.default_region is not None: self._PRW_region.SetText(value = self.default_region) self._PRW_type.SetText(value = 'home') # FIXME: only use this if member of gm-doctors, # FIXME: other than that check fallback_primary_provider self._PRW_primary_provider.SetData(data = gmStaff.gmCurrentProvider()['pk_staff']) self._PRW_lastname.SetFocus()
def _on_mark_reviewed(self, event): reviewed_results = [] for row in range(self.__grid_unreviewed_results.GetNumberRows()): if self.__grid_unreviewed_results.GetCellValue(row, 0) == '1': # look up associated request result = self.dict_unreviewed_results[row] reviewed_results.append(result) # update "relevant" status relevant = self.__grid_unreviewed_results.GetCellValue(row, 1) if relevant == '1': result['relevant'] = 'true' else: result['relevant'] = 'false' if len(reviewed_results) == 0: gmGuiHelpers.beep_status_text(_('No results marked as reviewed.')) event.Skip() return None for result in reviewed_results: result['reviewed'] = 'true' result['pk_reviewer'] = gmStaff.gmCurrentProvider()['pk_staff'] if not result['abnormal']: result['abnormal'] = '' successfull, error = result.save_payload() # repopulate if successfull: self.__populate_notebook() else: _log.Log(gmLog.lErr, 'setting result status to reviewed failed %s' % error) gmGuiHelpers.gm_show_error( aMessage=_('Cannot mark results as "reviewed":\n%s') % error, aTitle=_('update result status')) return None event.Skip()
def _on_mark_reviewed(self, event): reviewed_results = [] for row in range(self.__grid_unreviewed_results.GetNumberRows()): if self.__grid_unreviewed_results.GetCellValue(row, 0) == '1': # look up associated request result = self.dict_unreviewed_results[row] reviewed_results.append(result) # update "relevant" status relevant = self.__grid_unreviewed_results.GetCellValue(row, 1) if relevant == '1': result['relevant'] = 'true' else: result['relevant'] = 'false' if len(reviewed_results) == 0: gmGuiHelpers.beep_status_text(_('No results marked as reviewed.')) event.Skip() return None for result in reviewed_results: result['reviewed'] = 'true' result['pk_reviewer'] = gmStaff.gmCurrentProvider()['pk_staff'] if not result['abnormal']: result['abnormal'] = '' successfull, error = result.save_payload() # repopulate if successfull: self.__populate_notebook() else: _log.Log(gmLog.lErr, 'setting result status to reviewed failed %s' % error) gmGuiHelpers.gm_show_error ( aMessage = _('Cannot mark results as "reviewed":\n%s') % error, aTitle = _('update result status') ) return None event.Skip()
def __init_ui(self): self._PRW_lastname.final_regex = '.+' self._PRW_firstnames.final_regex = '.+' self._PRW_address_searcher.selection_only = False # only if we would support None on selection_only's: # self._PRW_external_id_type.selection_only = True if self.default_country is not None: match = self._PRW_country._data2match(data=self.default_country) if match is not None: self._PRW_country.SetText(value=match['field_label'], data=match['data']) if self.default_region is not None: self._PRW_region.SetText(value=self.default_region) self._PRW_type.SetText(value='home') # FIXME: only use this if member of gm-doctors, # FIXME: other than that check fallback_primary_provider self._PRW_primary_provider.SetData( data=gmStaff.gmCurrentProvider()['pk_staff']) self._PRW_lastname.SetFocus()
def Setup(parent): """Wrapper to load this module from an environment that wants a panel """ currUser = gmStaff.gmCurrentProvider()['db_user'] workplace = gmPraxis.gmCurrentPraxisBranch().active_workplace return gmConfigEditorPanel(parent, currUser, workplace)
def print_generic_document(parent=None, jobtype:str=None, episode=None): """Call LibreOffice Writer with a generated (fake) ODT file. Once Writer is closed, the ODT is imported if different from its initial content. Note: The file passed to LO _must_ reside in a directory the parents of which are all R-X by the user or else LO will throw up its arms in despair and fall back to the user's home dir upon saving. So, /tmp/user/$UID/some-file.odt will *not* work (because .../user/... is "drwx--x--x root.root") while /home/$USER/some/dir/some-file.odt does. """ sandbox = os.path.join(gmTools.gmPaths().user_tmp_dir, 'libreoffice') gmTools.mkdir(sandbox) fpath = gmTools.get_unique_filename(suffix = '.txt', tmp_dir = sandbox) doc_file = open(fpath, mode = 'wt') doc_file.write(__ODT_FILE_PREAMBLE) doc_file.write(_('Today: %s') % gmDateTime.pydt_now_here().strftime('%c')) doc_file.write('\n\n') prax = gmPraxis.gmCurrentPraxisBranch() doc_file.write('Praxis:\n') doc_file.write(prax.format()) doc_file.write('\n') doc_file.write('Praxis branch:\n') doc_file.write('\n'.join(prax.org_unit.format ( with_address = True, with_org = True, with_comms = True ))) doc_file.write('\n\n') pat = gmPerson.gmCurrentPatient(gmPerson.cPatient(12)) if pat.connected: doc_file.write('Patient:\n') doc_file.write(pat.get_description_gender()) doc_file.write('\n\n') for adr in pat.get_addresses(): doc_file.write(adr.format(single_line = False, verbose = True, show_type = True)) doc_file.write('\n\n') for chan in pat.get_comm_channels(): doc_file.werite(chan.format()) doc_file.write('\n\n') doc_file.write('Provider:\n') doc_file.write('\n'.join(gmStaff.gmCurrentProvider().get_staff().format())) doc_file.write('\n\n-----------------------------------------------------------------------------\n\n') doc_file.close() # convert txt -> odt success, ret_code, stdout = gmShellAPI.run_process ( cmd_line = [ 'lowriter', '--convert-to', 'odt', '--outdir', os.path.split(fpath)[0], fpath ], verbose = True ) if success: fpath = gmTools.fname_stem_with_path(fpath) + '.odt' else: _log.warning('cannot convert .txt to .odt') md5_before = gmTools.file2md5(fpath) gmShellAPI.run_process(cmd_line = ['lowriter', fpath], verbose = True) md5_after = gmTools.file2md5(fpath) if md5_before == md5_after: gmDispatcher.send(signal = 'statustext', msg = _('Document not modified. Discarding.'), beep = False) return if not pat.connected: shutil.move(fpath, gmTools.gmPaths().user_work_dir) gmDispatcher.send(signal = 'statustext', msg = _('No patient. Moved file into %s') % gmTools.gmPaths().user_work_dir, beep = False) return pat.export_area.add_file ( filename = fpath, hint = _('Generic letter, written at %s') % gmDateTime.pydt_now_here().strftime('%Y %b %d %H:%M') ) gmDispatcher.send(signal = 'display_widget', name = 'gmExportAreaPlugin')
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
def sanity_check_encounter_of_active_patient(parent=None, msg=None): # FIXME: should consult a centralized security provider # secretaries cannot edit encounters if gmStaff.gmCurrentProvider()['role'] == u'secretary': return True pat = gmPerson.gmCurrentPatient() if not pat.connected: return True dbcfg = gmCfg.cCfgSQL() check_enc = bool(dbcfg.get2 ( option = 'encounter.show_editor_before_patient_change', workplace = gmPraxis.gmCurrentPraxisBranch().active_workplace, bias = 'user', default = True # True: if needed, not always unconditionally )) if not check_enc: return True emr = pat.get_emr() enc = emr.active_encounter # did we add anything to the EMR ? has_narr = enc.has_narrative() has_docs = enc.has_documents() if (not has_narr) and (not has_docs): return True empty_aoe = (gmTools.coalesce(enc['assessment_of_encounter'], '').strip() == u'') zero_duration = (enc['last_affirmed'] == enc['started']) # all is well anyway if (not empty_aoe) and (not zero_duration): return True if zero_duration: enc['last_affirmed'] = pydt.datetime.now(tz = gmDateTime.gmCurrentLocalTimezone) # no narrative, presumably only import of docs and done if not has_narr: if empty_aoe: enc['assessment_of_encounter'] = _('only documents added') enc['pk_type'] = gmEMRStructItems.get_encounter_type(description = 'chart review')[0]['pk'] # "last_affirmed" should be latest modified_at of relevant docs but that's a lot more involved enc.save_payload() return True # does have narrative if empty_aoe: # - work out suitable default epis = emr.get_episodes_by_encounter() if len(epis) > 0: enc_summary = '' for epi in epis: enc_summary += '%s; ' % epi['description'] enc['assessment_of_encounter'] = enc_summary if msg is None: msg = _('Edit the encounter details of the active patient before moving on:') if parent is None: parent = wx.GetApp().GetTopWindow() edit_encounter(parent = parent, encounter = enc, msg = msg) return True
def sanity_check_encounter_of_active_patient(parent=None, msg=None): # FIXME: should consult a centralized security provider # secretaries cannot edit encounters if gmStaff.gmCurrentProvider()['role'] == 'secretary': return True pat = gmPerson.gmCurrentPatient() if not pat.connected: return True check_enc = gmCfgDB.get4user( option='encounter.show_editor_before_patient_change', workplace=gmPraxis.gmCurrentPraxisBranch().active_workplace, default=True # True: if needed, not always unconditionally ) if not check_enc: return True emr = pat.emr enc = emr.active_encounter # did we add anything to the EMR ? has_narr = enc.has_narrative() has_docs = enc.has_documents() if (not has_narr) and (not has_docs): return True empty_aoe = (gmTools.coalesce(enc['assessment_of_encounter'], '').strip() == '') zero_duration = (enc['last_affirmed'] == enc['started']) # all is well anyway if (not empty_aoe) and (not zero_duration): return True if zero_duration: enc['last_affirmed'] = pydt.datetime.now( tz=gmDateTime.gmCurrentLocalTimezone) # no narrative, presumably only import of docs and done if not has_narr: if empty_aoe: enc['assessment_of_encounter'] = _('only documents added') enc['pk_type'] = gmEMRStructItems.get_encounter_type( description='chart review')[0]['pk'] # "last_affirmed" should be latest modified_at of relevant docs but that's a lot more involved enc.save_payload() return True # does have narrative if empty_aoe: # - work out suitable default epis = emr.get_episodes_by_encounter() if len(epis) > 0: enc['assessment_of_encounter'] = '; '.join( [e['description'] for e in epis]) enc.save_payload() if msg is None: msg = _( 'Edit the encounter details of the active patient before moving on:' ) if parent is None: parent = wx.GetApp().GetTopWindow() _log.debug('sanity-check editing encounter [%s] for patient [%s]', enc['pk_encounter'], enc['pk_patient']) edit_encounter(parent=parent, encounter=enc, msg=msg) return True
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', 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
from Gnumed.business import gmStaff from Gnumed.wxpython import gmGuiHelpers _log = logging.getLogger('gm.perms') #========================================================================= _known_roles = [ 'public access', 'non-clinical access', 'limited clinical access', # currently not in use 'full clinical access', 'admin' # currently not in use ] _curr_staff = gmStaff.gmCurrentProvider() #------------------------------------------------------------------------- def verify_minimum_required_role(minimum_role, activity=None, return_value_on_failure=None, fail_silently=False): if activity is None: activity = _('generic activity') #--------- def _inner_verify_minimum_required_role(original_function): #---------
def get_provider_inbox_data(self): self.provider = gmStaff.gmCurrentProvider(provider=gmStaff.cStaff()) inbox = gmProviderInbox.cProviderInbox() self.__msgs = inbox.messages return jsonclasshintify(inbox.messages)
def __init__(self, provider_id=None): if provider_id is None: self.__provider_id = gmStaff.gmCurrentProvider()['pk_staff'] else: self.__provider_id = provider_id
def test_inbox(): gmStaff.gmCurrentProvider(provider=gmStaff.cStaff()) inbox = cProviderInbox() for msg in inbox.messages: print msg
def edit_narrative(parent=None, narrative=None, single_entry=False): assert isinstance(narrative, gmClinNarrative.cNarrative), '<narrative> must be of type <cNarrative>' title = _('Editing progress note') if narrative['modified_by_raw'] == gmStaff.gmCurrentProvider()['db_user']: msg = _('Your original progress note:') else: msg = _('Original progress note by %s [%s]\n(will be notified of changes):') % ( narrative['modified_by'], narrative['modified_by_raw'] ) if parent is None: parent = wx.GetApp().GetTopWindow() dlg = gmGuiHelpers.cMultilineTextEntryDlg ( parent, -1, title = title, msg = msg, data = narrative.format(left_margin = ' ', fancy = True), text = narrative['narrative'].strip() ) decision = dlg.ShowModal() val = dlg.value.strip() dlg.DestroyLater() if decision != wx.ID_SAVE: return False if val == '': return False if val == narrative['narrative'].strip(): return False if narrative['modified_by_raw'] == gmStaff.gmCurrentProvider()['db_user']: narrative['narrative'] = val narrative.save_payload() return True q = _( 'Original progress note written by someone else:\n' '\n' ' %s (%s)\n' '\n' 'Upon saving changes that person will be notified.\n' '\n' 'Consider saving as a new progress note instead.' ) % ( narrative['modified_by_raw'], narrative['modified_by'] ) buttons = [ {'label': _('Save changes'), 'default': True}, {'label': _('Save new note')}, {'label': _('Discard')} ] dlg = gmGuiHelpers.c3ButtonQuestionDlg(parent = parent, caption = title, question = q, button_defs = buttons) decision = dlg.ShowModal() dlg.DestroyLater() if decision not in [wx.ID_YES, wx.ID_NO]: return False if decision == wx.ID_NO: # create new progress note within the same context as the original one gmClinNarrative.create_narrative_item ( narrative = val, soap_cat = narrative['soap_cat'], episode_id = narrative['pk_episode'], encounter_id = narrative['pk_encounter'] ) return True # notify original provider msg = gmProviderInbox.create_inbox_message ( staff = narrative.staff_id, message_type = _('Change notification'), message_category = 'administrative', subject = _('A progress note of yours has been edited.'), patient = narrative['pk_patient'] ) msg['data'] = _( 'Original (by [%s]):\n' '%s\n' '\n' 'Edited (by [%s]):\n' '%s' ) % ( narrative['modified_by'], narrative['narrative'].strip(), gmStaff.gmCurrentProvider()['short_alias'], val ) msg.save() # notify /me about the staff member notification #gmProviderInbox.create_inbox_message ( # staff = curr_prov['pk_staff'], # message_type = _('Privacy notice'), # message_category = 'administrative', # subject = _('%s: Staff member %s has been notified of your chart access.') % (prov, pat) #) # save narrative change narrative['narrative'] = val narrative.save() return True
def _verify_staff_chart_access(patient=None): if patient is None: return True # staff ? if patient.ID not in [ s['pk_identity'] for s in gmStaff.get_staff_list() ]: return True curr_prov = gmStaff.gmCurrentProvider() # can view my own chart if patient.ID == curr_prov['pk_identity']: return True # primary provider can view patient if patient['pk_primary_provider'] == curr_prov['pk_staff']: return True proceed = gmGuiHelpers.gm_show_question ( aTitle = _('Privacy check'), aMessage = _( 'You have selected the chart of a member of staff,\n' 'for whom privacy is especially important:\n' '\n' ' %s, %s\n' '\n' 'This may be OK depending on circumstances.\n' '\n' 'Please be aware that accessing patient charts is\n' 'logged and that %s%s will be\n' 'notified of the access if you choose to proceed.\n' '\n' 'Are you sure you want to draw this chart ?' ) % ( patient.get_description_gender(), patient.get_formatted_dob(), gmTools.coalesce(patient['title'], '', '%s '), patient['lastnames'] ) ) if proceed: prov = '%s (%s%s %s)' % ( curr_prov['short_alias'], gmTools.coalesce(curr_prov['title'], '', '%s '), curr_prov['firstnames'], curr_prov['lastnames'] ) pat = '%s%s %s' % ( gmTools.coalesce(patient['title'], '', '%s '), patient['firstnames'], patient['lastnames'] ) # notify the staff member gmProviderInbox.create_inbox_message ( staff = patient.staff_id, message_type = _('Privacy notice'), message_category = 'administrative', subject = _('%s: Your chart has been accessed by %s.') % (pat, prov), patient = patient.ID ) # notify /me about the staff member notification gmProviderInbox.create_inbox_message ( staff = curr_prov['pk_staff'], message_type = _('Privacy notice'), message_category = 'administrative', subject = _('%s: Staff member %s has been notified of your chart access.') % (prov, pat) ) return proceed
def manage_progress_notes(parent=None, encounters=None, episodes=None, patient=None): # sanity checks if patient is None: patient = gmPerson.gmCurrentPatient() if not patient.connected: gmDispatcher.send( signal='statustext', msg=_('Cannot edit progress notes. No active patient.')) return False if parent is None: parent = wx.GetApp().GetTopWindow() emr = patient.emr #-------------------------- def delete(item): if item is None: return False dlg = gmGuiHelpers.c2ButtonQuestionDlg( parent, -1, caption=_('Deleting progress note'), question=_( 'Are you positively sure you want to delete this\n' 'progress note from the medical record ?\n' '\n' 'Note that even if you chose to delete the entry it will\n' 'still be (invisibly) kept in the audit trail to protect\n' 'you from litigation because physical deletion is known\n' 'to be unlawful in some jurisdictions.\n'), button_defs=({ 'label': _('Delete'), 'tooltip': _('Yes, delete the progress note.'), 'default': False }, { 'label': _('Cancel'), 'tooltip': _('No, do NOT delete the progress note.'), 'default': True })) decision = dlg.ShowModal() if decision != wx.ID_YES: return False gmClinNarrative.delete_clin_narrative(narrative=item['pk_narrative']) return True #-------------------------- def edit(item): if item is None: return False dlg = gmGuiHelpers.cMultilineTextEntryDlg( parent, -1, title=_('Editing progress note'), msg=_('This is the original progress note:'), data=item.format(left_margin=' ', fancy=True), text=item['narrative']) decision = dlg.ShowModal() if decision != wx.ID_SAVE: return False val = dlg.value dlg.Destroy() if val.strip() == '': return False item['narrative'] = val item.save_payload() return True #-------------------------- def refresh(lctrl): notes = emr.get_clin_narrative( encounters=encounters, episodes=episodes, providers=[gmStaff.gmCurrentProvider()['short_alias']]) lctrl.set_string_items(items=[[ narr['date'].strftime('%x %H:%M'), gmSoapDefs.soap_cat2l10n[ narr['soap_cat']], narr['narrative'].replace( '\n', '/').replace('\r', '/') ] for narr in notes]) lctrl.set_data(data=notes) #-------------------------- gmListWidgets.get_choices_from_list( parent=parent, caption=_('Managing progress notes'), msg=_('\n' ' This list shows the progress notes by %s.\n' '\n') % gmStaff.gmCurrentProvider()['short_alias'], columns=[_('when'), _('type'), _('entry')], single_selection=True, can_return_empty=False, edit_callback=edit, delete_callback=delete, refresh_callback=refresh)
def manage_progress_notes(parent=None, encounters=None, episodes=None, patient=None): # sanity checks if patient is None: patient = gmPerson.gmCurrentPatient() if not patient.connected: gmDispatcher.send(signal = 'statustext', msg = _('Cannot edit progress notes. No active patient.')) return False if parent is None: parent = wx.GetApp().GetTopWindow() emr = patient.emr #-------------------------- def delete(item): if item is None: return False dlg = gmGuiHelpers.c2ButtonQuestionDlg ( parent, -1, caption = _('Deleting progress note'), question = _( 'Are you positively sure you want to delete this\n' 'progress note from the medical record ?\n' '\n' 'Note that even if you chose to delete the entry it will\n' 'still be (invisibly) kept in the audit trail to protect\n' 'you from litigation because physical deletion is known\n' 'to be unlawful in some jurisdictions.\n' ), button_defs = ( {'label': _('Delete'), 'tooltip': _('Yes, delete the progress note.'), 'default': False}, {'label': _('Cancel'), 'tooltip': _('No, do NOT delete the progress note.'), 'default': True} ) ) decision = dlg.ShowModal() if decision != wx.ID_YES: return False gmClinNarrative.delete_clin_narrative(narrative = item['pk_narrative']) return True #-------------------------- def edit(item): if item is None: return False dlg = gmGuiHelpers.cMultilineTextEntryDlg ( parent, -1, title = _('Editing progress note'), msg = _('This is the original progress note:'), data = item.format(left_margin = ' ', fancy = True), text = item['narrative'] ) decision = dlg.ShowModal() if decision != wx.ID_SAVE: return False val = dlg.value dlg.DestroyLater() if val.strip() == '': return False item['narrative'] = val item.save_payload() return True #-------------------------- def refresh(lctrl): notes = emr.get_clin_narrative ( encounters = encounters, episodes = episodes, providers = [ gmStaff.gmCurrentProvider()['short_alias'] ] ) lctrl.set_string_items(items = [ [ narr['date'].strftime('%x %H:%M'), gmSoapDefs.soap_cat2l10n[narr['soap_cat']], narr['narrative'].replace('\n', '/').replace('\r', '/') ] for narr in notes ]) lctrl.set_data(data = notes) #-------------------------- gmListWidgets.get_choices_from_list ( parent = parent, caption = _('Managing progress notes'), msg = _( '\n' ' This list shows the progress notes by %s.\n' '\n' ) % gmStaff.gmCurrentProvider()['short_alias'], columns = [_('when'), _('type'), _('entry')], single_selection = True, can_return_empty = False, edit_callback = edit, delete_callback = delete, refresh_callback = refresh )
def save(self): """Save data into backend.""" # fill progress_note for import progress_note = [] aoe = '' rfe = '' has_rfe = False soap_lines_contents = self.GetValue() for line_content in soap_lines_contents.values(): if line_content.text.strip() == '': continue progress_note.append ({ gmSOAPimporter.soap_bundle_SOAP_CAT_KEY: line_content.data.soap_cat, gmSOAPimporter.soap_bundle_TYPES_KEY: [], # these types need to come from the editor gmSOAPimporter.soap_bundle_TEXT_KEY: line_content.text.rstrip() }) if line_content.data.is_rfe: has_rfe = True rfe += line_content.text.rstrip() if line_content.data.soap_cat == 'a': aoe += line_content.text.rstrip() emr = self.__pat.emr # - new episode, must get name from narrative (or user) if (self.__problem is None) or (self.__problem['type'] == 'issue'): # work out episode name epi_name = '' if len(aoe) != 0: epi_name = aoe else: epi_name = rfe dlg = wx.TextEntryDialog ( self, _('Enter a descriptive name for this new problem:'), caption = _('Creating a problem (episode) to save the notelet under ...'), value = epi_name.replace('\r', '//').replace('\n', '//'), style = wx.OK | wx.CANCEL | wx.CENTRE ) decision = dlg.ShowModal() if decision != wx.ID_OK: return False epi_name = dlg.GetValue().strip() if epi_name == '': gmGuiHelpers.gm_show_error(_('Cannot save a new problem without a name.'), _('saving progress note')) return False # new unassociated episode new_episode = emr.add_episode(episode_name = epi_name[:45], pk_health_issue = None, is_open = True) if self.__problem is not None: issue = emr.problem2issue(self.__problem) if not gmEMRStructWidgets.move_episode_to_issue(episode = new_episode, target_issue = issue, save_to_backend = True): print("error moving episode to issue") epi_id = new_episode['pk_episode'] else: epi_id = self.__problem['pk_episode'] # set up clinical context in progress note encounter = emr.active_encounter staff_id = gmStaff.gmCurrentProvider()['pk_staff'] clin_ctx = { gmSOAPimporter.soap_bundle_EPISODE_ID_KEY: epi_id, gmSOAPimporter.soap_bundle_ENCOUNTER_ID_KEY: encounter['pk_encounter'], gmSOAPimporter.soap_bundle_STAFF_ID_KEY: staff_id } for line in progress_note: line[gmSOAPimporter.soap_bundle_CLIN_CTX_KEY] = clin_ctx # dump progress note to backend importer = gmSOAPimporter.cSOAPImporter() if not importer.import_soap(progress_note): gmGuiHelpers.gm_show_error(_('Error saving progress note.'), _('saving progress note')) return False # dump embedded data to backend if not self.__embedded_data_holder.save(): gmGuiHelpers.gm_show_error ( _('Error saving embedded data.'), _('saving progress note') ) return False self.__embedded_data_holder.clear() return True
from Gnumed.wxpython import gmGuiHelpers _log = logging.getLogger('gm.perms') #========================================================================= _known_roles = [ 'public access', 'non-clinical access', 'limited clinical access', # currently not in use 'full clinical access', 'admin' # currently not in use ] _curr_staff = gmStaff.gmCurrentProvider() #------------------------------------------------------------------------- def verify_minimum_required_role(minimum_role, activity=None, return_value_on_failure=None, fail_silently=False): if activity is None: activity = _('generic activity') #--------- def _inner_verify_minimum_required_role(original_function): #--------- #@functools.wraps(original_function) def _func_decorated_with_required_role_checking(*args, **kwargs): if _known_roles.index(minimum_role) > _known_roles.index(_curr_staff['role']): _log.info('access denied: %s', activity)
def save(self): """Save data into backend.""" # fill progress_note for import progress_note = [] aoe = '' rfe = '' has_rfe = False soap_lines_contents = self.GetValue() for line_content in soap_lines_contents.values(): if line_content.text.strip() == '': continue progress_note.append({ gmSOAPimporter.soap_bundle_SOAP_CAT_KEY: line_content.data.soap_cat, gmSOAPimporter.soap_bundle_TYPES_KEY: [], # these types need to come from the editor gmSOAPimporter.soap_bundle_TEXT_KEY: line_content.text.rstrip() }) if line_content.data.is_rfe: has_rfe = True rfe += line_content.text.rstrip() if line_content.data.soap_cat == 'a': aoe += line_content.text.rstrip() emr = self.__pat.emr # - new episode, must get name from narrative (or user) if (self.__problem is None) or (self.__problem['type'] == 'issue'): # work out episode name epi_name = '' if len(aoe) != 0: epi_name = aoe else: epi_name = rfe dlg = wx.TextEntryDialog( parent=self, message=_('Enter a descriptive name for this new problem:'), caption=_( 'Creating a problem (episode) to save the notelet under ...' ), defaultValue=epi_name.replace('\r', '//').replace('\n', '//'), style=wx.OK | wx.CANCEL | wx.CENTRE) decision = dlg.ShowModal() if decision != wx.ID_OK: return False epi_name = dlg.GetValue().strip() if epi_name == '': gmGuiHelpers.gm_show_error( _('Cannot save a new problem without a name.'), _('saving progress note')) return False # new unassociated episode new_episode = emr.add_episode(episode_name=epi_name[:45], pk_health_issue=None, is_open=True) if self.__problem is not None: issue = emr.problem2issue(self.__problem) if not gmEMRStructWidgets.move_episode_to_issue( episode=new_episode, target_issue=issue, save_to_backend=True): print("error moving episode to issue") epi_id = new_episode['pk_episode'] else: epi_id = self.__problem['pk_episode'] # set up clinical context in progress note encounter = emr.active_encounter staff_id = gmStaff.gmCurrentProvider()['pk_staff'] clin_ctx = { gmSOAPimporter.soap_bundle_EPISODE_ID_KEY: epi_id, gmSOAPimporter.soap_bundle_ENCOUNTER_ID_KEY: encounter['pk_encounter'], gmSOAPimporter.soap_bundle_STAFF_ID_KEY: staff_id } for line in progress_note: line[gmSOAPimporter.soap_bundle_CLIN_CTX_KEY] = clin_ctx # dump progress note to backend importer = gmSOAPimporter.cSOAPImporter() if not importer.import_soap(progress_note): gmGuiHelpers.gm_show_error(_('Error saving progress note.'), _('saving progress note')) return False # dump embedded data to backend if not self.__embedded_data_holder.save(): gmGuiHelpers.gm_show_error(_('Error saving embedded data.'), _('saving progress note')) return False self.__embedded_data_holder.clear() return True
def test_inbox(): gmStaff.gmCurrentProvider(provider = gmStaff.cStaff()) inbox = cProviderInbox() for msg in inbox.messages: print(msg)