Exemple #1
0
 def sendAlertEmail(self):
     # Send an alert email
     laboratory = self.context.bika_setup.laboratory
     subject = self.request.get('subject')
     to = self.request.get('to')
     body = self.request.get('body')
     body = "<br/>".join(body.split("\r\n"))
     mime_msg = MIMEMultipart('related')
     mime_msg['Subject'] = subject
     mime_msg['From'] = formataddr((encode_header(laboratory.getName()),
                                    laboratory.getEmailAddress()))
     mime_msg['To'] = to
     msg_txt = MIMEText(safe_unicode(body).encode('utf-8'), _subtype='html')
     mime_msg.preamble = 'This is a multi-part MIME message.'
     mime_msg.attach(msg_txt)
     succeed = False
     try:
         host = getToolByName(self.context, 'MailHost')
         host.send(mime_msg.as_string(), immediate=True)
     except Exception, msg:
         ar = self.context.id
         logger.error("Panic level email %s: %s" % (ar, str(msg)))
         message = _('Unable to send an email to alert client '
                     'that some results exceeded the panic levels') \
                                          + (": %s" % str(msg))
         self.addMessage(message, 'warning')
Exemple #2
0
def resolve_client_for_doctor(doctor):
    # If the doctor has a client assigned already, return it directly. We
    # consider that a patient with a client assigned this way has been processed
    # already or does not require any further checks
    client = doctor.getClient()
    if client:
        return client

    # Try to infer the client from Samples or Batches
    batches = doctor.getBatches(full_objects=True)
    client_uids = map(lambda b: b.getClientUID(), batches)
    client_uids.extend(map(lambda s: s.getClientUID, doctor.getSamples()))
    client_uids = filter(None, list(set(client_uids)))
    if not client_uids:
        # This Doctor has no batch/sample assigned
        return None

    clients = map(api.get_object_by_uid, client_uids)
    internals = map(is_internal_client, clients)
    if all(internals):
        # All clients are internal, return the first one
        return clients[0]
    else:
        # OOps, we have a problem here. This Doctor is assigned to samples and
        # batches that belong to different types of client!
        logger.error(
            "Doctor {} is assigned to clients from different types".format(
                api.get_id(doctor), repr(clients)))
        return None
Exemple #3
0
def install_senaite_panic(portal):
    """Install the senaite.panic addon
    """
    qi = api.get_tool("portal_quickinstaller")
    profile = "senaite.panic"
    if profile not in qi.listInstallableProfiles():
        logger.error(
            "Profile '{}' not found. Forgot to run buildout?".format(profile))
        return
    if qi.isProductInstalled(profile):
        logger.info("'{}' is installed".format(profile))
        return
    qi.installProduct(profile)
Exemple #4
0
    def Import(self):
        folder = self.context.patients
        rows = self.get_rows(3)
        for row in rows:
            if not row['Firstname'] or not row['PrimaryReferrer']:
                continue
            pc = getToolByName(self.context, 'portal_catalog')
            client = pc(portal_type='Client', Title=row['PrimaryReferrer'])
            if len(client) == 0:
                error = "Primary referrer invalid: '%s'. Patient '%s %s' will not be uploaded"
                logger.error(error, row['PrimaryReferrer'], row['Firstname'], row.get('Surname', ''))
                continue

            client = client[0].getObject()

            # Getting an existing ethnicity
            bsc = getToolByName(self.context, 'bika_setup_catalog')
            ethnicity = bsc(portal_type='Ethnicity', Title=row.get('Ethnicity', ''))
            if len(ethnicity) == 0:
                raise IndexError("Invalid ethnicity: '%s'" % row['Ethnicity'])
            ethnicity = ethnicity[0].getObject()

            _id = folder.invokeFactory('Patient', id=tmpID())
            obj = folder[_id]
            obj.unmarkCreationFlag()
            renameAfterCreation(obj)
            Fullname = (row['Firstname'] + " " + row.get('Surname', '')).strip()
            obj.edit(PatientID=row.get('PatientID'),
                     title=Fullname,
                     ClientPatientID = row.get('ClientPatientID', ''),
                     Salutation = row.get('Salutation', ''),
                     Firstname = row.get('Firstname', ''),
                     Surname = row.get('Surname', ''),
                     PrimaryReferrer = client.UID(),
                     Gender = row.get('Gender', 'dk'),
                     Age = row.get('Age', ''),
                     BirthDate = row.get('BirthDate', ''),
                     BirthDateEstimated =self.to_bool(row.get('BirthDateEstimated','False')),
                     BirthPlace = row.get('BirthPlace', ''),
                     # TODO Ethnicity_Obj -> Ethnicity on health v319
                     Ethnicity_Obj=ethnicity.UID(),
                     Citizenship =row.get('Citizenship', ''),
                     MothersName = row.get('MothersName', ''),
                     CivilStatus =row.get('CivilStatus', ''),
                     Anonymous = self.to_bool(row.get('Anonymous','False'))
                     )
            self.fill_contactfields(row, obj)
            self.fill_addressfields(row, obj)
            if 'Photo' in row and row['Photo']:
                try:
                    path = resource_filename(self.dataset_project,
                                             "setupdata/%s/%s" \
                                             % (self.dataset_name, row['Photo']))
                    file_data = open(path, "rb").read() if os.path.isfile(path) \
                        else open(path+'.jpg', "rb").read()
                    obj.setPhoto(file_data)
                except:
                    logger.error("Unable to load Photo %s"%row['Photo'])

            if 'Feature' in row and row['Feature']:
                try:
                    path = resource_filename(self.dataset_project,
                                             "setupdata/%s/%s" \
                                             % (self.dataset_name, row['Feature']))
                    file_data = open(path, "rb").read() if os.path.isfile(path) \
                        else open(path+'.pdf', "rb").read()
                    obj.setFeature(file_data)
                except:
                    logger.error("Unable to load Feature %s"%row['Feature'])

            obj.unmarkCreationFlag()
            transaction.savepoint(optimistic=True)
            if row.get('PatientID'):
                # To maintain the patient spreadsheet's IDs, we cannot do a 'renameaftercreation()'
                if obj.getPatientID() != row.get('PatientID'):
                    transaction.savepoint(optimistic=True)
                    obj.aq_inner.aq_parent.manage_renameObject(obj.id, row.get('PatientID'))
            else:
                renameAfterCreation(obj)
