def __call__(self):
        form = self.request.form
        plone.protect.CheckAuthenticator(form)
        workflow = getToolByName(self.context, 'portal_workflow')
        rc = getToolByName(self.context, REFERENCE_CATALOG)
        action, came_from = WorkflowAction._get_form_workflow_action(self)

        if action == 'reassign':
            selected_worksheets = WorkflowAction._get_selected_items(self)
            selected_worksheet_uids = selected_worksheets.keys()

            if selected_worksheets:
                changes = False
                for uid in selected_worksheet_uids:
                    worksheet = selected_worksheets[uid]
                    # Double-check the state first
                    if workflow.getInfoFor(worksheet, 'review_state') == 'open':
                        worksheet.setAnalyst(form['Analyst'][0][uid])
                        changes = True

                if changes:
                    message = self.context.translate(PMF('Changes saved.'))
                    self.context.plone_utils.addPortalMessage(message, 'info')

            self.destination_url = self.request.get_header("referer",
                                   self.context.absolute_url())
            self.request.response.redirect(self.destination_url)
        else:
            # default bika_listing.py/WorkflowAction for other transitions
            WorkflowAction.__call__(self)
Esempio n. 2
0
    def __call__(self):
        form = self.request.form
        plone.protect.CheckAuthenticator(form)
        action, came_from = WorkflowAction._get_form_workflow_action(self)

        if action == 'submit':

            objects = WorkflowAction._get_selected_items(self)
            if not objects:
                message = self.context.translate(
                    _b("No analyses have been selected"))
                self.context.plone_utils.addPortalMessage(message, 'info')
                self.destination_url = self.context.absolute_url() + \
                    "/batchbook"
                self.request.response.redirect(self.destination_url)
                return

            for ar_uid, ar in objects.items():
                for analysis in ar.getAnalyses(full_objects=True):
                    kw = analysis.getKeyword()
                    values = form.get(kw)
                    analysis.setResult(values[0][ar_uid])
                    if values[0][ar_uid]:
                        doActionFor(analysis, 'submit')

            message = self.context.translate(_p("Changes saved."))
            self.context.plone_utils.addPortalMessage(message, 'info')
            self.request.response.redirect(self.request.get('URL'))
            return

        else:

            WorkflowAction.__call__(self)
Esempio n. 3
0
    def workflow_action_save_analyses_button(self):
        form = self.request.form
        workflow = getToolByName(self.context, 'portal_workflow')
        action, came_from = WorkflowAction._get_form_workflow_action(self)
        # AR Manage Analyses: save Analyses
        ar = self.context
        sample = ar.getSample()
        objects = WorkflowAction._get_selected_items(self)
        if not objects:
            message = _("No analyses have been selected")
            self.context.plone_utils.addPortalMessage(message, 'info')
            self.destination_url = self.context.absolute_url() + "/analyses"
            self.request.response.redirect(self.destination_url)
            return
        Analyses = objects.keys()
        prices = form.get("Price", [None])[0]
        specs = {}
        if form.get("min", None):
            for service_uid in Analyses:
                specs[service_uid] = {
                    "min": form["min"][0][service_uid],
                    "max": form["max"][0][service_uid],
                    "error": form["error"][0][service_uid]
                }
        else:
            for service_uid in Analyses:
                specs[service_uid] = {"min": "", "max": "", "error": ""}
        new = ar.setAnalyses(Analyses, prices=prices, specs=specs)
        # link analyses and partitions
        # If Bika Setup > Analyses > 'Display individual sample
        # partitions' is checked, no Partitions available.
        # https://github.com/bikalabs/Bika-LIMS/issues/1030
        if 'Partition' in form:
            for service_uid, service in objects.items():
                part_id = form['Partition'][0][service_uid]
                part = sample[part_id]
                analysis = ar[service.getKeyword()]
                analysis.setSamplePartition(part)
                analysis.reindexObject()
        if new:
            for analysis in new:
                # if the AR has progressed past sample_received, we need to bring it back.
                ar_state = workflow.getInfoFor(ar, 'review_state')
                if ar_state in ('attachment_due', 'to_be_verified'):
                    # Apply to AR only; we don't want this transition to cascade.
                    ar.REQUEST['workflow_skiplist'].append(
                        "retract all analyses")
                    workflow.doActionFor(ar, 'retract')
                    ar.REQUEST['workflow_skiplist'].remove(
                        "retract all analyses")
                    ar_state = workflow.getInfoFor(ar, 'review_state')
                # Then we need to forward new analyses state
                analysis.updateDueDate()
                changeWorkflowState(analysis, 'bika_analysis_workflow',
                                    ar_state)

        message = PMF("Changes saved.")
        self.context.plone_utils.addPortalMessage(message, 'info')
        self.destination_url = self.context.absolute_url()
        self.request.response.redirect(self.destination_url)
Esempio n. 4
0
    def __call__(self):
        form = self.request.form
        CheckAuthenticator(form)
        analysis_uids = form.get("uids", [])
        if not analysis_uids:
            self.destination_url = self.context.absolute_url()
            self.request.response.redirect(self.destination_url)
            return

        action, came_from = WorkflowAction._get_form_workflow_action(self)

        if action == "submit":
            # Submit the form. Saves the results, methods, etc.
            # Calls to its parent class AnalysesWorkflowAction
            self.workflow_action_submit()

        elif action == "assign":
            # Assign the analyses
            self.do_assign(analysis_uids)

        elif action == "unassign":
            # Unassign analyses
            self.do_unassign(analysis_uids)

        elif action == "verify":
            # default bika_listing.py/WorkflowAction, but then go to view
            # screen.
            self.destination_url = self.context.absolute_url()
            return self.workflow_action_default(
                action="verify", came_from=came_from)
        else:
            # default bika_listing.py/WorkflowAction for other transitions
            WorkflowAction.__call__(self)
Esempio n. 5
0
    def __call__(self):
        form = self.request.form
        plone.protect.CheckAuthenticator(form)
        workflow = getToolByName(self.context, 'portal_workflow')
        rc = getToolByName(self.context, REFERENCE_CATALOG)
        action, came_from = WorkflowAction._get_form_workflow_action(self)

        if action == 'reassign':
            selected_worksheets = WorkflowAction._get_selected_items(self)
            selected_worksheet_uids = selected_worksheets.keys()

            if selected_worksheets:
                changes = False
                for uid in selected_worksheet_uids:
                    worksheet = selected_worksheets[uid]
                    # Double-check the state first
                    if workflow.getInfoFor(worksheet,
                                           'review_state') == 'open':
                        worksheet.setAnalyst(form['Analyst'][0][uid])
                        changes = True

                if changes:
                    message = self.context.translation_service.translate(
                        PMF('Changes saved.'))
                    self.context.plone_utils.addPortalMessage(message, 'info')

            self.destination_url = self.request.get_header(
                "referer", self.context.absolute_url())
            self.request.response.redirect(self.destination_url)
        else:
            # default bika_listing.py/WorkflowAction for other transitions
            WorkflowAction.__call__(self)
Esempio n. 6
0
    def workflow_action_preserve(self):
        form = self.request.form
        workflow = getToolByName(self.context, 'portal_workflow')
        action, came_from = WorkflowAction._get_form_workflow_action(self)
        checkPermission = self.context.portal_membership.checkPermission
        # Partition Preservation
        # the partition table shown in AR and Sample views sends it's
        # action button submits here.
        objects = WorkflowAction._get_selected_items(self)
        transitioned = []
        incomplete = []
        for obj_uid, obj in objects.items():
            part = obj
            # can't transition inactive items
            if workflow.getInfoFor(part, 'inactive_state', '') == 'inactive':
                continue
            if not checkPermission(PreserveSample, part):
                continue
            # grab this object's Preserver and DatePreserved from the form
            Preserver = form['getPreserver'][0][obj_uid].strip()
            Preserver = Preserver and Preserver or ''
            DatePreserved = form['getDatePreserved'][0][obj_uid].strip()
            DatePreserved = DatePreserved and DateTime(DatePreserved) or ''
            # write them to the sample
            part.setPreserver(Preserver)
            part.setDatePreserved(DatePreserved)
            # transition the object if both values are present
            if Preserver and DatePreserved:
                workflow.doActionFor(part, action)
                transitioned.append(part.id)
            else:
                incomplete.append(part.id)
            part.reindexObject()
            part.aq_parent.reindexObject()
        message = None
        if len(transitioned) > 1:
            message = _('${items} are waiting to be received.',
                        mapping={'items': safe_unicode(', '.join(transitioned))})
            self.context.plone_utils.addPortalMessage(message, 'info')
        elif len(transitioned) == 1:
            message = _('${item} is waiting to be received.',
                        mapping={'item': safe_unicode(', '.join(transitioned))})
            self.context.plone_utils.addPortalMessage(message, 'info')
        if not message:
            message = _('No changes made.')
            self.context.plone_utils.addPortalMessage(message, 'info')

        if len(incomplete) > 1:
            message = _('${items} are missing Preserver or Date Preserved',
                        mapping={'items': safe_unicode(', '.join(incomplete))})
            self.context.plone_utils.addPortalMessage(message, 'error')
        elif len(incomplete) == 1:
            message = _('${item} is missing Preserver or Preservation Date',
                        mapping={'item': safe_unicode(', '.join(incomplete))})
            self.context.plone_utils.addPortalMessage(message, 'error')

        self.destination_url = self.request.get_header("referer",
                               self.context.absolute_url())
        self.request.response.redirect(self.destination_url)
Esempio n. 7
0
    def workflow_action_preserve(self):
        form = self.request.form
        workflow = getToolByName(self.context, 'portal_workflow')
        action, came_from = WorkflowAction._get_form_workflow_action(self)
        checkPermission = self.context.portal_membership.checkPermission
        # Partition Preservation
        # the partition table shown in AR and Sample views sends it's
        # action button submits here.
        objects = WorkflowAction._get_selected_items(self)
        transitioned = []
        incomplete = []
        for obj_uid, obj in objects.items():
            part = obj
            # can't transition inactive items
            if workflow.getInfoFor(part, 'inactive_state', '') == 'inactive':
                continue
            if not checkPermission(PreserveSample, part):
                continue
            # grab this object's Preserver and DatePreserved from the form
            Preserver = form['getPreserver'][0][obj_uid].strip()
            Preserver = Preserver and Preserver or ''
            DatePreserved = form['getDatePreserved'][0][obj_uid].strip()
            DatePreserved = DatePreserved and DateTime(DatePreserved) or ''
            # write them to the sample
            part.setPreserver(Preserver)
            part.setDatePreserved(DatePreserved)
            # transition the object if both values are present
            if Preserver and DatePreserved:
                workflow.doActionFor(part, action)
                transitioned.append(part.id)
            else:
                incomplete.append(part.id)
            part.reindexObject()
            part.aq_parent.reindexObject()
        message = None
        if len(transitioned) > 1:
            message = _('${items} are waiting to be received.',
                        mapping={'items': safe_unicode(', '.join(transitioned))})
            self.context.plone_utils.addPortalMessage(message, 'info')
        elif len(transitioned) == 1:
            message = _('${item} is waiting to be received.',
                        mapping={'item': safe_unicode(', '.join(transitioned))})
            self.context.plone_utils.addPortalMessage(message, 'info')
        if not message:
            message = _('No changes made.')
            self.context.plone_utils.addPortalMessage(message, 'info')

        if len(incomplete) > 1:
            message = _('${items} are missing Preserver or Date Preserved',
                        mapping={'items': safe_unicode(', '.join(incomplete))})
            self.context.plone_utils.addPortalMessage(message, 'error')
        elif len(incomplete) == 1:
            message = _('${item} is missing Preserver or Preservation Date',
                        mapping={'item': safe_unicode(', '.join(incomplete))})
            self.context.plone_utils.addPortalMessage(message, 'error')

        self.destination_url = self.request.get_header("referer",
                               self.context.absolute_url())
        self.request.response.redirect(self.destination_url)
Esempio n. 8
0
 def workflow_action_receive(self):
     # default bika_listing.py/WorkflowAction, but then
     # print automatic labels.
     if 'receive' in self.context.bika_setup.getAutoPrintLabels():
         size = self.context.bika_setup.getAutoLabelSize()
         q = "/sticker?size=%s&items=%s" % (size, self.context.getId())
         self.destination_url = self.context.absolute_url() + q
     WorkflowAction.__call__(self)
Esempio n. 9
0
 def __call__(self):
     form = self.request.form
     plone.protect.CheckAuthenticator(form)
     action, _ = WorkflowAction._get_form_workflow_action(self)
     if action == 'receive' and 'Type' in form:
         BiospecimenWorkflowAction.__call__(self)
     else:
         WorkflowAction.__call__(self)
Esempio n. 10
0
 def workflow_action_receive(self):
     # default bika_listing.py/WorkflowAction, but then
     # print automatic labels.
     if 'receive' in self.context.bika_setup.getAutoPrintLabels():
         size = self.context.bika_setup.getAutoLabelSize()
         q = "/sticker?size=%s&items=%s" % (size, self.context.getId())
         self.destination_url = self.context.absolute_url() + q
     WorkflowAction.__call__(self)
Esempio n. 11
0
    def __call__(self):
        form = self.request.form
        plone.protect.CheckAuthenticator(form)
        workflow = getToolByName(self.context, 'portal_workflow')
        rc = getToolByName(self.context, REFERENCE_CATALOG)
        uc = getToolByName(self.context, 'uid_catalog')
        action, came_from = WorkflowAction._get_form_workflow_action(self)

        if action == 'duplicate':
            selected_services = WorkflowAction._get_selected_items(self)

            ## Create a copy of the selected services
            folder = self.context.bika_setup.bika_analysisservices
            created = []
            for service in selected_services.values():
                _id = folder.invokeFactory('AnalysisService', id = 'tmp')
                dup = folder[_id]
                dup.setTitle('%s (copy)' % service.Title())
                _id = renameAfterCreation(dup)
                dup.edit(
                    description = service.Description(),
                    PointOfCapture = service.getPointOfCapture(),
                    ReportDryMatter = service.getReportDryMatter(),
                    Unit = service.getUnit(),
                    Precision = service.getPrecision(),
                    Price = service.getPrice(),
                    CorporatePrice = service.getCorporatePrice(),
                    VAT = service.getVAT(),
                    Calculation = service.getCalculation(),
                    Instrument = service.getInstrument(),
                    MaxTimeAllowed = service.getMaxTimeAllowed(),
                    DuplicateVariation = service.getDuplicateVariation(),
                    Category = service.getCategory(),
                    Department = service.getDepartment(),
                    Accredited = service.getAccredited(),
                    Uncertainties = service.getUncertainties(),
                    ResultOptions = service.getResultOptions()
                )
                created.append(_id)

            if len(created) > 1:
                message = self.context.translation_service.translate(
                    _('Services ${services} were successfully created.',
                      mapping = {'services': ', '.join(created)}))
                self.destination_url = self.request.get_header("referer",
                                                               self.context.absolute_url())
            else:
                message = self.context.translation_service.translate(
                    _('Analysis request ${service} was successfully created.',
                    mapping = {'service': ', '.join(created)}))
                self.destination_url = dup.absolute_url() + "/base_edit"

            self.context.plone_utils.addPortalMessage(message, 'info')
            self.request.response.redirect(self.destination_url)

        else:
            # default bika_listing.py/WorkflowAction for other transitions
            WorkflowAction.__call__(self)
Esempio n. 12
0
    def workflow_action_save_analyses_button(self):
        form = self.request.form
        workflow = getToolByName(self.context, 'portal_workflow')
        action, came_from = WorkflowAction._get_form_workflow_action(self)
        # AR Manage Analyses: save Analyses
        ar = self.context
        sample = ar.getSample()
        objects = WorkflowAction._get_selected_items(self)
        if not objects:
            message = _("No analyses have been selected")
            self.context.plone_utils.addPortalMessage(message, 'info')
            self.destination_url = self.context.absolute_url() + "/analyses"
            self.request.response.redirect(self.destination_url)
            return
        Analyses = objects.keys()
        prices = form.get("Price", [None])[0]
        specs = {}
        if form.get("min", None):
            for service_uid in Analyses:
                specs[service_uid] = {
                    "min": form["min"][0][service_uid],
                    "max": form["max"][0][service_uid],
                    "error": form["error"][0][service_uid]
                }
        else:
            for service_uid in Analyses:
                specs[service_uid] = {"min": "", "max": "", "error": ""}
        new = ar.setAnalyses(Analyses, prices=prices, specs=specs)
        # link analyses and partitions
        # If Bika Setup > Analyses > 'Display individual sample
        # partitions' is checked, no Partitions available.
        # https://github.com/bikalabs/Bika-LIMS/issues/1030
        if 'Partition' in form:
            for service_uid, service in objects.items():
                part_id = form['Partition'][0][service_uid]
                part = sample[part_id]
                analysis = ar[service.getKeyword()]
                analysis.setSamplePartition(part)
                analysis.reindexObject()
        if new:
            for analysis in new:
                # if the AR has progressed past sample_received, we need to bring it back.
                ar_state = workflow.getInfoFor(ar, 'review_state')
                if ar_state in ('attachment_due', 'to_be_verified'):
                    # Apply to AR only; we don't want this transition to cascade.
                    ar.REQUEST['workflow_skiplist'].append("retract all analyses")
                    workflow.doActionFor(ar, 'retract')
                    ar.REQUEST['workflow_skiplist'].remove("retract all analyses")
                    ar_state = workflow.getInfoFor(ar, 'review_state')
                # Then we need to forward new analyses state
                analysis.updateDueDate()
                changeWorkflowState(analysis, 'bika_analysis_workflow', ar_state)

        message = PMF("Changes saved.")
        self.context.plone_utils.addPortalMessage(message, 'info')
        self.destination_url = self.context.absolute_url()
        self.request.response.redirect(self.destination_url)
Esempio n. 13
0
    def __call__(self):
        form = self.request.form
        plone.protect.CheckAuthenticator(form)
        workflow = getToolByName(self.context, 'portal_workflow')
        rc = getToolByName(self.context, REFERENCE_CATALOG)
        uc = getToolByName(self.context, 'uid_catalog')
        action, came_from = WorkflowAction._get_form_workflow_action(self)

        if action == 'duplicate':
            selected_services = WorkflowAction._get_selected_items(self)

            ## Create a copy of the selected services
            folder = self.context.bika_setup.bika_analysisservices
            created = []
            for service in selected_services.values():
                _id = folder.invokeFactory('AnalysisService', id='tmp')
                dup = folder[_id]
                dup.setTitle('%s (copy)' % service.Title())
                _id = renameAfterCreation(dup)
                dup.edit(description=service.Description(),
                         PointOfCapture=service.getPointOfCapture(),
                         ReportDryMatter=service.getReportDryMatter(),
                         Unit=service.getUnit(),
                         Precision=service.getPrecision(),
                         Price=service.getPrice(),
                         CorporatePrice=service.getCorporatePrice(),
                         VAT=service.getVAT(),
                         Calculation=service.getCalculation(),
                         Instrument=service.getInstrument(),
                         MaxTimeAllowed=service.getMaxTimeAllowed(),
                         DuplicateVariation=service.getDuplicateVariation(),
                         Category=service.getCategory(),
                         Department=service.getDepartment(),
                         Accredited=service.getAccredited(),
                         Uncertainties=service.getUncertainties(),
                         ResultOptions=service.getResultOptions())
                created.append(_id)

            if len(created) > 1:
                message = self.context.translation_service.translate(
                    _('Services ${services} were successfully created.',
                      mapping={'services': ', '.join(created)}))
                self.destination_url = self.request.get_header(
                    "referer", self.context.absolute_url())
            else:
                message = self.context.translation_service.translate(
                    _('Analysis request ${service} was successfully created.',
                      mapping={'service': ', '.join(created)}))
                self.destination_url = dup.absolute_url() + "/base_edit"

            self.context.plone_utils.addPortalMessage(message, 'info')
            self.request.response.redirect(self.destination_url)

        else:
            # default bika_listing.py/WorkflowAction for other transitions
            WorkflowAction.__call__(self)
Esempio n. 14
0
 def __call__(self):
     form = self.request.form
     plone.protect.CheckAuthenticator(form)
     action, _ = WorkflowAction._get_form_workflow_action(self)
     if action == 'receive' and 'Type' in form:
         BiospecimenWorkflowAction.__call__(self)
     elif action == 'receive' and 'AliquotType' in form:
         AliquotWorkflowAction.__call__(self)
     else:
         WorkflowAction.__call__(self)
Esempio n. 15
0
    def __call__(self):
        form = self.request.form
        plone.protect.CheckAuthenticator(form)
        action, _ = WorkflowAction._get_form_workflow_action(self)
        if type(action) in (list, tuple):
            action = action[0]

        # Call out to the workflow action method
        method_name = 'workflow_action_' + action
        method = getattr(self, method_name, False)
        if method:
            method()
        else:
            WorkflowAction.__call__(self)
Esempio n. 16
0
    def __call__(self):
        form = self.request.form
        plone.protect.CheckAuthenticator(form)
        action, _ = WorkflowAction._get_form_workflow_action(self)
        if type(action) in (list, tuple):
            action = action[0]

        # Call out to the workflow action method
        method_name = 'workflow_action_' + action
        method = getattr(self, method_name, False)
        if method:
            method()
        else:
            WorkflowAction.__call__(self)
Esempio n. 17
0
 def workflow_action_keep(self):
     workflow = getToolByName(self.context, 'portal_workflow')
     action, came_from = WorkflowAction._get_form_workflow_action(self)
     objects = WorkflowAction._get_selected_items(self)
     for obj_uid, obj in objects.items():
         pitem = obj
         old_d = pitem.Description()
         new_message = "\n*** Restored in Inventory at " + time.strftime("%c") + " ***\n"
         pitem.setDescription(old_d + new_message)
         pitem.reindexObject()
         workflow.doActionFor(pitem, action)
     message = PMF("Changes saved.")
     self.context.plone_utils.addPortalMessage(message, 'info')
     self.destination_url = self.context.absolute_url()
     self.request.response.redirect(self.destination_url)
Esempio n. 18
0
 def __call__(self):
     form = self.request.form
     plone.protect.CheckAuthenticator(form)
     action, came_from = WorkflowAction._get_form_workflow_action(self)
     if type(action) in (list, tuple):
         action = action[0]
     if type(came_from) in (list, tuple):
         came_from = came_from[0]
     # Call out to the workflow action method
     # Use default bika_listing.py/WorkflowAction for other transitions
     method_name = 'workflow_action_' + action
     method = getattr(self, method_name, False)
     if method:
         method()
     else:
         WorkflowAction.__call__(self)
Esempio n. 19
0
    def workflow_action_sample_due(self):
        form = self.request.form
        selected_biospecimens = WorkflowAction._get_selected_items(self)
        biospecimens = []
        for uid in selected_biospecimens.keys():
            if not form['Barcode'][0][uid] or \
                    not form['Type'][0][uid]:
                continue
            try:
                obj = selected_biospecimens.get(uid, None)
                obj.getField('Barcode').set(obj, form['Barcode'][0][uid])
                obj.getField('SampleType').set(obj, form['Type'][0][uid])
                obj.setId(form['Barcode'][0][uid])
                obj.edit(SampleID=obj.getId())
                obj.reindexObject()
                biospecimens.append(obj)
            except ReferenceException:
                continue
        message = PMF("Changes saved.")
        self.context.plone_utils.addPortalMessage(message, 'info')

        for biospecimen in biospecimens:
            doActionFor(biospecimen, 'sample_due')
            for partition in biospecimen.objectValues('SamplePartition'):
                doActionFor(partition, 'sample_due')

        self.destination_url = self.context.absolute_url()
        if form['portal_type'] == 'Kit' or \
                form['portal_type'] == 'SampleBatch':
            self.destination_url = form['view_url']

        self.destination_url += '/biospecimens'
        self.request.response.redirect(self.destination_url)
Esempio n. 20
0
 def workflow_action_verify(self):
     # default bika_listing.py/WorkflowAction, but then go to view screen.
     self.destination_url = self.context.absolute_url()
     action, came_from = WorkflowAction._get_form_workflow_action(self)
     if type(came_from) in (list, tuple):
         came_from = came_from[0]
     return self.workflow_action_default(action="verify", came_from=came_from)
Esempio n. 21
0
    def workflow_action_deactivate(self):
        context = self.context
        selected_elements = WorkflowAction._get_selected_items(self)
        catalog = getToolByName(self, 'portal_catalog')
        # import pdb;pdb.set_trace()
        for uid in selected_elements.keys():
            try:
                obj = selected_elements.get(uid, None)
                units = []
                if obj.portal_type in ['ManagedStorage', 'UnmanagedStorage']:
                    units.append(obj)
                else:
                    unit_path = '/'.join(obj.getPhysicalPath())
                    brains = catalog(portal_type=[
                        'StorageUnit', 'UnmanagedStorage', 'ManagedStorage'
                    ],
                                     path={
                                         'query': unit_path,
                                         'level': 0
                                     })
                    units += [brain.getObject() for brain in brains]
                for unit in units:
                    review_state = context.portal_workflow.getInfoFor(
                        unit, 'inactive_state')
                    if review_state == 'active':
                        context.portal_workflow.doActionFor(unit, 'deactivate')

            except ReferenceException:
                pass

        self.request.response.redirect(context.absolute_url())
Esempio n. 22
0
 def workflow_action_verify(self):
     # default bika_listing.py/WorkflowAction, but then go to view screen.
     self.destination_url = self.context.absolute_url()
     action, came_from = WorkflowAction._get_form_workflow_action(self)
     if type(came_from) in (list, tuple):
         came_from = came_from[0]
     return self.workflow_action_default(action='verify', came_from=came_from)
Esempio n. 23
0
    def workflow_action_aliquot_receive(self):
        form = self.request.form
        selected_aliquots = WorkflowAction._get_selected_items(self)
        aliquots = []
        for uid in selected_aliquots.keys():
            if not form["AliquotType"][0][uid] or not form["Volume"][0][uid] or not form["Unit"][0][uid]:
                continue
            try:
                aliquot = selected_aliquots.get(uid, None)
                aliquot.getField("SampleType").set(aliquot, form["AliquotType"][0][uid])
                aliquot.getField("Volume").set(aliquot, form["Volume"][0][uid])
                unit = "ml"
                for u in VOLUME_UNITS:
                    if u["ResultValue"] == form["Unit"][0][uid]:
                        unit = u["ResultText"]
                aliquot.getField("Unit").set(aliquot, unit)
                aliquot.reindexObject()
                aliquots.append(aliquot)
            except ReferenceException:
                continue

        message = PMF("Changes saved.")
        self.context.plone_utils.addPortalMessage(message, "info")

        for aliquot in aliquots:
            doActionFor(aliquot, "receive")
            for partition in aliquot.objectValues("SamplePartition"):
                doActionFor(partition, "receive")

        self.destination_url = self.context.absolute_url()
        if self.context.portal_type == "Project":
            self.destination_url += "/aliquots"
        self.request.response.redirect(self.destination_url)