Exemple #5
0
    def __call__(self):
        # Do generic bika.lims stuff
        _AnalysisRequestWorkflowAction.__call__(self)
        # Do bika-health specific actions when submit
        action = _AnalysisRequestWorkflowAction._get_form_workflow_action(self)
        addPortalMessage = self.context.plone_utils.addPortalMessage
        if action[0] == 'submit' and isActive(self.context):
            inpanicanalyses = []
            workflow = getToolByName(self.context, 'portal_workflow')
            translate = self.context.translate
            rc = getToolByName(self.context, REFERENCE_CATALOG)
            uc = getToolByName(self.context, 'uid_catalog')
            # retrieve the results from database and check if
            # the values are exceeding panic levels
            alerts = {}
            for uid in self.request.form.get('Result', [{}])[0].keys():
                analysis = rc.lookupObject(uid)
                analysis = analysis.getObject() if hasattr(analysis, 'getObject') else analysis
                if not analysis:
                    continue
                astate = workflow.getInfoFor(analysis, 'review_state')
                if astate == 'retracted':
                    continue
                alerts.update(ResultOutOfRange(analysis)())
            if alerts:
                message = translate(_('Some results exceeded the '
                                      'panic levels that may '
                                      'indicate an imminent '
                                      'life-threatening condition'
                                      ))
                addPortalMessage(message, 'warning')
                self.request.response.redirect(self.context.absolute_url())

                # If panic levels alert email enabled, send an email to
                # labmanagers
                bs = self.context.bika_setup
                if hasattr(bs, 'getEnablePanicAlert') \
                        and bs.getEnablePanicAlert():
                    laboratory = self.context.bika_setup.laboratory
                    lab_address = "<br/>".join(laboratory.getPrintAddress())
                    managers = self.context.portal_groups.getGroupMembers('LabManagers')
                    mime_msg = MIMEMultipart('related')
                    mime_msg['Subject'] = _("Panic alert")
                    mime_msg['From'] = formataddr(
                        (encode_header(laboratory.getName()),
                         laboratory.getEmailAddress()))
                    to = []
                    for manager in managers:
                        user = self.portal.acl_users.getUser(manager)
                        uemail = user.getProperty('email')
                        ufull = user.getProperty('fullname')
                        to.append(formataddr((encode_header(ufull), uemail)))
                    mime_msg['To'] = ','.join(to)
                    strans = []
                    ars = {}
                    for analysis_uid, alertlist in alerts:
                        analysis = uc(analysis_uid).getObject()
                        for alert in alertlist:
                            ars[analysis.aq_parent.Title()] = 1
                            strans.append("- {0}, {1}: {2}".format(
                                          analysis.Title(),
                                          translate(_("Result")),
                                          analysis.getResult()))
                    ars = ", ".join(ars.keys())
                    stran = "<br/>".join(strans)
                    text = translate(_(
                        "Some results from ${items} exceeded the panic levels "
                        "that may indicate an imminent life-threatening "
                        "condition: <br/><br/>{analysisresults}<br/><br/>"
                        "<b>Please, check the Analysis Request if you "
                        "want to re-test the analysis or immediately "
                        "alert the client.</b><br/><br/>{lab_address}",
                        mapping={'items': ars,
                                 'analysisresults': stran,
                                 'lab_address': lab_address}))
                    msg_txt = MIMEText(safe_unicode(text).encode('utf-8'),
                                       _subtype='html')
                    mime_msg.preamble = 'This is a multi-part MIME message.'
                    mime_msg.attach(msg_txt)
                    try:
                        host = getToolByName(self.context, 'MailHost')
                        host.send(mime_msg.as_string(), immediate=True)
                    except Exception as msg:
                        ar = inpanicanalyses[0].getRequestID()
                        logger.error("Panic level email %s: %s" %
                                     (ar, str(msg)))
                        message = translate(
                            _('Unable to send an email to alert lab '
                              'managers that some analyses exceeded the '
                              'panic levels') + (": %s" % str(msg)))
                        addPortalMessage(message, 'warning')