Esempio n. 24
0
 def __call__(self):
     form = self.request.form
     plone.protect.CheckAuthenticator(form)
     action, came_from = WorkflowAction._get_form_workflow_action(self)
     if type(action) in (list, tuple):
         action = action[0]
     if type(came_from) in (list, tuple):
         came_from = came_from[0]
     # Call out to the workflow action method
     # Use default bika_listing.py/WorkflowAction for other transitions
     method_name = 'workflow_action_' + action
     method = getattr(self, method_name, False)
     if method:
         method()
     else:
         WorkflowAction.__call__(self)
Esempio n. 25
0
    def workflow_action_schedule_sampling(self):
        """
        This function prevent the transition if the fields "SamplingDate"
        and "ScheduledSamplingSampler" are uncompleted.
        :return: bool
        """
        from bika.lims.utils.workflow import schedulesampling

        message = "Not expected transition."
        # In Samples Folder we have to get each selected item
        if interfaces.ISamplesFolder.providedBy(self.context):
            select_objs = WorkflowAction._get_selected_items(self)
            message = _("Transition done.")
            for key in select_objs.keys():
                sample = select_objs[key]
                # Getting the sampler
                sch_sampl = (
                    self.request.form.get("getScheduledSamplingSampler", None)[0].get(key)
                    if self.request.form.get("getScheduledSamplingSampler", None)
                    else ""
                )
                # Getting the date
                sampl_date = (
                    self.request.form.get("getSamplingDate", None)[0].get(key)
                    if self.request.form.get("getSamplingDate", None)
                    else ""
                )
                # Setting both values
                sample.setScheduledSamplingSampler(sch_sampl)
                sample.setSamplingDate(sampl_date)
                # Transitioning the sample
                success, errmsg = schedulesampling.doTransition(sample)
                if errmsg == "missing":
                    message = _(
                        "'Sampling date' and 'Define the Sampler for the"
                        + " scheduled sampling' must be completed and saved "
                        + "in order to schedule a sampling. Element: %s" % sample.getId()
                    )
                elif errmsg == "cant_trans":
                    message = _("The item %s can't be transitioned." % sample.getId())
                else:
                    message = _("Transition done.")
                self.context.plone_utils.addPortalMessage(message, "info")
        else:
            success, errmsg = schedulesampling.doTransition(self.context)
            if errmsg == "missing":
                message = _(
                    "'Sampling date' and 'Define the Sampler for the"
                    + " scheduled sampling' must be completed and saved in "
                    + "order to schedule a sampling."
                )
            elif errmsg == "cant_trans":
                message = _("The item can't be transitioned.")
            else:
                message = _("Transition done.")
            self.context.plone_utils.addPortalMessage(message, "info")
        # Reload the page in order to show the portal message
        self.request.response.redirect(self.context.absolute_url())
        return success
Esempio n. 26
0
    def __call__(self):
        form = self.request.form
        plone.protect.CheckAuthenticator(form)
        workflow = getToolByName(self.context, 'portal_workflow')
        rc = getToolByName(self.context, REFERENCE_CATALOG)
        action, came_from = WorkflowAction._get_form_workflow_action(self)

        if action == 'reassign':
            mtool = getToolByName(self.context, 'portal_membership')
            if not mtool.checkPermission(ManageWorksheets, self.context):

                # Redirect to WS list
                msg = _('You do not have sufficient privileges to '
                        'manage worksheets.')
                self.context.plone_utils.addPortalMessage(msg, 'warning')
                portal = getToolByName(self.context,
                                       'portal_url').getPortalObject()
                self.destination_url = portal.absolute_url() + "/worksheets"
                self.request.response.redirect(self.destination_url)
                return

            selected_worksheets = WorkflowAction._get_selected_items(self)
            selected_worksheet_uids = selected_worksheets.keys()

            if selected_worksheets:
                changes = False
                for uid in selected_worksheet_uids:
                    worksheet = selected_worksheets[uid]
                    # Double-check the state first
                    if workflow.getInfoFor(worksheet,
                                           'review_state') == 'open':
                        worksheet.setAnalyst(form['Analyst'][0][uid])
                        worksheet.reindexObject(idxs=['getAnalyst'])
                        changes = True

                if changes:
                    message = PMF('Changes saved.')
                    self.context.plone_utils.addPortalMessage(message, 'info')

            self.destination_url = self.request.get_header(
                "referer", self.context.absolute_url())
            self.request.response.redirect(self.destination_url)
        else:
            # default bika_listing.py/WorkflowAction for other transitions
            WorkflowAction.__call__(self)
Esempio n. 27
0
 def workflow_action_publish(self):
     action, came_from = WorkflowAction._get_form_workflow_action(self)
     if not isActive(self.context):
         message = _('Item is inactive.')
         self.context.plone_utils.addPortalMessage(message, 'info')
         self.request.response.redirect(self.context.absolute_url())
         return
     # AR publish preview
     self.request.response.redirect(self.context.absolute_url() + "/publish")
Esempio n. 28
0
 def workflow_action_publish(self):
     action, came_from = WorkflowAction._get_form_workflow_action(self)
     if not isActive(self.context):
         message = _('Item is inactive.')
         self.context.plone_utils.addPortalMessage(message, 'info')
         self.request.response.redirect(self.context.absolute_url())
         return
     # AR publish preview
     self.request.response.redirect(self.context.absolute_url() + "/publish")
Esempio n. 29
0
 def workflow_action_save_partitions_button(self):
     form = self.request.form
     # Sample Partitions or AR Manage Analyses: save Partition Table
     sample = self.context.portal_type == 'Sample' and self.context or\
         self.context.getSample()
     part_prefix = sample.getId() + "-P"
     nr_existing = len(sample.objectIds())
     nr_parts = len(form['PartTitle'][0])
     # add missing parts
     if nr_parts > nr_existing:
         for i in range(nr_parts - nr_existing):
             part = _createObjectByType("SamplePartition", sample, tmpID())
             part.setDateReceived = DateTime()
             part.processForm()
     # remove excess parts
     if nr_existing > nr_parts:
         for i in range(nr_existing - nr_parts):
             part = sample['%s%s' % (part_prefix, nr_existing - i)]
             analyses = part.getAnalyses()
             for a in analyses:
                 a.setSamplePartition(None)
             sample.manage_delObjects([
                 '%s%s' % (part_prefix, nr_existing - i),
             ])
     # modify part container/preservation
     for part_uid, part_id in form['PartTitle'][0].items():
         part = sample["%s%s" %
                       (part_prefix, part_id.split(part_prefix)[1])]
         part.edit(
             Container=form['getContainer'][0][part_uid],
             Preservation=form['getPreservation'][0][part_uid],
         )
         part.reindexObject()
         # Adding the Security Seal Intact checkbox's value to the container object
         container_uid = form['getContainer'][0][part_uid]
         uc = getToolByName(self.context, 'uid_catalog')
         cbr = uc(UID=container_uid)
         if cbr and len(cbr) > 0:
             container_obj = cbr[0].getObject()
         else:
             continue
         value = form.get('setSecuritySealIntact', {}).get(part_uid,
                                                           '') == 'on'
         container_obj.setSecuritySealIntact(value)
     objects = WorkflowAction._get_selected_items(self)
     if not objects:
         message = _("No items have been selected")
         self.context.plone_utils.addPortalMessage(message, 'info')
         if self.context.portal_type == 'Sample':
             # in samples his table is on 'Partitions' tab
             self.destination_url = self.context.absolute_url() +\
                 "/partitions"
         else:
             # in ar context this table is on 'ManageAnalyses' tab
             self.destination_url = self.context.absolute_url() +\
                 "/analyses"
         self.request.response.redirect(self.destination_url)
Esempio n. 30
0
 def workflow_action_schedule_sampling(self):
     """
     This function prevent the transition if the fields "SamplingDate"
     and "ScheduledSamplingSampler" are uncompleted.
     :return: bool
     """
     from bika.lims.utils.workflow import schedulesampling
     message = 'Not expected transition.'
     # In Samples Folder we have to get each selected item
     if interfaces.ISamplesFolder.providedBy(self.context):
         select_objs = WorkflowAction._get_selected_items(self)
         message = _('Transition done.')
         for key in select_objs.keys():
             sample = select_objs[key]
             # Getting the sampler
             sch_sampl = self.request.form.get(
                 'getScheduledSamplingSampler', None)[0].get(key) if\
                 self.request.form.get(
                     'getScheduledSamplingSampler', None) else ''
             # Getting the date
             sampl_date = self.request.form.get(
                 'getSamplingDate', None)[0].get(key) if\
                 self.request.form.get(
                     'getSamplingDate', None) else ''
             # Setting both values
             sample.setScheduledSamplingSampler(sch_sampl)
             sample.setSamplingDate(sampl_date)
             # Transitioning the sample
             success, errmsg = schedulesampling.doTransition(sample)
             if errmsg == 'missing':
                 message = _(
                     "'Sampling date' and 'Define the Sampler for the" +
                     " scheduled sampling' must be completed and saved " +
                     "in order to schedule a sampling. Element: %s" %
                     sample.getId())
             elif errmsg == 'cant_trans':
                 message = _(
                     "The item %s can't be transitioned." % sample.getId())
             else:
                 message = _('Transition done.')
             self.context.plone_utils.addPortalMessage(message, 'info')
     else:
         success, errmsg = schedulesampling.doTransition(self.context)
         if errmsg == 'missing':
             message = _(
                 "'Sampling date' and 'Define the Sampler for the" +
                 " scheduled sampling' must be completed and saved in " +
                 "order to schedule a sampling.")
         elif errmsg == 'cant_trans':
             message = _("The item can't be transitioned.")
         else:
             message = _('Transition done.')
         self.context.plone_utils.addPortalMessage(message, 'info')
     # Reload the page in order to show the portal message
     self.request.response.redirect(self.context.absolute_url())
     return success
Esempio n. 31
0
    def __call__(self):
        form = self.request.form
        CheckAuthenticator(form)
        workflow = getToolByName(self.context, 'portal_workflow')
        rc = getToolByName(self.context, REFERENCE_CATALOG)
        action, came_from = WorkflowAction._get_form_workflow_action(self)

        if action == 'reassign':
            mtool = getToolByName(self.context, 'portal_membership')
            if not mtool.checkPermission(ManageWorksheets, self.context):

                # Redirect to WS list
                msg = _('You do not have sufficient privileges to '
                        'manage worksheets.')
                self.context.plone_utils.addPortalMessage(msg, 'warning')
                portal = getToolByName(self.context, 'portal_url').getPortalObject()
                self.destination_url = portal.absolute_url() + "/worksheets"
                self.request.response.redirect(self.destination_url)
                return

            selected_worksheets = WorkflowAction._get_selected_items(self)
            selected_worksheet_uids = selected_worksheets.keys()

            if selected_worksheets:
                changes = False
                for uid in selected_worksheet_uids:
                    worksheet = selected_worksheets[uid]
                    # Double-check the state first
                    if workflow.getInfoFor(worksheet, 'review_state') == 'open':
                        worksheet.setAnalyst(form['Analyst'][0][uid])
                        worksheet.reindexObject(idxs=['getAnalyst'])
                        changes = True

                if changes:
                    message = PMF('Changes saved.')
                    self.context.plone_utils.addPortalMessage(message, 'info')

            self.destination_url = self.request.get_header("referer",
                                   self.context.absolute_url())
            self.request.response.redirect(self.destination_url)
        else:
            # default bika_listing.py/WorkflowAction for other transitions
            WorkflowAction.__call__(self)
Esempio n. 32
0
    def __call__(self):
        form = self.request.form
        CheckAuthenticator(form)
        action, came_from = WorkflowAction._get_form_workflow_action(self)

        if action == "reassign":
            mtool = api.get_tool("portal_membership")
            if not mtool.checkPermission(ManageWorksheets, self.context):
                # Redirect to WS list
                msg = _("You do not have sufficient privileges to "
                        "manage worksheets.")
                self.context.plone_utils.addPortalMessage(msg, "warning")
                portal = api.get_portal()
                self.destination_url = portal.absolute_url() + "/worksheets"
                self.request.response.redirect(self.destination_url)
                return

            selected_worksheets = WorkflowAction._get_selected_items(self)
            selected_worksheet_uids = selected_worksheets.keys()

            if selected_worksheets:
                changes = False
                for uid in selected_worksheet_uids:
                    worksheet = selected_worksheets[uid]
                    # Double-check the state first
                    if api.get_workflow_status_of(worksheet) == "open":
                        analyst = form["Analyst"][0][uid]
                        worksheet.setAnalyst(analyst)
                        worksheet.reindexObject(idxs=["getAnalyst"])
                        changes = True
                if changes:
                    message = _("Changes saved.")
                    self.context.plone_utils.addPortalMessage(message, "info")

            self.destination_url = self.request.get_header(
                "referer", self.context.absolute_url())
            self.request.response.redirect(self.destination_url)
        else:
            # default bika_listing.py/WorkflowAction for other transitions
            WorkflowAction.__call__(self)
Esempio n. 33
0
 def workflow_action_save_partitions_button(self):
     form = self.request.form
     # Sample Partitions or AR Manage Analyses: save Partition Table
     sample = self.context.portal_type == 'Sample' and self.context or\
         self.context.getSample()
     part_prefix = sample.getId() + "-P"
     nr_existing = len(sample.objectIds())
     nr_parts = len(form['PartTitle'][0])
     # add missing parts
     if nr_parts > nr_existing:
         for i in range(nr_parts - nr_existing):
             part = _createObjectByType("SamplePartition", sample, tmpID())
             part.setDateReceived = DateTime()
             part.processForm()
     # remove excess parts
     if nr_existing > nr_parts:
         for i in range(nr_existing - nr_parts):
             part = sample['%s%s' % (part_prefix, nr_existing - i)]
             for a in part.getBackReferences("AnalysisSamplePartition"):
                 a.setSamplePartition(None)
             sample.manage_delObjects(['%s%s' % (part_prefix, nr_existing - i), ])
     # modify part container/preservation
     for part_uid, part_id in form['PartTitle'][0].items():
         part = sample["%s%s" % (part_prefix, part_id.split(part_prefix)[1])]
         part.edit(
             Container=form['getContainer'][0][part_uid],
             Preservation=form['getPreservation'][0][part_uid],
         )
         part.reindexObject()
         # Adding the Security Seal Intact checkbox's value to the container object
         container_uid = form['getContainer'][0][part_uid]
         uc = getToolByName(self.context, 'uid_catalog')
         cbr = uc(UID=container_uid)
         if cbr and len(cbr) > 0:
             container_obj = cbr[0].getObject()
         else:
             continue
         value = form.get('setSecuritySealIntact', {}).get(part_uid, '') == 'on'
         container_obj.setSecuritySealIntact(value)
     objects = WorkflowAction._get_selected_items(self)
     if not objects:
         message = _("No items have been selected")
         self.context.plone_utils.addPortalMessage(message, 'info')
         if self.context.portal_type == 'Sample':
             # in samples his table is on 'Partitions' tab
             self.destination_url = self.context.absolute_url() +\
                 "/partitions"
         else:
             # in ar context this table is on 'ManageAnalyses' tab
             self.destination_url = self.context.absolute_url() +\
                 "/analyses"
         self.request.response.redirect(self.destination_url)
Esempio n. 34
0
 def workflow_action_publish(self):
     action, came_from = WorkflowAction._get_form_workflow_action(self)
     if not isActive(self.context):
         message = _('Item is inactive.')
         self.context.plone_utils.addPortalMessage(message, 'info')
         self.request.response.redirect(self.context.absolute_url())
         return
     # AR publish preview
     uids = self.request.form.get('uids', [self.context.UID()])
     items = ",".join(uids)
     self.request.response.redirect(self.context.portal_url() +
                                    "/analysisrequests/publish?items=" +
                                    items)
Esempio n. 35
0
 def workflow_action_copy_to_new(self):
     # Pass the selected AR UIDs in the request, to ar_add.
     objects = WorkflowAction._get_selected_items(self)
     if not objects:
         message = _("No analyses have been selected")
         self.context.plone_utils.addPortalMessage(message, 'info')
         referer = self.request.get_header("referer")
         self.request.response.redirect(referer)
         return
     url = self.context.absolute_url() + "/ar_add" + \
         "?ar_count={0}".format(len(objects)) + \
         "&copy_from={0}".format(",".join(reversed(objects.keys())))
     self.request.response.redirect(url)
     return
Esempio n. 36
0
 def workflow_action_copy_to_new(self):
     # Pass the selected AR UIDs in the request, to ar_add.
     objects = WorkflowAction._get_selected_items(self)
     if not objects:
         message = _("No analyses have been selected")
         self.context.plone_utils.addPortalMessage(message, 'info')
         referer = self.request.get_header("referer")
         self.request.response.redirect(referer)
         return
     url = self.context.absolute_url() + "/ar_add" + \
         "?ar_count={0}".format(len(objects)) + \
         "&copy_from={0}".format(",".join(objects.keys()))
     self.request.response.redirect(url)
     return
Esempio n. 37
0
 def workflow_action_receive(self):
     action, came_from = WorkflowAction._get_form_workflow_action(self)
     items = [self.context] if came_from == "workflow_action" else self._get_selected_items().values()
     trans, dest = self.submitTransition(action, came_from, items)
     if trans and "receive" in self.context.bika_setup.getAutoPrintStickers():
         transitioned = [item.id for item in items]
         tmpl = self.context.bika_setup.getAutoStickerTemplate()
         q = "/sticker?autoprint=1&template=%s&items=" % tmpl
         q += ",".join(transitioned)
         self.request.response.redirect(self.context.absolute_url() + q)
     elif trans:
         message = PMF("Changes saved.")
         self.context.plone_utils.addPortalMessage(message, "info")
         self.destination_url = self.context.absolute_url()
         self.request.response.redirect(self.destination_url)
Esempio n. 38
0
 def workflow_action_receive(self):
     action, came_from = WorkflowAction._get_form_workflow_action(self)
     items = [self.context,] if came_from == 'workflow_action' \
             else self._get_selected_items().values()
     trans, dest = self.submitTransition(action, came_from, items)
     if trans and 'receive' in self.context.bika_setup.getAutoPrintStickers():
         transitioned = [item.id for item in items]
         tmpl = self.context.bika_setup.getAutoStickerTemplate()
         q = "/sticker?template=%s&items=" % tmpl
         q += ",".join(transitioned)
         self.request.response.redirect(self.context.absolute_url() + q)
     elif trans:
         message = PMF('Changes saved.')
         self.context.plone_utils.addPortalMessage(message, 'info')
         self.destination_url = self.context.absolute_url()
         self.request.response.redirect(self.destination_url)
Esempio n. 39
0
 def workflow_action_receive(self):
     action, came_from = WorkflowAction._get_form_workflow_action(self)
     items = [self.context,] if came_from == 'workflow_action' \
             else self._get_selected_items().values()
     trans, dest = self.submitTransition(action, came_from, items)
     if trans and 'receive' in self.context.bika_setup.getAutoPrintLabels():
         transitioned = [item.id for item in items]
         size = self.context.bika_setup.getAutoLabelSize()
         q = "/sticker?size=%s&items=" % size
         q += ",".join(transitioned)
         self.request.response.redirect(self.context.absolute_url() + q)
     elif trans:
         message = PMF('Changes saved.')
         self.context.plone_utils.addPortalMessage(message, 'info')
         self.destination_url = self.context.absolute_url()
         self.request.response.redirect(self.destination_url)
Esempio n. 40
0
    def workflow_action_sample_due(self):
        form = self.request.form
        selected_biospecimens = WorkflowAction._get_selected_items(self)
        biospecimens = []
        for uid in selected_biospecimens.keys():
            if not form['Barcode'][0][uid] or \
                    not form['Type'][0][uid]:
                continue
            try:
                obj = selected_biospecimens.get(uid, None)
                if 'Barcode' in form and form['Barcode'][0][uid]:
                    obj.getField('Barcode').set(obj, form['Barcode'][0][uid])
                    obj.setId(form['Barcode'][0][uid])
                if 'Type' in form and form['Type'][0][uid]:
                    obj.getField('SampleType').set(obj, form['Type'][0][uid])
                if 'FrozenTime' in form and form['FrozenTime'][0][uid]:
                    if not self.frozen_time_format_is_valid(form['FrozenTime'][0][uid]):
                        self.context.plone_utils.addPortalMessage('Invalid frozen datetime for %s  has been removed. Please complete this batch first and then edit the aliquot separately to enter the frozen time.' % form['Barcode'][0][uid], 'error')
                    else:
                        obj.getField('FrozenTime').set(obj, form['FrozenTime'][0][uid])
                min_volume = obj.getSampleType().getMinimumVolume()
                volume_unit = min_volume.split(' ')
                if min_volume and len(volume_unit) == 2:
                    obj.getField('Volume').set(obj, volume_unit[0])
                    obj.getField('Unit').set(obj, volume_unit[1])
                obj.edit(SampleID=obj.getId())
                obj.reindexObject()
                biospecimens.append(obj)
            except ReferenceException:
                continue
        message = PMF("Changes saved.")
        self.context.plone_utils.addPortalMessage(message, 'info')

        for biospecimen in biospecimens:
            doActionFor(biospecimen, 'sample_due')
            for partition in biospecimen.objectValues('SamplePartition'):
                doActionFor(partition, 'sample_due')

        self.destination_url = self.context.absolute_url()
        if form['portal_type'] == 'Kit' or \
                form['portal_type'] == 'SampleBatch':
            self.destination_url = form['view_url']

        self.destination_url += '/biospecimens'
        self.request.response.redirect(self.destination_url)
Esempio n. 41
0
    def workflow_action_receive(self):
        form = self.request.form
        # print form
        selected_biospecimens = WorkflowAction._get_selected_items(self)
        biospecimens = []
        for uid in selected_biospecimens.keys():
            if not form['Volume'][0][uid] or \
                    not form['Unit'][0][uid] or \
                    not form['SubjectID'][0][uid]:
                continue

            try:
                obj = selected_biospecimens.get(uid, None)
                obj.getField('Volume').set(obj, form['Volume'][0][uid])
                obj.getField('SubjectID').set(obj, form['SubjectID'][0][uid])
                if 'Unit' in form and form['Unit'][0][uid]:
                    unit = 'ml'
                    for u in VOLUME_UNITS:
                        if u['ResultText'] == form['Unit'][0][uid]:
                            unit = u['ResultText']
                    obj.getField('Unit').set(obj, unit)
                location = obj.getStorageLocation()
                if location:
                    doActionFor(location, 'occupy')

                obj.reindexObject()
                biospecimens.append(obj)
            except ReferenceException:
                continue

        message = PMF("Changes saved.")
        self.context.plone_utils.addPortalMessage(message, 'info')

        for biospecimen in biospecimens:
            doActionFor(biospecimen, 'receive')
            for partition in biospecimen.objectValues('SamplePartition'):
                doActionFor(partition, 'receive')

        self.destination_url = self.context.absolute_url()
        if form['portal_type'] == 'Kit' or \
                form['portal_type'] == 'SampleBatch':
            self.destination_url = form['view_url']

        self.destination_url += '/biospecimens'
        self.request.response.redirect(self.destination_url)
Esempio n. 42
0
 def workflow_action_save_partitions_button(self):
     form = self.request.form
     # Sample Partitions or AR Manage Analyses: save Partition Table
     sample = self.context.portal_type == 'Sample' and self.context or\
         self.context.getSample()
     part_prefix = sample.getId() + "-P"
     nr_existing = len(sample.objectIds())
     nr_parts = len(form['PartTitle'][0])
     # add missing parts
     if nr_parts > nr_existing:
         for i in range(nr_parts - nr_existing):
             part = _createObjectByType("SamplePartition", sample, tmpID())
             part.setDateReceived = DateTime()
             part.processForm()
     # remove excess parts
     if nr_existing > nr_parts:
         for i in range(nr_existing - nr_parts):
             part = sample['%s%s' % (part_prefix, nr_existing - i)]
             for a in part.getBackReferences("AnalysisSamplePartition"):
                 a.setSamplePartition(None)
             sample.manage_delObjects([
                 '%s%s' % (part_prefix, nr_existing - i),
             ])
     # modify part container/preservation
     for part_uid, part_id in form['PartTitle'][0].items():
         part = sample["%s%s" %
                       (part_prefix, part_id.split(part_prefix)[1])]
         part.edit(
             Container=form['getContainer'][0][part_uid],
             Preservation=form['getPreservation'][0][part_uid],
         )
         part.reindexObject()
     objects = WorkflowAction._get_selected_items(self)
     if not objects:
         message = _("No items have been selected")
         self.context.plone_utils.addPortalMessage(message, 'info')
         if self.context.portal_type == 'Sample':
             # in samples his table is on 'Partitions' tab
             self.destination_url = self.context.absolute_url() +\
                 "/partitions"
         else:
             # in ar context this table is on 'ManageAnalyses' tab
             self.destination_url = self.context.absolute_url() +\
                 "/analyses"
         self.request.response.redirect(self.destination_url)
Esempio n. 43
0
    def workflow_action_receive(self):
        form = self.request.form
        # print form
        selected_biospecimens = WorkflowAction._get_selected_items(self)
        biospecimens = []
        for uid in selected_biospecimens.keys():
            if not form['Barcode'][0][uid] or \
                    not form['Type'][0][uid] or \
                    not form['Volume'][0][uid] or \
                    not form['Unit'][0][uid] or \
                    not form['SubjectID'][0][uid]:
                continue

            try:
                obj = selected_biospecimens.get(uid, None)
                obj.getField('Barcode').set(obj, form['Barcode'][0][uid])
                obj.getField('SampleType').set(obj, form['Type'][0][uid])
                obj.getField('Volume').set(obj, form['Volume'][0][uid])
                obj.getField('SubjectID').set(obj, form['SubjectID'][0][uid])
                unit = 'ml'
                for u in VOLUME_UNITS:
                    if u['ResultValue'] == form['Unit'][0][uid]:
                        unit = u['ResultText']
                obj.getField('Unit').set(obj, unit)
                obj.reindexObject()
                biospecimens.append(obj)
            except ReferenceException:
                continue

        message = PMF("Changes saved.")
        self.context.plone_utils.addPortalMessage(message, 'info')

        for biospecimen in biospecimens:
            doActionFor(biospecimen, 'receive')
            for partition in biospecimen.objectValues('SamplePartition'):
                doActionFor(partition, 'receive')

        self.destination_url = self.context.absolute_url()
        if self.context.portal_type == 'Project':
            self.destination_url += '/biospecimens'
        self.request.response.redirect(self.destination_url)
Esempio n. 44
0
 def workflow_action_publish(self):
     action, came_from = WorkflowAction._get_form_workflow_action(self)
     if not isActive(self.context):
         message = _('Item is inactive.')
         self.context.plone_utils.addPortalMessage(message, 'info')
         self.request.response.redirect(self.context.absolute_url())
         return
     # publish entire AR.
     self.context.setDatePublished(DateTime())
     transitioned = self.doPublish(self.context,
                            self.request,
                            action,
                            [self.context, ])()
     if len(transitioned) == 1:
         message = _(
             '${items} published.',
             mapping={'items': safe_unicode(', '.join(transitioned))})
     else:
         message = _("No items were published")
     self.context.plone_utils.addPortalMessage(message, 'info')
     self.destination_url = self.request.get_header("referer",
                            self.context.absolute_url())
     self.request.response.redirect(self.destination_url)
Esempio n. 45
0
    def workflow_action_aliquot_receive(self):
        form = self.request.form
        selected_aliquots = WorkflowAction._get_selected_items(self)
        aliquots = []
        for uid in selected_aliquots.keys():
            if not form['AliquotType'][0][uid] or \
               not form['Volume'][0][uid] or \
               not form['Unit'][0][uid]:
                continue
            try:
                aliquot = selected_aliquots.get(uid, None)
                aliquot.getField('SampleType').set(aliquot,
                                                   form['AliquotType'][0][uid])
                aliquot.getField('Volume').set(aliquot, form['Volume'][0][uid])
                unit = 'ml'
                for u in VOLUME_UNITS:
                    if u['ResultValue'] == form['Unit'][0][uid]:
                        unit = u['ResultText']
                aliquot.getField('Unit').set(aliquot, unit)
                aliquot.reindexObject()
                aliquots.append(aliquot)
            except ReferenceException:
                continue

        message = PMF("Changes saved.")
        self.context.plone_utils.addPortalMessage(message, 'info')

        for aliquot in aliquots:
            doActionFor(aliquot, 'receive')
            for partition in aliquot.objectValues('SamplePartition'):
                doActionFor(partition, 'receive')

        self.destination_url = self.context.absolute_url()
        if self.context.portal_type == 'Project':
            self.destination_url += '/aliquots'
        self.request.response.redirect(self.destination_url)
Esempio n. 46
0
    def workflow_action_submit(self):
        form = self.request.form
        rc = getToolByName(self.context, REFERENCE_CATALOG)
        action, came_from = WorkflowAction._get_form_workflow_action(self)
        checkPermission = self.context.portal_membership.checkPermission
        if not isActive(self.context):
            message = _('Item is inactive.')
            self.context.plone_utils.addPortalMessage(message, 'info')
            self.request.response.redirect(self.context.absolute_url())
            return
        # calcs.js has kept item_data and form input interim values synced,
        # so the json strings from item_data will be the same as the form values
        item_data = {}
        if 'item_data' in form:
            if isinstance(form['item_data'], list):
                for i_d in form['item_data']:
                    for i, d in json.loads(i_d).items():
                        item_data[i] = d
            else:
                item_data = json.loads(form['item_data'])
        selected_analyses = WorkflowAction._get_selected_items(self)
        results = {}
        hasInterims = {}
        # check that the form values match the database
        # save them if not.
        for uid, result in self.request.form.get('Result', [{}])[0].items():
            # if the AR has ReportDryMatter set, get dry_result from form.
            dry_result = ''
            if hasattr(self.context, 'getReportDryMatter') \
               and self.context.getReportDryMatter():
                for k, v in self.request.form['ResultDM'][0].items():
                    if uid == k:
                        dry_result = v
                        break
            if uid in selected_analyses:
                analysis = selected_analyses[uid]
            else:
                analysis = rc.lookupObject(uid)
            if not analysis:
                # ignore result if analysis object no longer exists
                continue
            results[uid] = result
            interimFields = item_data[uid]
            if len(interimFields) > 0:
                hasInterims[uid] = True
            else:
                hasInterims[uid] = False
            retested = 'retested' in form and uid in form['retested']
            remarks = form.get('Remarks', [{}, ])[0].get(uid, '')
            # Don't save uneccessary things
            # https://github.com/bikalabs/Bika-LIMS/issues/766:
            #    Somehow, using analysis.edit() fails silently when
            #    logged in as Analyst.
            if analysis.getInterimFields() != interimFields or \
               analysis.getRetested() != retested or \
               analysis.getRemarks() != remarks:
                analysis.setInterimFields(interimFields)
                analysis.setRetested(retested)
                analysis.setRemarks(remarks)
            # save results separately, otherwise capture date is rewritten
            if analysis.getResult() != result or \
               analysis.getResultDM() != dry_result:
                analysis.setResultDM(dry_result)
                analysis.setResult(result)
        methods = self.request.form.get('Method', [{}])[0]
        instruments = self.request.form.get('Instrument', [{}])[0]
        analysts = self.request.form.get('Analyst', [{}])[0]
        # discover which items may be submitted
        submissable = []
        for uid, analysis in selected_analyses.items():
            analysis_active = isActive(analysis)

            # Need to save the instrument?
            if uid in instruments and analysis_active:
                # TODO: Add SetAnalysisInstrument permission
                # allow_setinstrument = sm.checkPermission(SetAnalysisInstrument)
                allow_setinstrument = True
                # ---8<-----
                if allow_setinstrument == True:
                    # The current analysis allows the instrument regards
                    # to its analysis service and method?
                    if (instruments[uid]==''):
                        previnstr = analysis.getInstrument()
                        if previnstr:
                            previnstr.removeAnalysis(analysis)
                        analysis.setInstrument(None);
                    elif analysis.isInstrumentAllowed(instruments[uid]):
                        previnstr = analysis.getInstrument()
                        if previnstr:
                            previnstr.removeAnalysis(analysis)
                        analysis.setInstrument(instruments[uid])
                        instrument = analysis.getInstrument()
                        instrument.addAnalysis(analysis)

            # Need to save the method?
            if uid in methods and analysis_active:
                # TODO: Add SetAnalysisMethod permission
                # allow_setmethod = sm.checkPermission(SetAnalysisMethod)
                allow_setmethod = True
                # ---8<-----
                if allow_setmethod == True and analysis.isMethodAllowed(methods[uid]):
                    analysis.setMethod(methods[uid])

            # Need to save the analyst?
            if uid in analysts and analysis_active:
                analysis.setAnalyst(analysts[uid]);

            if uid not in results or not results[uid]:
                continue
            can_submit = True
            # guard_submit does a lot of the same stuff, too.
            # the code there has also been commented.
            # we must find a better way to allow dependencies to control
            # this process.
            # for dependency in analysis.getDependencies():
            #     dep_state = workflow.getInfoFor(dependency, 'review_state')
            #     if hasInterims[uid]:
            #         if dep_state in ('to_be_sampled', 'to_be_preserved',
            #                          'sample_due', 'sample_received',
            #                          'attachment_due', 'to_be_verified',):
            #             can_submit = False
            #             break
            #     else:
            #         if dep_state in ('to_be_sampled', 'to_be_preserved',
            #                          'sample_due', 'sample_received',):
            #             can_submit = False
            #             break
            if can_submit and analysis not in submissable:
                submissable.append(analysis)
        # and then submit them.
        for analysis in submissable:
            doActionFor(analysis, 'submit')
        message = PMF("Changes saved.")
        self.context.plone_utils.addPortalMessage(message, 'info')
        if checkPermission(EditResults, self.context):
            self.destination_url = self.context.absolute_url() + "/manage_results"
        else:
            self.destination_url = self.context.absolute_url()
        self.request.response.redirect(self.destination_url)
Esempio n. 47
0
    def submit(self):
        """ Saves the form
        """

        form = self.request.form
        remarks = form.get('Remarks', [{}])[0]
        results = form.get('Result', [{}])[0]
        retested = form.get('retested', {})
        methods = form.get('Method', [{}])[0]
        instruments = form.get('Instrument', [{}])[0]
        analysts = self.request.form.get('Analyst', [{}])[0]
        uncertainties = self.request.form.get('Uncertainty', [{}])[0]
        dlimits = self.request.form.get('DetectionLimit', [{}])[0]
        selected = WorkflowAction._get_selected_items(self)
        workflow = getToolByName(self.context, 'portal_workflow')
        rc = getToolByName(self.context, REFERENCE_CATALOG)
        sm = getSecurityManager()

        hasInterims = {}
        # XXX combine data from multiple bika listing tables.
        item_data = {}
        if 'item_data' in form:
            if type(form['item_data']) == list:
                for i_d in form['item_data']:
                    for i, d in json.loads(i_d).items():
                        item_data[i] = d
            else:
                item_data = json.loads(form['item_data'])

        # Iterate for each selected analysis and save its data as needed
        for uid, analysis in selected.items():

            allow_edit = sm.checkPermission(EditResults, analysis)
            analysis_active = isActive(analysis)

            # Need to save remarks?
            if uid in remarks and allow_edit and analysis_active:
                analysis.setRemarks(remarks[uid])

            # Retested?
            if uid in retested and allow_edit and analysis_active:
                analysis.setRetested(retested[uid])

            # Need to save the instrument?
            if uid in instruments and analysis_active:
                # TODO: Add SetAnalysisInstrument permission
                # allow_setinstrument = sm.checkPermission(SetAnalysisInstrument)
                allow_setinstrument = True
                # ---8<-----
                if allow_setinstrument == True:
                    # The current analysis allows the instrument regards
                    # to its analysis service and method?
                    if (instruments[uid] == ''):
                        previnstr = analysis.getInstrument()
                        if previnstr:
                            previnstr.removeAnalysis(analysis)
                        analysis.setInstrument(None)
                    elif analysis.isInstrumentAllowed(instruments[uid]):
                        previnstr = analysis.getInstrument()
                        if previnstr:
                            previnstr.removeAnalysis(analysis)
                        analysis.setInstrument(instruments[uid])
                        instrument = analysis.getInstrument()
                        instrument.addAnalysis(analysis)
                        if analysis.meta_type == 'ReferenceAnalysis':
                            instrument.setDisposeUntilNextCalibrationTest(
                                False)

            # Need to save the method?
            if uid in methods and analysis_active:
                # TODO: Add SetAnalysisMethod permission
                # allow_setmethod = sm.checkPermission(SetAnalysisMethod)
                allow_setmethod = True
                # ---8<-----
                if allow_setmethod == True and analysis.isMethodAllowed(
                        methods[uid]):
                    analysis.setMethod(methods[uid])

            # Need to save the analyst?
            if uid in analysts and analysis_active:
                analysis.setAnalyst(analysts[uid])

            # Need to save the uncertainty?
            if uid in uncertainties and analysis_active:
                analysis.setUncertainty(uncertainties[uid])

            # Need to save the detection limit?
            if analysis_active and uid in dlimits and dlimits[uid]:
                analysis.setDetectionLimitOperand(dlimits[uid])

            # Need to save results?
            if uid in results and results[uid] and allow_edit \
                and analysis_active:
                interims = item_data.get(uid, [])
                analysis.setInterimFields(interims)
                analysis.setResult(results[uid])
                analysis.reindexObject()

                can_submit = True
                deps = analysis.getDependencies() \
                        if hasattr(analysis, 'getDependencies') else []
                for dependency in deps:
                    if workflow.getInfoFor(dependency, 'review_state') in \
                       ('to_be_sampled', 'to_be_preserved',
                        'sample_due', 'sample_received'):
                        can_submit = False
                        break
                if can_submit:
                    # doActionFor transitions the analysis to verif pending,
                    # so must only be done when results are submitted.
                    doActionFor(analysis, 'submit')

        # Maybe some analyses need to be retracted due to a QC failure
        # Done here because don't know if the last selected analysis is
        # a valid QC for the instrument used in previous analyses.
        # If we add this logic in subscribers.analyses, there's the
        # possibility to retract analyses before the QC being reached.
        self.retractInvalidAnalyses()

        message = PMF("Changes saved.")
        self.context.plone_utils.addPortalMessage(message, 'info')
        self.destination_url = self.request.get_header(
            "referer", self.context.absolute_url())
        self.request.response.redirect(self.destination_url)
Esempio n. 48
0
    def __call__(self):
        form = self.request.form
        plone.protect.CheckAuthenticator(form)
        workflow = getToolByName(self.context, 'portal_workflow')
        rc = getToolByName(self.context, REFERENCE_CATALOG)
        bsc = getToolByName(self.context, 'bika_setup_catalog')
        bac = getToolByName(self.context, 'bika_analysis_catalog')
        action, came_from = WorkflowAction._get_form_workflow_action(self)


        if action == 'submit':

            # Submit the form. Saves the results, methods, etc.
            self.submit()

        ## assign
        elif action == 'assign':
            if not self.context.checkUserManage():
                self.request.response.redirect(self.context.absolute_url())
                return

            selected_analyses = WorkflowAction._get_selected_items(self)
            selected_analysis_uids = selected_analyses.keys()

            if selected_analyses:
                for uid in selected_analysis_uids:
                    analysis = rc.lookupObject(uid)
                    # Double-check the state first
                    if (workflow.getInfoFor(analysis, 'worksheetanalysis_review_state') == 'unassigned'
                    and workflow.getInfoFor(analysis, 'review_state') == 'sample_received'
                    and workflow.getInfoFor(analysis, 'cancellation_state') == 'active'):
                        self.context.addAnalysis(analysis)

            self.destination_url = self.context.absolute_url()
            self.request.response.redirect(self.destination_url)
        ## unassign
        elif action == 'unassign':
            if not self.context.checkUserManage():
                self.request.response.redirect(self.context.absolute_url())
                return

            selected_analyses = WorkflowAction._get_selected_items(self)
            selected_analysis_uids = selected_analyses.keys()

            for analysis_uid in selected_analysis_uids:
                try:
                    analysis = bac(UID=analysis_uid)[0].getObject()
                except IndexError:
                    # Duplicate analyses are removed when their analyses
                    # get removed, so indexerror is expected.
                    continue
                if skip(analysis, action, peek=True):
                    continue
                self.context.removeAnalysis(analysis)

            message = PMF("Changes saved.")
            self.context.plone_utils.addPortalMessage(message, 'info')
            self.destination_url = self.context.absolute_url()
            self.request.response.redirect(self.destination_url)
        ## verify
        elif action == 'verify':
            # default bika_listing.py/WorkflowAction, but then go to view screen.
            self.destination_url = self.context.absolute_url()
            return self.workflow_action_default(action='verify',
                                                came_from='edit')
        else:
            # default bika_listing.py/WorkflowAction for other transitions
            WorkflowAction.__call__(self)
Esempio n. 49
0
    def __call__(self):
        form = self.request.form
        CheckAuthenticator(form)
        workflow = getToolByName(self.context, 'portal_workflow')
        rc = getToolByName(self.context, REFERENCE_CATALOG)
        bsc = getToolByName(self.context, 'bika_setup_catalog')
        bac = getToolByName(self.context, 'bika_analysis_catalog')
        action, came_from = WorkflowAction._get_form_workflow_action(self)


        if action == 'submit':
            # Submit the form. Saves the results, methods, etc.
            self.submit()

        ## assign
        elif action == 'assign':
            if not self.context.checkUserManage():
                self.request.response.redirect(self.context.absolute_url())
                return

            analysis_uids = form.get("uids", [])
            if analysis_uids:
                # We retrieve the analyses from the database sorted by AR ID
                # ascending, so the positions of the ARs inside the WS are
                # consistent with the order of the ARs
                catalog = get_tool(CATALOG_ANALYSIS_LISTING)
                brains = catalog({'UID': analysis_uids,
                                  'sort_on': 'getRequestID'})

                # Now, we need the analyses within a request ID to be sorted by
                # sortkey (sortable_title index), so it will appear in the same
                # order as they appear in Analyses list from AR view
                curr_arid = None
                curr_brains = []
                sorted_brains = []
                for brain in brains:
                    arid = brain.getRequestID
                    if curr_arid != arid:
                        # Sort the brains we've collected until now, that belong to
                        # the same Analysis Request
                        curr_brains.sort(key=attrgetter('getPrioritySortkey'))
                        sorted_brains.extend(curr_brains)
                        curr_arid = arid
                        curr_brains = []

                    # Now we are inside the same AR
                    curr_brains.append(brain)
                    continue

                # Sort the last set of brains we've collected
                curr_brains.sort(key=attrgetter('getPrioritySortkey'))
                sorted_brains.extend(curr_brains)

                # Add analyses in the worksheet
                for brain in sorted_brains:
                    analysis = brain.getObject()
                    self.context.addAnalysis(analysis)

            self.destination_url = self.context.absolute_url()
            self.request.response.redirect(self.destination_url)
        ## unassign
        elif action == 'unassign':
            if not self.context.checkUserManage():
                self.request.response.redirect(self.context.absolute_url())
                return

            selected_analyses = WorkflowAction._get_selected_items(self)
            selected_analysis_uids = selected_analyses.keys()

            for analysis_uid in selected_analysis_uids:
                try:
                    analysis = bac(UID=analysis_uid)[0].getObject()
                except IndexError:
                    # Duplicate analyses are removed when their analyses
                    # get removed, so indexerror is expected.
                    continue
                if skip(analysis, action, peek=True):
                    continue
                self.context.removeAnalysis(analysis)

            message = PMF("Changes saved.")
            self.context.plone_utils.addPortalMessage(message, 'info')
            self.destination_url = self.context.absolute_url()
            self.request.response.redirect(self.destination_url)
        ## verify
        elif action == 'verify':
            # default bika_listing.py/WorkflowAction, but then go to view screen.
            self.destination_url = self.context.absolute_url()
            return self.workflow_action_default(action='verify',
                                                came_from=came_from)
        else:
            # default bika_listing.py/WorkflowAction for other transitions
            WorkflowAction.__call__(self)
Esempio n. 50
0
    def __call__(self):
        form = self.request.form
        plone.protect.CheckAuthenticator(form)
        workflow = getToolByName(self.context, 'portal_workflow')
        pc = getToolByName(self.context, 'portal_catalog')
        rc = getToolByName(self.context, REFERENCE_CATALOG)

        # use came_from to decide which UI action was clicked.
        # "workflow_action" is the action name specified in the
        # portal_workflow transition url.
        came_from = "workflow_action"
        action = form.get(came_from, '')
        if not action:
            # workflow_action_button is the action name specified in
            # the bika_listing_view table buttons.
            came_from = "workflow_action_button"
            action = form.get(came_from, '')
            # XXX some browsers agree better than others about our JS ideas.
            if type(action) == type([]): action = action[0]
            if not action:
                if self.destination_url == "":
                    self.destination_url = self.request.get_header("referer",
                                           self.context.absolute_url())
                self.request.response.redirect(self.destination_url)
                return

        if action in ('prepublish', 'publish', 'prepublish'):
            # We pass a list of AR objects to Publish.
            # it returns a list of AR IDs which were actually published.
            ARs_to_publish = []
            transitioned = []
            if 'paths' in form:
                for path in form['paths']:
                    item_id = path.split("/")[-1]
                    item_path = path.replace("/" + item_id, '')
                    ar = pc(id = item_id,
                              path = {'query':item_path,
                                      'depth':1})[0].getObject()
                    # can't publish inactive items
                    if not(
                        'bika_inactive_workflow' in workflow.getChainFor(ar) and \
                        workflow.getInfoFor(ar, 'inactive_state', '') == 'inactive'):
                        ar.setDatePublished(DateTime())
                        ARs_to_publish.append(ar)

                transitioned = Publish(self.context,
                                       self.request,
                                       action,
                                       ARs_to_publish)()

            if len(transitioned) > 1:
                message = _('message_items_published',
                    default = '${items} were published.',
                    mapping = {'items': ', '.join(transitioned)})
            elif len(transitioned) == 1:
                message = _('message_item_published',
                    default = '${items} published.',
                    mapping = {'items': ', '.join(transitioned)})
            else:
                message = _('No items were published')
            message = self.context.translate(message)
            self.context.plone_utils.addPortalMessage(message, 'info')
            self.destination_url = self.request.get_header("referer",
                                   self.context.absolute_url())
            self.request.response.redirect(self.destination_url)

        else:
            # default bika_listing.py/WorkflowAction for other transitions
            WorkflowAction.__call__(self)
Esempio n. 51
0
    def workflow_action_submit(self):
        form = self.request.form
        rc = getToolByName(self.context, REFERENCE_CATALOG)
        action, came_from = WorkflowAction._get_form_workflow_action(self)
        checkPermission = self.context.portal_membership.checkPermission
        if not isActive(self.context):
            message = _('Item is inactive.')
            self.context.plone_utils.addPortalMessage(message, 'info')
            self.request.response.redirect(self.context.absolute_url())
            return
        # calcs.js has kept item_data and form input interim values synced,
        # so the json strings from item_data will be the same as the form values
        item_data = {}
        if 'item_data' in form:
            if isinstance(form['item_data'], list):
                for i_d in form['item_data']:
                    for i, d in json.loads(i_d).items():
                        item_data[i] = d
            else:
                item_data = json.loads(form['item_data'])
        selected_analyses = WorkflowAction._get_selected_items(self)
        results = {}
        hasInterims = {}
        # check that the form values match the database
        # save them if not.
        for uid, result in self.request.form.get('Result', [{}])[0].items():
            # Do not save data for analyses that are not selected.
            if uid not in selected_analyses:
                continue
            analysis = selected_analyses[uid]
            # never save any part of rows with empty result values.
            # https://jira.bikalabs.com/browse/LIMS-1944:
            if not result:
                continue
            # ignore result if analysis object no longer exists
            if not analysis:
                continue
            # Prevent saving data if the analysis is already transitioned
            if not (checkPermission(EditResults, analysis)
                    or checkPermission(EditFieldResults, analysis)):
                title = safe_unicode(analysis.getService().Title())
                msgid = _('Result for ${analysis} could not be saved because '
                          'it was already submitted by another user.',
                          mapping={'analysis': title})
                message = safe_unicode(t(msgid))
                self.context.plone_utils.addPortalMessage(message)
                continue
            # if the AR has ReportDryMatter set, get dry_result from form.
            dry_result = ''
            if hasattr(self.context, 'getReportDryMatter') \
               and self.context.getReportDryMatter():
                for k, v in self.request.form['ResultDM'][0].items():
                    if uid == k:
                        dry_result = v
                        break
            results[uid] = result
            interimFields = item_data[uid]
            if len(interimFields) > 0:
                hasInterims[uid] = True
            else:
                hasInterims[uid] = False
            retested = 'retested' in form and uid in form['retested']
            remarks = form.get('Remarks', [{}, ])[0].get(uid, '')
            # Don't save uneccessary things
            # https://github.com/bikalabs/Bika-LIMS/issues/766:
            #    Somehow, using analysis.edit() fails silently when
            #    logged in as Analyst.
            if analysis.getInterimFields() != interimFields or \
               analysis.getRetested() != retested or \
               analysis.getRemarks() != remarks:
                analysis.setInterimFields(interimFields)
                analysis.setRetested(retested)
                analysis.setRemarks(remarks)
            # save results separately, otherwise capture date is rewritten
            if analysis.getResult() != result or \
               analysis.getResultDM() != dry_result:
                analysis.setResultDM(dry_result)
                analysis.setResult(result)
        methods = self.request.form.get('Method', [{}])[0]
        instruments = self.request.form.get('Instrument', [{}])[0]
        analysts = self.request.form.get('Analyst', [{}])[0]
        uncertainties = self.request.form.get('Uncertainty', [{}])[0]
        dlimits = self.request.form.get('DetectionLimit', [{}])[0]
        # discover which items may be submitted
        submissable = []
        for uid, analysis in selected_analyses.items():
            analysis_active = isActive(analysis)

            # Need to save the instrument?
            if uid in instruments and analysis_active:
                # TODO: Add SetAnalysisInstrument permission
                # allow_setinstrument = sm.checkPermission(SetAnalysisInstrument)
                allow_setinstrument = True
                # ---8<-----
                if allow_setinstrument == True:
                    # The current analysis allows the instrument regards
                    # to its analysis service and method?
                    if (instruments[uid]==''):
                        previnstr = analysis.getInstrument()
                        if previnstr:
                            previnstr.removeAnalysis(analysis)
                        analysis.setInstrument(None);
                    elif analysis.isInstrumentAllowed(instruments[uid]):
                        previnstr = analysis.getInstrument()
                        if previnstr:
                            previnstr.removeAnalysis(analysis)
                        analysis.setInstrument(instruments[uid])
                        instrument = analysis.getInstrument()
                        instrument.addAnalysis(analysis)

            # Need to save the method?
            if uid in methods and analysis_active:
                # TODO: Add SetAnalysisMethod permission
                # allow_setmethod = sm.checkPermission(SetAnalysisMethod)
                allow_setmethod = True
                # ---8<-----
                if allow_setmethod == True and analysis.isMethodAllowed(methods[uid]):
                    analysis.setMethod(methods[uid])

            # Need to save the analyst?
            if uid in analysts and analysis_active:
                analysis.setAnalyst(analysts[uid])

            # Need to save the uncertainty?
            if uid in uncertainties and analysis_active:
                analysis.setUncertainty(uncertainties[uid])

            # Need to save the detection limit?
            if analysis_active:
                analysis.setDetectionLimitOperand(dlimits.get(uid, None))

            if uid not in results or not results[uid]:
                continue
            can_submit = True
            # guard_submit does a lot of the same stuff, too.
            # the code there has also been commented.
            # we must find a better way to allow dependencies to control
            # this process.
            # for dependency in analysis.getDependencies():
            #     dep_state = workflow.getInfoFor(dependency, 'review_state')
            #     if hasInterims[uid]:
            #         if dep_state in ('to_be_sampled', 'to_be_preserved',
            #                          'sample_due', 'sample_received',
            #                          'attachment_due', 'to_be_verified',):
            #             can_submit = False
            #             break
            #     else:
            #         if dep_state in ('to_be_sampled', 'to_be_preserved',
            #                          'sample_due', 'sample_received',):
            #             can_submit = False
            #             break
            if can_submit and analysis not in submissable:
                submissable.append(analysis)
        # and then submit them.
        for analysis in submissable:
            doActionFor(analysis, 'submit')

        # LIMS-2366: Finally, when we are done processing all applicable
        # analyses, we must attempt to initiate the submit transition on the
        # AR itself. This is for the case where "general retraction" has been
        # done, or where the last "received" analysis has been removed, and
        # the AR is in state "received" while there are no "received" analyses
        # left to trigger the parent transition.
        if self.context.portal_type == 'Sample':
            ar = self.context.getAnalysisRequests()[0]
        elif self.context.portal_type == 'Analysis':
            ar = self.context.aq_parent
        else:
            ar = self.context
        doActionFor(ar, 'submit')

        message = PMF("Changes saved.")
        self.context.plone_utils.addPortalMessage(message, 'info')
        if checkPermission(EditResults, self.context):
            self.destination_url = self.context.absolute_url() + "/manage_results"
        else:
            self.destination_url = self.context.absolute_url()
        self.request.response.redirect(self.destination_url)
Esempio n. 52
0
    def retractInvalidAnalyses(self):
        """ Retract the analyses with validation pending status for which
            the instrument used failed a QC Test.
        """
        toretract = {}
        instruments = {}
        refs = []
        rc = getToolByName(self.context, REFERENCE_CATALOG)
        selected = WorkflowAction._get_selected_items(self)
        for uid in selected.iterkeys():
            # We need to do this instead of using the dict values
            # directly because all these analyses have been saved before
            # and don't know if they already had an instrument assigned
            an = rc.lookupObject(uid)
            if an.portal_type == 'ReferenceAnalysis':
                refs.append(an)
                instrument = an.getInstrument()
                if instrument and instrument.UID() not in instruments:
                    instruments[instrument.UID()] = instrument

        for instr in instruments.itervalues():
            analyses = instr.getAnalysesToRetract()
            for a in analyses:
                if a.UID() not in toretract:
                    toretract[a.UID] = a

        retracted = []
        for analysis in toretract.itervalues():
            try:
                # add a remark to this analysis
                failedtxt = ulocalized_time(DateTime(), long_format=0)
                failedtxt = '%s: %s' % (failedtxt,
                                        _("Instrument failed reference test"))
                analysis.setRemarks(failedtxt)

                # retract the analysis
                doActionFor(analysis, 'retract')
                retracted.append(analysis)
            except:
                # Already retracted as a dependant from a previous one?
                pass

        if len(retracted) > 0:
            # Create the Retracted Analyses List
            rep = AnalysesRetractedListReport(self.context, self.request,
                                              self.portal_url,
                                              'Retracted analyses', retracted)

            # Attach the pdf to the ReferenceAnalysis (accessible
            # from Instrument's Internal Calibration Tests list
            pdf = rep.toPdf()
            for ref in refs:
                ref.setRetractedAnalysesPdfReport(pdf)

            # Send the email
            try:
                rep.sendEmail()
            except:
                pass

            # TODO: mostra una finestra amb els resultats publicats d'AS
            # que han utilitzat l'instrument des de la seva última
            # calibració vàlida, amb els emails, telèfons dels
            # contactes associats per a una intervenció manual
            pass
Esempio n. 53
0
    def __call__(self):
        form = self.request.form
        plone.protect.CheckAuthenticator(form)
        workflow = getToolByName(self.context, 'portal_workflow')
        rc = getToolByName(self.context, REFERENCE_CATALOG)
        bsc = getToolByName(self.context, 'bika_setup_catalog')
        bac = getToolByName(self.context, 'bika_analysis_catalog')
        action, came_from = WorkflowAction._get_form_workflow_action(self)

        # XXX combine data from multiple bika listing tables.
        item_data = {}
        if 'item_data' in form:
            if type(form['item_data']) == list:
                for i_d in form['item_data']:
                    for i, d in json.loads(i_d).items():
                        item_data[i] = d
            else:
                item_data = json.loads(form['item_data'])

        if action == 'submit' and self.request.form.has_key("Result"):
            selected_analyses = WorkflowAction._get_selected_items(self)
            results = {}
            hasInterims = {}

            # first save results for entire form
            for uid, result in self.request.form['Result'][0].items():
                if uid in selected_analyses:
                    analysis = selected_analyses[uid]
                else:
                    analysis = rc.lookupObject(uid)
                if not analysis:
                    # ignore result if analysis object no longer exists
                    continue
                if not(getSecurityManager().checkPermission(EditResults, analysis)):
                    # or changes no longer allowed
                    continue
                if not isActive(analysis):
                    # or it's cancelled
                    continue
                results[uid] = result
                service = analysis.getService()
                interimFields = item_data[uid]
                if len(interimFields) > 0:
                    hasInterims[uid] = True
                else:
                    hasInterims[uid] = False
                unit = service.getUnit()
                analysis.edit(
                    Result = result,
                    InterimFields = interimFields,
                    Retested = form.has_key('retested') and \
                               form['retested'].has_key(uid),
                    Unit = unit and unit or '')

            # discover which items may be submitted
            submissable = []
            for uid, analysis in selected_analyses.items():
                if uid not in results:
                    continue
                can_submit = True
                if hasattr(analysis, 'getDependencies'):
                    dependencies = analysis.getDependencies()
                    for dependency in dependencies:
                        dep_state = workflow.getInfoFor(dependency, 'review_state')
                        if hasInterims[uid]:
                            if dep_state in ('to_be_sampled', 'to_be_preserved',
                                             'sample_due', 'sample_received',
                                             'attachment_due', 'to_be_verified',):
                                can_submit = False
                                break
                        else:
                            if dep_state in ('to_be_sampled', 'to_be_preserved',
                                             'sample_due', 'sample_received',):
                                can_submit = False
                                break
                    for dependency in dependencies:
                        if workflow.getInfoFor(dependency, 'review_state') in \
                           ('to_be_sampled', 'to_be_preserved',
                            'sample_due', 'sample_received'):
                            can_submit = False
                if can_submit:
                    submissable.append(analysis)

            # and then submit them.
            for analysis in submissable:
                doActionFor(analysis, 'submit')

            message = PMF("Changes saved.")
            self.context.plone_utils.addPortalMessage(message, 'info')
            self.destination_url = self.request.get_header("referer",
                                   self.context.absolute_url())
            self.request.response.redirect(self.destination_url)
        ## assign
        elif action == 'assign':
            if not(getSecurityManager().checkPermission(EditWorksheet, self.context)):
                self.request.response.redirect(self.context.absolute_url())
                return

            selected_analyses = WorkflowAction._get_selected_items(self)
            selected_analysis_uids = selected_analyses.keys()

            if selected_analyses:
                for uid in selected_analysis_uids:
                    analysis = rc.lookupObject(uid)
                    # Double-check the state first
                    if (workflow.getInfoFor(analysis, 'worksheetanalysis_review_state') == 'unassigned'
                    and workflow.getInfoFor(analysis, 'review_state') == 'sample_received'
                    and workflow.getInfoFor(analysis, 'cancellation_state') == 'active'):
                        self.context.addAnalysis(analysis)

            self.destination_url = self.context.absolute_url()
            self.request.response.redirect(self.destination_url)
        ## unassign
        elif action == 'unassign':
            if not(getSecurityManager().checkPermission(EditWorksheet, self.context)):
                self.request.response.redirect(self.context.absolute_url())
                return

            selected_analyses = WorkflowAction._get_selected_items(self)
            selected_analysis_uids = selected_analyses.keys()

            for analysis_uid in selected_analysis_uids:
                try:
                    analysis = bac(UID=analysis_uid)[0].getObject()
                except IndexError:
                    # Duplicate analyses are removed when their analyses
                    # get removed, so indexerror is expected.
                    continue
                if skip(analysis, action, peek=True):
                    continue
                self.context.removeAnalysis(analysis)

            self.destination_url = self.context.absolute_url()
            self.request.response.redirect(self.destination_url)
        ## verify
        elif action == 'verify':
            # default bika_listing.py/WorkflowAction, but then go to view screen.
            self.destination_url = self.context.absolute_url()
            WorkflowAction.__call__(self)
        else:
            # default bika_listing.py/WorkflowAction for other transitions
            WorkflowAction.__call__(self)
Esempio n. 54
0
    def __call__(self):
        form = self.request.form
        plone.protect.CheckAuthenticator(form)
        workflow = getToolByName(self.context, 'portal_workflow')
        rc = getToolByName(self.context, REFERENCE_CATALOG)
        bsc = getToolByName(self.context, 'bika_setup_catalog')
        bac = getToolByName(self.context, 'bika_analysis_catalog')
        action, came_from = WorkflowAction._get_form_workflow_action(self)

        if action == 'submit':

            # Submit the form. Saves the results, methods, etc.
            self.submit()

        ## assign
        elif action == 'assign':
            if not self.context.checkUserManage():
                self.request.response.redirect(self.context.absolute_url())
                return

            selected_analyses = WorkflowAction._get_selected_items(self)
            selected_analysis_uids = selected_analyses.keys()
            if selected_analyses:
                for uid in selected_analysis_uids:
                    analysis = rc.lookupObject(uid)
                    # Double-check the state first
                    if (workflow.getInfoFor(analysis,
                                            'worksheetanalysis_review_state')
                            == 'unassigned' and workflow.getInfoFor(
                                analysis, 'review_state') == 'sample_received'
                            and workflow.getInfoFor(
                                analysis, 'cancellation_state') == 'active'):
                        self.context.addAnalysis(analysis)

            self.destination_url = self.context.absolute_url()
            self.request.response.redirect(self.destination_url)
        ## unassign
        elif action == 'unassign':
            if not self.context.checkUserManage():
                self.request.response.redirect(self.context.absolute_url())
                return

            selected_analyses = WorkflowAction._get_selected_items(self)
            selected_analysis_uids = selected_analyses.keys()

            for analysis_uid in selected_analysis_uids:
                try:
                    analysis = bac(UID=analysis_uid)[0].getObject()
                except IndexError:
                    # Duplicate analyses are removed when their analyses
                    # get removed, so indexerror is expected.
                    continue
                if skip(analysis, action, peek=True):
                    continue
                self.context.removeAnalysis(analysis)

            message = PMF("Changes saved.")
            self.context.plone_utils.addPortalMessage(message, 'info')
            self.destination_url = self.context.absolute_url()
            self.request.response.redirect(self.destination_url)
        ## verify
        elif action == 'verify':
            # default bika_listing.py/WorkflowAction, but then go to view screen.
            self.destination_url = self.context.absolute_url()
            return self.workflow_action_default(action='verify',
                                                came_from=came_from)
        else:
            # default bika_listing.py/WorkflowAction for other transitions
            WorkflowAction.__call__(self)
Esempio n. 55
0
    def retractInvalidAnalyses(self):
        """ Retract the analyses with validation pending status for which
            the instrument used failed a QC Test.
        """
        toretract = {}
        instruments = {}
        refs = []
        rc = getToolByName(self.context, REFERENCE_CATALOG)
        selected = WorkflowAction._get_selected_items(self)
        for uid in selected.iterkeys():
            # We need to do this instead of using the dict values
            # directly because all these analyses have been saved before
            # and don't know if they already had an instrument assigned
            an = rc.lookupObject(uid)
            if an.portal_type == 'ReferenceAnalysis':
                refs.append(an)
                instrument = an.getInstrument()
                if instrument and instrument.UID() not in instruments:
                    instruments[instrument.UID()] = instrument

        for instr in instruments.itervalues():
            analyses = instr.getAnalysesToRetract()
            for a in analyses:
                if a.UID() not in toretract:
                    toretract[a.UID] = a

        retracted = []
        for analysis in toretract.itervalues():
            try:
                # add a remark to this analysis
                failedtxt = ulocalized_time(DateTime(), long_format=0)
                failedtxt = '%s: %s' % (failedtxt, _("Instrument failed reference test"))
                analysis.setRemarks(failedtxt)

                # retract the analysis
                doActionFor(analysis, 'retract')
                retracted.append(analysis)
            except:
                # Already retracted as a dependant from a previous one?
                pass

        if len(retracted) > 0:
            # Create the Retracted Analyses List
            rep = AnalysesRetractedListReport(self.context,
                                               self.request,
                                               self.portal_url,
                                               'Retracted analyses',
                                               retracted)

            # Attach the pdf to the ReferenceAnalysis (accessible
            # from Instrument's Internal Calibration Tests list
            pdf = rep.toPdf()
            for ref in refs:
                ref.setRetractedAnalysesPdfReport(pdf)

            # Send the email
            try:
                rep.sendEmail()
            except:
                pass

            # TODO: mostra una finestra amb els resultats publicats d'AS
            # que han utilitzat l'instrument des de la seva última
            # calibració vàlida, amb els emails, telèfons dels
            # contactes associats per a una intervenció manual
            pass
Esempio n. 56
0
    def workflow_action_submit(self):
        form = self.request.form
        rc = getToolByName(self.context, REFERENCE_CATALOG)
        action, came_from = WorkflowAction._get_form_workflow_action(self)
        checkPermission = self.context.portal_membership.checkPermission
        if not isActive(self.context):
            message = _("Item is inactive.")
            self.context.plone_utils.addPortalMessage(message, "info")
            self.request.response.redirect(self.context.absolute_url())
            return
        # calcs.js has kept item_data and form input interim values synced,
        # so the json strings from item_data will be the same as the form values
        item_data = {}
        if "item_data" in form:
            if isinstance(form["item_data"], list):
                for i_d in form["item_data"]:
                    for i, d in json.loads(i_d).items():
                        item_data[i] = d
            else:
                item_data = json.loads(form["item_data"])
        selected_analyses = WorkflowAction._get_selected_items(self)
        results = {}
        hasInterims = {}
        # check that the form values match the database
        # save them if not.
        for uid, result in self.request.form.get("Result", [{}])[0].items():
            # Do not save data for analyses that are not selected.
            if uid not in selected_analyses:
                continue
            analysis = selected_analyses[uid]
            # never save any part of rows with empty result values.
            # https://jira.bikalabs.com/browse/LIMS-1944:
            if not result:
                continue
            # ignore result if analysis object no longer exists
            if not analysis:
                continue
            # Prevent saving data if the analysis is already transitioned
            if not (checkPermission(EditResults, analysis) or checkPermission(EditFieldResults, analysis)):
                title = safe_unicode(analysis.getService().Title())
                msgid = _(
                    "Result for ${analysis} could not be saved because " "it was already submitted by another user.",
                    mapping={"analysis": title},
                )
                message = safe_unicode(t(msgid))
                self.context.plone_utils.addPortalMessage(message)
                continue
            # if the AR has ReportDryMatter set, get dry_result from form.
            dry_result = ""
            if hasattr(self.context, "getReportDryMatter") and self.context.getReportDryMatter():
                for k, v in self.request.form["ResultDM"][0].items():
                    if uid == k:
                        dry_result = v
                        break
            results[uid] = result
            interimFields = item_data[uid]
            if len(interimFields) > 0:
                hasInterims[uid] = True
            else:
                hasInterims[uid] = False
            retested = "retested" in form and uid in form["retested"]
            remarks = form.get("Remarks", [{}])[0].get(uid, "")
            # Don't save uneccessary things
            # https://github.com/bikalabs/Bika-LIMS/issues/766:
            #    Somehow, using analysis.edit() fails silently when
            #    logged in as Analyst.
            if (
                analysis.getInterimFields() != interimFields
                or analysis.getRetested() != retested
                or analysis.getRemarks() != remarks
            ):
                analysis.setInterimFields(interimFields)
                analysis.setRetested(retested)
                analysis.setRemarks(remarks)
            # save results separately, otherwise capture date is rewritten
            if analysis.getResult() != result or analysis.getResultDM() != dry_result:
                analysis.setResultDM(dry_result)
                analysis.setResult(result)
        methods = self.request.form.get("Method", [{}])[0]
        instruments = self.request.form.get("Instrument", [{}])[0]
        analysts = self.request.form.get("Analyst", [{}])[0]
        uncertainties = self.request.form.get("Uncertainty", [{}])[0]
        dlimits = self.request.form.get("DetectionLimit", [{}])[0]
        # discover which items may be submitted
        submissable = []
        for uid, analysis in selected_analyses.items():
            analysis_active = isActive(analysis)

            # Need to save the instrument?
            if uid in instruments and analysis_active:
                # TODO: Add SetAnalysisInstrument permission
                # allow_setinstrument = sm.checkPermission(SetAnalysisInstrument)
                allow_setinstrument = True
                # ---8<-----
                if allow_setinstrument == True:
                    # The current analysis allows the instrument regards
                    # to its analysis service and method?
                    if instruments[uid] == "":
                        previnstr = analysis.getInstrument()
                        if previnstr:
                            previnstr.removeAnalysis(analysis)
                        analysis.setInstrument(None)
                    elif analysis.isInstrumentAllowed(instruments[uid]):
                        previnstr = analysis.getInstrument()
                        if previnstr:
                            previnstr.removeAnalysis(analysis)
                        analysis.setInstrument(instruments[uid])
                        instrument = analysis.getInstrument()
                        instrument.addAnalysis(analysis)

            # Need to save the method?
            if uid in methods and analysis_active:
                # TODO: Add SetAnalysisMethod permission
                # allow_setmethod = sm.checkPermission(SetAnalysisMethod)
                allow_setmethod = True
                # ---8<-----
                if allow_setmethod == True and analysis.isMethodAllowed(methods[uid]):
                    analysis.setMethod(methods[uid])

            # Need to save the analyst?
            if uid in analysts and analysis_active:
                analysis.setAnalyst(analysts[uid])

            # Need to save the uncertainty?
            if uid in uncertainties and analysis_active:
                analysis.setUncertainty(uncertainties[uid])

            # Need to save the detection limit?
            if analysis_active:
                analysis.setDetectionLimitOperand(dlimits.get(uid, None))

            if uid not in results or not results[uid]:
                continue
            can_submit = True
            # guard_submit does a lot of the same stuff, too.
            # the code there has also been commented.
            # we must find a better way to allow dependencies to control
            # this process.
            # for dependency in analysis.getDependencies():
            #     dep_state = workflow.getInfoFor(dependency, 'review_state')
            #     if hasInterims[uid]:
            #         if dep_state in ('to_be_sampled', 'to_be_preserved',
            #                          'sample_due', 'sample_received',
            #                          'attachment_due', 'to_be_verified',):
            #             can_submit = False
            #             break
            #     else:
            #         if dep_state in ('to_be_sampled', 'to_be_preserved',
            #                          'sample_due', 'sample_received',):
            #             can_submit = False
            #             break
            if can_submit and analysis not in submissable:
                submissable.append(analysis)
        # and then submit them.
        for analysis in submissable:
            doActionFor(analysis, "submit")

        # LIMS-2366: Finally, when we are done processing all applicable
        # analyses, we must attempt to initiate the submit transition on the
        # AR itself. This is for the case where "general retraction" has been
        # done, or where the last "received" analysis has been removed, and
        # the AR is in state "received" while there are no "received" analyses
        # left to trigger the parent transition.
        if self.context.portal_type == "Sample":
            ar = self.context.getAnalysisRequests()[0]
        elif self.context.portal_type == "Analysis":
            ar = self.context.aq_parent
        else:
            ar = self.context
        doActionFor(ar, "submit")

        message = PMF("Changes saved.")
        self.context.plone_utils.addPortalMessage(message, "info")
        if checkPermission(EditResults, self.context):
            self.destination_url = self.context.absolute_url() + "/manage_results"
        else:
            self.destination_url = self.context.absolute_url()
        self.request.response.redirect(self.destination_url)
Esempio n. 57
0
 def workflow_action_verify(self):
     # default bika_listing.py/WorkflowAction, but then go to view screen.
     self.destination_url = self.context.absolute_url()
     WorkflowAction.__call__(self)
Esempio n. 58
0
    def submit(self):
        """ Saves the form
        """

        form = self.request.form
        remarks = form.get('Remarks', [{}])[0]
        results = form.get('Result',[{}])[0]
        retested = form.get('retested', {})
        methods = form.get('Method', [{}])[0]
        instruments = form.get('Instrument', [{}])[0]
        analysts = self.request.form.get('Analyst', [{}])[0]
        uncertainties = self.request.form.get('Uncertainty', [{}])[0]
        dlimits = self.request.form.get('DetectionLimit', [{}])[0]
        selected = WorkflowAction._get_selected_items(self)
        workflow = getToolByName(self.context, 'portal_workflow')
        rc = getToolByName(self.context, REFERENCE_CATALOG)
        sm = getSecurityManager()

        hasInterims = {}
        # XXX combine data from multiple bika listing tables.
        item_data = {}
        if 'item_data' in form:
            if type(form['item_data']) == list:
                for i_d in form['item_data']:
                    for i, d in json.loads(i_d).items():
                        item_data[i] = d
            else:
                item_data = json.loads(form['item_data'])

        # Iterate for each selected analysis and save its data as needed
        for uid, analysis in selected.items():

            allow_edit = sm.checkPermission(EditResults, analysis)
            analysis_active = isActive(analysis)

            # Need to save remarks?
            if uid in remarks and allow_edit and analysis_active:
                analysis.setRemarks(remarks[uid])

            # Retested?
            if uid in retested and allow_edit and analysis_active:
                analysis.setRetested(retested[uid])

            # Need to save the instrument?
            if uid in instruments and analysis_active:
                # TODO: Add SetAnalysisInstrument permission
                # allow_setinstrument = sm.checkPermission(SetAnalysisInstrument)
                allow_setinstrument = True
                # ---8<-----
                if allow_setinstrument == True:
                    # The current analysis allows the instrument regards
                    # to its analysis service and method?
                    if (instruments[uid]==''):
                        previnstr = analysis.getInstrument()
                        if previnstr:
                            previnstr.removeAnalysis(analysis)
                        analysis.setInstrument(None);
                    elif analysis.isInstrumentAllowed(instruments[uid]):
                        previnstr = analysis.getInstrument()
                        if previnstr:
                            previnstr.removeAnalysis(analysis)
                        analysis.setInstrument(instruments[uid])
                        instrument = analysis.getInstrument()
                        instrument.addAnalysis(analysis)
                        if analysis.meta_type == 'ReferenceAnalysis':
                            instrument.setDisposeUntilNextCalibrationTest(False)

            # Need to save the method?
            if uid in methods and analysis_active:
                # TODO: Add SetAnalysisMethod permission
                # allow_setmethod = sm.checkPermission(SetAnalysisMethod)
                allow_setmethod = True
                # ---8<-----
                if allow_setmethod == True and analysis.isMethodAllowed(methods[uid]):
                    analysis.setMethod(methods[uid])

            # Need to save the analyst?
            if uid in analysts and analysis_active:
                analysis.setAnalyst(analysts[uid]);

            # Need to save the uncertainty?
            if uid in uncertainties and analysis_active:
                analysis.setUncertainty(uncertainties[uid])

            # Need to save the detection limit?
            if analysis_active and uid in dlimits and dlimits[uid]:
                analysis.setDetectionLimitOperand(dlimits[uid])

            # Need to save results?
            if uid in results and results[uid] and allow_edit \
                and analysis_active:
                interims = item_data.get(uid, [])
                analysis.setInterimFields(interims)
                analysis.setResult(results[uid])
                analysis.reindexObject()

                can_submit = True
                deps = analysis.getDependencies() \
                        if hasattr(analysis, 'getDependencies') else []
                for dependency in deps:
                    if workflow.getInfoFor(dependency, 'review_state') in \
                       ('to_be_sampled', 'to_be_preserved',
                        'sample_due', 'sample_received'):
                        can_submit = False
                        break
                if can_submit:
                    # doActionFor transitions the analysis to verif pending,
                    # so must only be done when results are submitted.
                    doActionFor(analysis, 'submit')

        # Maybe some analyses need to be retracted due to a QC failure
        # Done here because don't know if the last selected analysis is
        # a valid QC for the instrument used in previous analyses.
        # If we add this logic in subscribers.analyses, there's the
        # possibility to retract analyses before the QC being reached.
        self.retractInvalidAnalyses()

        message = PMF("Changes saved.")
        self.context.plone_utils.addPortalMessage(message, 'info')
        self.destination_url = self.request.get_header("referer",
                               self.context.absolute_url())
        self.request.response.redirect(self.destination_url)
Esempio n. 59
0
    def workflow_action_save_analyses_button(self):
        form = self.request.form
        workflow = getToolByName(self.context, 'portal_workflow')
        bsc = self.context.bika_setup_catalog
        action, came_from = WorkflowAction._get_form_workflow_action(self)
        # AR Manage Analyses: save Analyses
        ar = self.context
        sample = ar.getSample()
        objects = WorkflowAction._get_selected_items(self)
        if not objects:
            message = _("No analyses have been selected")
            self.context.plone_utils.addPortalMessage(message, 'info')
            self.destination_url = self.context.absolute_url() + "/analyses"
            self.request.response.redirect(self.destination_url)
            return
        Analyses = objects.keys()
        prices = form.get("Price", [None])[0]

        # Hidden analyses?
        # https://jira.bikalabs.com/browse/LIMS-1324
        outs = []
        hiddenans = form.get('Hidden', {})
        for uid in Analyses:
            hidden = hiddenans.get(uid, '')
            hidden = True if hidden == 'on' else False
            outs.append({'uid': uid, 'hidden': hidden})
        ar.setAnalysisServicesSettings(outs)

        specs = {}
        if form.get("min", None):
            for service_uid in Analyses:
                service = objects[service_uid]
                keyword = service.getKeyword()
                specs[service_uid] = {
                    "min": form["min"][0][service_uid],
                    "max": form["max"][0][service_uid],
                    "warn_min": form["warn_min"][0][service_uid],
                    "warn_max": form["warn_max"][0][service_uid],
                    "keyword": keyword,
                    "uid": service_uid,
                }
        else:
            for service_uid in Analyses:
                service = objects[service_uid]
                keyword = service.getKeyword()
                specs[service_uid] = ResultsRangeDict(keyword=keyword,
                                                      uid=service_uid)
        new = ar.setAnalyses(Analyses, prices=prices, specs=specs.values())
        # link analyses and partitions
        # If Bika Setup > Analyses > 'Display individual sample
        # partitions' is checked, no Partitions available.
        # https://github.com/bikalabs/Bika-LIMS/issues/1030
        if 'Partition' in form:
            for service_uid, service in objects.items():
                part_id = form['Partition'][0][service_uid]
                part = sample[part_id]
                analysis = ar[service.getKeyword()]
                analysis.setSamplePartition(part)
                analysis.reindexObject()
                partans = part.getAnalyses()
                partans.append(analysis)
                part.setAnalyses(partans)
                part.reindexObject()

        if new:
            ar_state = getCurrentState(ar)
            if wasTransitionPerformed(ar, 'to_be_verified'):
                # Apply to AR only; we don't want this transition to cascade.
                ar.REQUEST['workflow_skiplist'].append("retract all analyses")
                workflow.doActionFor(ar, 'retract')
                ar.REQUEST['workflow_skiplist'].remove("retract all analyses")
                ar_state = getCurrentState(ar)
            for analysis in new:
                changeWorkflowState(analysis, 'bika_analysis_workflow',
                                    ar_state)

        message = PMF("Changes saved.")
        self.context.plone_utils.addPortalMessage(message, 'info')
        self.destination_url = self.context.absolute_url()
        self.request.response.redirect(self.destination_url)