Esempio n. 1
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.UID() 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. 2
0
    def _create_user(self):
        """Create a new user
        """
        def error(field, message):
            if field:
                message = "%s: %s" % (field, message)
            self.context.plone_utils.addPortalMessage(message, 'error')
            return self.request.response.redirect(self.context.absolute_url() +
                                                  "/login_details")

        form = self.request.form
        contact = self.context

        password = safe_unicode(form.get('password', '')).encode('utf-8')
        username = safe_unicode(form.get('username', '')).encode('utf-8')
        confirm = form.get('confirm', '')
        email = safe_unicode(form.get('email', '')).encode('utf-8')

        if not username:
            return error('username', PMF("Input is required but not given."))

        if not email:
            return error('email', PMF("Input is required but not given."))

        reg_tool = self.context.portal_registration
        properties = self.context.portal_properties.site_properties

        # if properties.validate_email:
        #     password = reg_tool.generatePassword()
        # else:
        if password != confirm:
            return error('password', PMF("Passwords do not match."))

        if not password:
            return error('password', PMF("Input is required but not given."))

        if not confirm:
            return error('password', PMF("Passwords do not match."))

        if len(password) < 5:
            return error('password',
                         PMF("Passwords must contain at least 5 letters."))

        try:
            reg_tool.addMember(username,
                               password,
                               properties={
                                   'username': username,
                                   'email': email,
                                   'fullname': username
                               })
        except ValueError, msg:
            return error(None, msg)
Esempio n. 3
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. 4
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. 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':
            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. 6
0
    def __call__(self):
        if not (getSecurityManager().checkPermission(EditWorksheet,
                                                     self.context)):
            self.request.response.redirect(self.context.absolute_url())
            return

        # Deny access to foreign analysts
        if checkUserManage(self.context, self.request) == False:
            return []

        showRejectionMessage(self.context)

        translate = self.context.translate

        form_id = self.form_id
        form = self.request.form
        rc = getToolByName(self.context, REFERENCE_CATALOG)
        if 'submitted' in form:
            if 'getWorksheetTemplate' in form and form['getWorksheetTemplate']:
                layout = self.context.getLayout()
                wst = rc.lookupObject(form['getWorksheetTemplate'])
                client_title = form.get('client', 'any')
                self.request['context_uid'] = self.context.UID()
                self.context.applyWorksheetTemplate(wst,
                                                    client_title=client_title)
                if len(self.context.getLayout()) != len(layout):
                    self.context.plone_utils.addPortalMessage(
                        PMF("Changes saved."))
                    self.request.RESPONSE.redirect(
                        self.context.absolute_url() + "/manage_results")
                else:
                    self.context.plone_utils.addPortalMessage(
                        _("No analyses were added to this worksheet."))
                    self.request.RESPONSE.redirect(
                        self.context.absolute_url() + "/add_analyses")

        self._process_request()

        if self.request.get('table_only', '') == self.form_id:
            return self.contents_table()
        elif self.request.get('rows_only', '') == self.form_id:
            return self.contents_table()
        else:
            return self.template()
Esempio n. 7
0
    def workflow_action_default(self, action, came_from):
        if came_from == 'workflow_action':
            # jsonapi, I believe, ends up here.
            items = [self.context, ]
        else:
            # normal bika_listing.
            items = self._get_selected_items().values()

        if items:
            trans, dest = self.submitTransition(action, came_from, items)
            if trans:
                message = PMF('Changes saved.')
                self.context.plone_utils.addPortalMessage(message, 'info')
            if dest:
                self.request.response.redirect(dest)
                return
        else:
            message = _('No items selected')
            self.context.plone_utils.addPortalMessage(message, 'warn')
        self.request.response.redirect(self.destination_url)
        return
Esempio n. 8
0
    def workflow_action_default(self, action, came_from):
        if came_from in ['workflow_action', 'edit']:
            # If a single item was acted on we will create the item list
            # manually from this item itself.  Otherwise, bika_listing will
            # pass a list of selected items in the requyest.
            items = [self.context, ]
        else:
            # normal bika_listing.
            items = self._get_selected_items().values()

        if items:
            trans, dest = self.submitTransition(action, came_from, items)
            if trans:
                message = PMF('Changes saved.')
                self.context.plone_utils.addPortalMessage(message, 'info')
            if dest:
                self.request.response.redirect(dest)
                return
        else:
            message = _('No items selected')
            self.context.plone_utils.addPortalMessage(message, 'warn')
        self.request.response.redirect(self.destination_url)
        return
Esempio n. 9
0
    def workflow_action_send_to_lab(self):
        """Redirects the user to the requisition form automatically generated
         due to the send_to_lab transition
        """
        logger.info("SampleARWorkflowAction.workflow_action_send_to_lab")
        action, came_from = self._get_form_workflow_action()
        if not get_field_value(self.context, "Courier"):
            message = "Cannot send to the lab. Courier is not set"
            self.context.plone_utils.addPortalMessage(message, "error")
            self.request.response.redirect(self.context.absolute_url())
            return

        trans, dest = self.submitTransition(action, came_from, [self.context])
        if trans:
            message = PMF('Changes saved.')
            self.context.plone_utils.addPortalMessage(message, 'info')
            # TODO Page does not get refreshed when displaying pdf
            #self.destination_url = '{}/workflow_action?workflow_action=download_requisition'\
            #    .format(self.context.absolute_url())
            self.destination_url = self.context.absolute_url()
            self.request.response.redirect(self.destination_url)
        else:
            return
Esempio n. 10
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. 11
0
     'MemberDiscountApplies',
     default=False,
     write_permission=ManageClients,
     widget=atapi.BooleanWidget(label=_("Member discount applies"), ),
 ),
 atapi.StringField(
     'ClientType',
     required=1,
     default='noncorporate',
     write_permission=ManageClients,
     vocabulary=CLIENT_TYPES,
     widget=atapi.SelectionWidget(label=_("Client Type"), ),
 ),
 atapi.LinesField(
     'EmailSubject',
     schemata=PMF('Preferences'),
     default=[
         'ar',
     ],
     vocabulary=EMAIL_SUBJECT_OPTIONS,
     widget=atapi.MultiSelectionWidget(
         description=_('Items to be included in email subject lines'),
         label=_("Email subject line"),
     ),
 ),
 atapi.ReferenceField(
     'DefaultCategories',
     schemata=PMF('Preferences'),
     required=0,
     multiValued=1,
     vocabulary='getAnalysisCategories',
Esempio n. 12
0
    def __call__(self):
        form = self.request.form
        portal = getSite()
        workbook = None

        if 'setupexisting' in form and 'existing' in form and form['existing']:
                fn = form['existing'].split(":")
                self.dataset_project = fn[0]
                self.dataset_name = fn[1]
                path = 'setupdata/%s/%s.xlsx' % \
                    (self.dataset_name, self.dataset_name)
                filename = resource_filename(self.dataset_project, path)
                try:
                    workbook = load_workbook(filename=filename)  # , use_iterators=True)
                except AttributeError:
                    print ""
                    print traceback.format_exc()
                    print "Error while loading ", path

        elif 'setupfile' in form and 'file' in form and form['file'] and 'projectname' in form and form['projectname']:
                self.dataset_project = form['projectname']
                tmp = tempfile.mktemp()
                file_content = form['file'].read()
                open(tmp, 'wb').write(file_content)
                workbook = load_workbook(filename=tmp)  # , use_iterators=True)
                self.dataset_name = 'uploaded'

        assert(workbook is not None)

        adapters = [[name, adapter]
                    for name, adapter
                    in list(getAdapters((self.context, ), ISetupDataImporter))]
        for sheetname in workbook.get_sheet_names():
            transaction.savepoint()
            ad_name = sheetname.replace(" ", "_")
            if ad_name in [a[0] for a in adapters]:
                adapter = [a[1] for a in adapters if a[0] == ad_name][0]
                adapter(self, workbook, self.dataset_project, self.dataset_name)
                adapters = [a for a in adapters if a[0] != ad_name]
        for name, adapter in adapters:
            transaction.savepoint()
            adapter(self, workbook, self.dataset_project, self.dataset_name)

        check = len(self.deferred)
        while len(self.deferred) > 0:
            new = self.solve_deferred()
            logger.info("solved %s of %s deferred references" % (
                check - new, check))
            if new == check:
                raise Exception("%s unsolved deferred references: %s" % (
                    len(self.deferred), self.deferred))
            check = new

        logger.info("Rebuilding bika_setup_catalog")
        bsc = getToolByName(self.context, 'bika_setup_catalog')
        bsc.clearFindAndRebuild()
        logger.info("Rebuilding bika_catalog")
        bc = getToolByName(self.context, 'bika_catalog')
        bc.clearFindAndRebuild()
        logger.info("Rebuilding bika_analysis_catalog")
        bac = getToolByName(self.context, 'bika_analysis_catalog')
        bac.clearFindAndRebuild()

        message = PMF("Changes saved.")
        self.context.plone_utils.addPortalMessage(message)
        self.request.RESPONSE.redirect(portal.absolute_url())
Esempio n. 13
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. 14
0
    def __init__(self, context, request):
        super(SamplesView, self).__init__(context, request)

        request.set('disable_plone.rightcolumn', 1)

        self.catalog = 'bika_catalog'
        self.contentFilter = {
            'portal_type': 'Sample',
            'sort_on': 'created',
            'sort_order': 'reverse',
            'path': {
                'query': "/",
                'level': 0
            }
        }
        self.context_actions = {}
        self.show_sort_column = False
        self.show_select_row = False
        self.show_select_column = True
        self.allow_edit = True
        self.form_id = "samples"

        if self.view_url.find("/samples") > -1:
            self.request.set('disable_border', 1)
        else:
            self.view_url = self.view_url + "/samples"

        self.icon = self.portal_url + "/++resource++bika.lims.images/sample_big.png"
        self.title = self.context.translate(_("Samples"))
        self.description = ""

        SamplingWorkflowEnabled = self.context.bika_setup.getSamplingWorkflowEnabled(
        )

        mtool = getToolByName(self.context, 'portal_membership')
        member = mtool.getAuthenticatedMember()
        user_is_preserver = 'Preserver' in member.getRoles()

        self.columns = {
            'getSampleID': {
                'title': _('Sample ID'),
                'index': 'getSampleID'
            },
            'Client': {
                'title': _("Client"),
                'toggle': True,
            },
            'Creator': {
                'title': PMF('Creator'),
                'index': 'Creator',
                'toggle': True
            },
            'Created': {
                'title': PMF('Date Created'),
                'index': 'created',
                'toggle': False
            },
            'Requests': {
                'title': _('Requests'),
                'sortable': False,
                'toggle': False
            },
            'getClientReference': {
                'title': _('Client Ref'),
                'index': 'getClientReference',
                'toggle': True
            },
            'getClientSampleID': {
                'title': _('Client SID'),
                'index': 'getClientSampleID',
                'toggle': True
            },
            'getSampleTypeTitle': {
                'title': _('Sample Type'),
                'index': 'getSampleTypeTitle'
            },
            'getSamplePointTitle': {
                'title': _('Sample Point'),
                'index': 'getSamplePointTitle',
                'toggle': False
            },
            'getStorageLocation': {
                'title': _('Storage Location'),
                'toggle': False
            },
            'SamplingDeviation': {
                'title': _('Sampling Deviation'),
                'toggle': False
            },
            'AdHoc': {
                'title': _('Ad-Hoc'),
                'toggle': False
            },
            'getSamplingDate': {
                'title': _('Sampling Date'),
                'index': 'getSamplingDate',
                'toggle': True
            },
            'getDateSampled': {
                'title': _('Date Sampled'),
                'index': 'getDateSampled',
                'toggle': SamplingWorkflowEnabled,
                'input_class': 'datepicker_nofuture',
                'input_width': '10'
            },
            'getSampler': {
                'title': _('Sampler'),
                'toggle': SamplingWorkflowEnabled
            },
            'getDatePreserved': {
                'title': _('Date Preserved'),
                'toggle': user_is_preserver,
                'input_class': 'datepicker_nofuture',
                'input_width': '10'
            },
            'getPreserver': {
                'title': _('Preserver'),
                'toggle': user_is_preserver
            },
            'DateReceived': {
                'title': _('Date Received'),
                'index': 'getDateReceived',
                'toggle': False
            },
            'state_title': {
                'title': _('State'),
                'index': 'review_state'
            },
        }
        self.review_states = [
            {
                'id':
                'default',
                'title':
                _('Active'),
                'contentFilter': {
                    'cancellation_state': 'active',
                    'sort_on': 'created'
                },
                'columns': [
                    'getSampleID', 'Client', 'Creator', 'Created', 'Requests',
                    'getClientReference', 'getClientSampleID',
                    'getSampleTypeTitle', 'getSamplePointTitle',
                    'getStorageLocation', 'SamplingDeviation', 'AdHoc',
                    'getSamplingDate', 'getDateSampled', 'getSampler',
                    'getDatePreserved', 'getPreserver', 'DateReceived',
                    'state_title'
                ]
            },
            {
                'id':
                'sample_due',
                'title':
                _('Due'),
                'contentFilter': {
                    'review_state':
                    ('to_be_sampled', 'to_be_preserved', 'sample_due'),
                    'sort_on':
                    'created',
                    'sort_order':
                    'reverse'
                },
                'columns': [
                    'getSampleID', 'Client', 'Creator', 'Created', 'Requests',
                    'getClientReference', 'getClientSampleID',
                    'getSamplingDate', 'getDateSampled', 'getSampler',
                    'getDatePreserved', 'getPreserver', 'getSampleTypeTitle',
                    'getSamplePointTitle', 'getStorageLocation',
                    'SamplingDeviation', 'AdHoc', 'state_title'
                ]
            },
            {
                'id':
                'sample_received',
                'title':
                _('Received'),
                'contentFilter': {
                    'review_state': 'sample_received',
                    'sort_order': 'reverse',
                    'sort_on': 'created'
                },
                'columns': [
                    'getSampleID', 'Client', 'Creator', 'Created', 'Requests',
                    'getClientReference', 'getClientSampleID',
                    'getSampleTypeTitle', 'getSamplePointTitle',
                    'getStorageLocation', 'SamplingDeviation', 'AdHoc',
                    'getSamplingDate', 'getDateSampled', 'getSampler',
                    'getDatePreserved', 'getPreserver', 'DateReceived'
                ]
            },
            {
                'id':
                'expired',
                'title':
                _('Expired'),
                'contentFilter': {
                    'review_state': 'expired',
                    'sort_order': 'reverse',
                    'sort_on': 'created'
                },
                'columns': [
                    'getSampleID', 'Client', 'Creator', 'Created', 'Requests',
                    'getClientReference', 'getClientSampleID',
                    'getSampleTypeTitle', 'getSamplePointTitle',
                    'getStorageLocation', 'SamplingDeviation', 'AdHoc',
                    'getSamplingDate', 'getDateSampled', 'getSampler',
                    'getDatePreserved', 'getPreserver', 'DateReceived'
                ]
            },
            {
                'id':
                'disposed',
                'title':
                _('Disposed'),
                'contentFilter': {
                    'review_state': 'disposed',
                    'sort_order': 'reverse',
                    'sort_on': 'created'
                },
                'columns': [
                    'getSampleID', 'Client', 'Creator', 'Created', 'Requests',
                    'getClientReference', 'getClientSampleID',
                    'getSampleTypeTitle', 'getSamplePointTitle',
                    'getStorageLocation', 'SamplingDeviation', 'AdHoc',
                    'getSamplingDate', 'getDateSampled', 'getSampler',
                    'getDatePreserved', 'getPreserver', 'DateReceived'
                ]
            },
            {
                'id':
                'cancelled',
                'title':
                _('Cancelled'),
                'contentFilter': {
                    'cancellation_state': 'cancelled',
                    'sort_order': 'reverse',
                    'sort_on': 'created'
                },
                'transitions': [
                    {
                        'id': 'reinstate'
                    },
                ],
                'columns': [
                    'getSampleID', 'Client', 'Creator', 'Created', 'Requests',
                    'getClientReference', 'getClientSampleID',
                    'getSampleTypeTitle', 'getSamplePointTitle',
                    'getStorageLocation', 'SamplingDeviation', 'AdHoc',
                    'getSamplingDate', 'DateReceived', 'getDateSampled',
                    'getSampler', 'getDatePreserved', 'getPreserver',
                    'state_title'
                ]
            },
        ]
Esempio n. 15
0
    def __init__(self, context, request):
        super(FolderView, self).__init__(context, request)
        self.catalog = 'bika_catalog'
        self.contentFilter = {
            'portal_type': 'Worksheet',
            'review_state': ['open', 'to_be_verified', 'verified', 'rejected'],
            'sort_on': 'id',
            'sort_order': 'reverse'
        }
        self.context_actions = {
            _('Add'): {
                'url': 'worksheet_add',
                'icon': '++resource++bika.lims.images/add.png',
                'class': 'worksheet_add'
            }
        }
        self.show_table_only = False
        self.show_sort_column = False
        self.show_select_row = False
        self.show_select_all_checkbox = True
        self.show_select_column = True
        self.pagesize = 25
        self.restrict_results = False

        request.set('disable_border', 1)

        self.icon = self.portal_url + "/++resource++bika.lims.images/worksheet_big.png"
        self.title = self.context.translate(_("Worksheets"))
        self.description = ""

        pm = getToolByName(context, "portal_membership")
        # this is a property of self, because self.getAnalysts returns it
        self.analysts = getUsers(self, ['Manager', 'LabManager', 'Analyst'])
        self.analysts = self.analysts.sortedByKey()

        bsc = getToolByName(context, 'bika_setup_catalog')
        templates = [
            t for t in bsc(portal_type='WorksheetTemplate',
                           inactive_state='active')
        ]

        self.templates = [(t.UID, t.Title) for t in templates]
        self.templates.sort(lambda x, y: cmp(x[1], y[1]))

        self.instruments = [
            (i.UID, i.Title)
            for i in bsc(portal_type='Instrument', inactive_state='active')
        ]
        self.instruments.sort(lambda x, y: cmp(x[1], y[1]))

        self.templateinstruments = {}
        for t in templates:
            i = t.getObject().getInstrument()
            if i:
                self.templateinstruments[t.UID] = i.UID()
            else:
                self.templateinstruments[t.UID] = ''

        self.columns = {
            'Title': {
                'title': _('Worksheet'),
                'index': 'sortable_title'
            },
            'Priority': {
                'title': _('Priority'),
                'index': 'Priority',
                'toggle': True
            },
            'Analyst': {
                'title': _('Analyst'),
                'index': 'getAnalyst',
                'toggle': True
            },
            'Template': {
                'title': _('Template'),
                'toggle': True
            },
            'Services': {
                'title': _('Services'),
                'sortable': False,
                'toggle': False
            },
            'SampleTypes': {
                'title': _('Sample Types'),
                'sortable': False,
                'toggle': False
            },
            'Instrument': {
                'title': _('Instrument'),
                'sortable': False,
                'toggle': False
            },
            'QC': {
                'title': _('QC'),
                'sortable': False,
                'toggle': False
            },
            'QCTotals': {
                'title': _('QC Samples (Analyses)'),
                'sortable': False,
                'toggle': False
            },
            'RoutineTotals': {
                'title': _('Routine Samples (Analyses)'),
                'sortable': False,
                'toggle': False
            },
            'CreationDate': {
                'title': PMF('Date Created'),
                'toggle': True,
                'index': 'created'
            },
            'state_title': {
                'title': _('State'),
                'index': 'review_state'
            },
        }
        self.review_states = [
            {
                'id':
                'default',
                'title':
                _('All'),
                'contentFilter': {
                    'portal_type': 'Worksheet',
                    'review_state': ['open', 'to_be_verified', 'verified'],
                    'sort_on': 'id',
                    'sort_order': 'reverse'
                },
                'transitions': [{
                    'id': 'retract'
                }, {
                    'id': 'verify'
                }, {
                    'id': 'reject'
                }],
                'columns': [
                    'Title', 'Priority', 'Analyst', 'Template', 'Services',
                    'SampleTypes', 'Instrument', 'QC', 'QCTotals',
                    'RoutineTotals', 'CreationDate', 'state_title'
                ]
            },
            # getAuthenticatedMember does not work in __init__
            # so 'mine' is configured further in 'folderitems' below.
            {
                'id':
                'mine',
                'title':
                _('Mine'),
                'contentFilter': {
                    'portal_type':
                    'Worksheet',
                    'review_state':
                    ['open', 'to_be_verified', 'verified', 'rejected'],
                    'sort_on':
                    'id',
                    'sort_order':
                    'reverse'
                },
                'transitions': [{
                    'id': 'retract'
                }, {
                    'id': 'verify'
                }, {
                    'id': 'reject'
                }],
                'columns': [
                    'Title', 'Priority', 'Analyst', 'Template', 'Services',
                    'SampleTypes', 'Instrument', 'QC', 'QCTotals',
                    'RoutineTotals', 'CreationDate', 'state_title'
                ]
            },
            {
                'id':
                'open',
                'title':
                _('Open'),
                'contentFilter': {
                    'portal_type': 'Worksheet',
                    'review_state': 'open',
                    'sort_on': 'id',
                    'sort_order': 'reverse'
                },
                'transitions': [],
                'columns': [
                    'Title', 'Priority', 'Analyst', 'Template', 'Services',
                    'SampleTypes', 'Instrument', 'QC', 'QCTotals',
                    'RoutineTotals', 'CreationDate', 'state_title'
                ]
            },
            {
                'id':
                'to_be_verified',
                'title':
                _('To be verified'),
                'contentFilter': {
                    'portal_type': 'Worksheet',
                    'review_state': 'to_be_verified',
                    'sort_on': 'id',
                    'sort_order': 'reverse'
                },
                'transitions': [{
                    'id': 'retract'
                }, {
                    'id': 'verify'
                }, {
                    'id': 'reject'
                }],
                'columns': [
                    'Title', 'Priority', 'Analyst', 'Template', 'Services',
                    'SampleTypes', 'Instrument', 'QC', 'QCTotals',
                    'RoutineTotals', 'CreationDate', 'state_title'
                ]
            },
            {
                'id':
                'verified',
                'title':
                _('Verified'),
                'contentFilter': {
                    'portal_type': 'Worksheet',
                    'review_state': 'verified',
                    'sort_on': 'id',
                    'sort_order': 'reverse'
                },
                'transitions': [],
                'columns': [
                    'Title', 'Priority', 'Analyst', 'Template', 'Services',
                    'SampleTypes', 'Instrument', 'QC', 'QCTotals',
                    'RoutineTotals', 'CreationDate', 'state_title'
                ]
            },
        ]
Esempio n. 16
0
from DateTime import DateTime
from AccessControl import ClassSecurityInfo
from Products.CMFCore.utils import UniqueObject
from Products.CMFCore.permissions import ListFolderContents, \
    ModifyPortalContent, View
from plone.app import folder
from Products.Archetypes.public import *
from bika.lims.content.organisation import Organisation
from bika.lims.config import ManageBika, PROJECTNAME
from bika.lims import PMF, bikaMessageFactory as _

schema = Organisation.schema.copy() + Schema((
    StringField('LabURL',
        schemata = PMF('Address'),
        write_permission = ManageBika,
        widget = StringWidget(
            size = 60,
            label = _("Lab URL"),
            description = _("The Laboratory's web address"),
        ),
    ),
    IntegerField('Confidence',
        schemata = PMF('Accreditation'),
        widget = IntegerWidget(
            label = _("Confidence Level %"),
            description = _("This value is reported at the bottom of all published results"),
        ),
    ),
    BooleanField('LaboratoryAccredited',
        default = False,
        schemata = PMF('Accreditation'),
Esempio n. 17
0
    def __init__(self, context, request):
        super(SamplesView, self).__init__(context, request)

        request.set('disable_plone.rightcolumn', 1)

        self.catalog = 'bika_catalog'
        self.contentFilter = {'portal_type': 'Sample',
                              'sort_on':'created',
                              'sort_order': 'reverse',
                              'path': {'query': "/",
                                       'level': 0 }
                              }
        # So far we will only print if the sampling workflow is activated
        if self.context.bika_setup.getSamplingWorkflowEnabled():
            self.context_actions = {
                _('Print sample sheets'): {
                    'url': 'print_sampling_sheets',
                    'icon': '++resource++bika.lims.images/print_32.png'}
                    }
        else:
                self.context_actions = {}
        self.show_sort_column = False
        self.show_select_row = False
        self.show_select_column = True
        self.allow_edit = True
        self.form_id = "samples"

        if self.view_url.find("/samples") > -1:
            self.request.set('disable_border', 1)
        else:
            self.view_url = self.view_url + "/samples"

        self.icon = self.portal_url + "/++resource++bika.lims.images/sample_big.png"
        self.title = self.context.translate(_("Samples"))
        self.description = ""
        SamplingWorkflowEnabled = self.context.bika_setup.getSamplingWorkflowEnabled()
        mtool = getToolByName(self.context, 'portal_membership')
        member = mtool.getAuthenticatedMember()
        user_is_preserver = 'Preserver' in member.getRoles()
        # Check if the filter bar functionality is activated or not
        self.filter_bar_enabled =\
            self.context.bika_setup.getDisplayAdvancedFilterBarForSamples()
        # Defined in the __init__.py
        self.columns = {
            'getSampleID': {
                'title': _('Sample ID'),
                'index': 'getSampleID'},
            'Client': {
                'title': _("Client"),
                'index': 'getClientTitle',
                'toggle': True, },
            'Creator': {
                'title': PMF('Creator'),
                'index': 'Creator',
                'toggle': True},
            'Created': {
                'title': PMF('Date Created'),
                'index': 'created',
                'toggle': False},
            'Requests': {
                'title': _('Requests'),
                'sortable': False,
                'toggle': False},
            'getClientReference': {
                'title': _('Client Ref'),
                'index': 'getClientReference',
                'toggle': True},
            'getClientSampleID': {
                'title': _('Client SID'),
                'index': 'getClientSampleID',
                'toggle': True},
            'getSampleTypeTitle': {
                'title': _('Sample Type'),
                'index': 'getSampleTypeTitle'},
            'getSamplePointTitle': {
                'title': _('Sample Point'),
                'index': 'getSamplePointTitle',
                'toggle': False},
            'getStorageLocation': {
                'sortable': False,
                'title': _('Storage Location'),
                'toggle': False},
            'SamplingDeviation': {
                'title': _('Sampling Deviation'),
                'sortable': False,
                'toggle': False},
            'AdHoc': {
                'title': _('Ad-Hoc'),
                'sortable': False,
                'toggle': False},
            'SamplingDate': {
                'title': _('Sampling Date'),
                'index': 'getSamplingDate',
                'input_class': 'datetimepicker_nofuture autosave',
                'input_width': '10',
                'toggle': SamplingWorkflowEnabled},
            'DateSampled': {
                'title': _('Date Sampled'),
                'index': 'getDateSampled',
                'toggle': True,
                'input_class': 'datetimepicker_nofuture autosave',
                'input_width': '10'},
            'getSampler': {
                'title': _('Sampler'),
                'toggle': SamplingWorkflowEnabled},
            'getScheduledSamplingSampler': {
                'title': _('Sampler for scheduled sampling'),
                'input_class': 'autosave',
                'sortable': False,
                'toggle': self.context.bika_setup.getScheduleSamplingEnabled()
                },
            'getDatePreserved': {
                'title': _('Date Preserved'),
                'toggle': user_is_preserver,
                'input_class': 'datepicker_nofuture',
                'input_width': '10'},
            'getPreserver': {
                'title': _('Preserver'),
                'toggle': user_is_preserver},
            'DateReceived': {
                'title': _('Date Received'),
                'index': 'getDateReceived',
                'toggle': False},
            'state_title': {
                'title': _('State'),
                'sortable': False,
                'index': 'review_state'},
        }

        self.review_states = [
            {'id': 'default',
             'title': _('Active'),
             'contentFilter': {'cancellation_state': 'active',
                               'sort_on': 'created'},
             'columns': ['getSampleID',
                         'Client',
                         'Creator',
                         'Created',
                         'Requests',
                         'getClientReference',
                         'getClientSampleID',
                         'getSampleTypeTitle',
                         'getSamplePointTitle',
                         'getStorageLocation',
                         'SamplingDeviation',
                         'AdHoc',
                         'SamplingDate',
                         'getScheduledSamplingSampler',
                         'DateSampled',
                         'getSampler',
                         'getDatePreserved',
                         'getPreserver',
                         'DateReceived',
                         'state_title']},
            {'id': 'to_be_sampled',
             'title': _('To be sampled'),
             'contentFilter': {'review_state': ('to_be_sampled',
                                                'scheduled_sampling'),
                               'cancellation_state': 'active',
                               'sort_on': 'created',
                               'sort_order': 'reverse'},
             'columns': ['getSampleID',
                         'Client',
                         'Requests',
                         'getClientReference',
                         'getClientSampleID',
                         'SamplingDate',
                         'getScheduledSamplingSampler',
                         'DateSampled',
                         'getSampler',
                         'getPreserver',
                         'getSampleTypeTitle',
                         'getSamplePointTitle',
                         'state_title'],
             'transitions': [
                {'id': 'schedule_sampling'}, {'id': 'sample'}],
             },
            {'id': 'sample_due',
             'title': _('Due'),
             'contentFilter': {'review_state': ('to_be_preserved',
                                                'sample_due'),
                               'sort_on': 'created',
                               'sort_order': 'reverse'},
             'columns': ['getSampleID',
                         'Client',
                         'Creator',
                         'Created',
                         'Requests',
                         'getClientReference',
                         'getClientSampleID',
                         'SamplingDate',
                         'getScheduledSamplingSampler',
                         'getScheduledSamplingSampler',
                         'DateSampled',
                         'getSampler',
                         'getDatePreserved',
                         'getPreserver',
                         'getSampleTypeTitle',
                         'getSamplePointTitle',
                         'getStorageLocation',
                         'SamplingDeviation',
                         'AdHoc',
                         'state_title']},
            {'id': 'sample_received',
             'title': _('Received'),
             'contentFilter': {'review_state':'sample_received',
                              'sort_order': 'reverse',
                              'sort_on':'created'},
             'columns': ['getSampleID',
                         'Client',
                         'Creator',
                         'Created',
                         'Requests',
                         'getClientReference',
                         'getClientSampleID',
                         'getSampleTypeTitle',
                         'getSamplePointTitle',
                         'getStorageLocation',
                         'SamplingDeviation',
                         'AdHoc',
                         'SamplingDate',
                         'getScheduledSamplingSampler',
                         'DateSampled',
                         'getSampler',
                         'getDatePreserved',
                         'getPreserver',
                         'DateReceived']},
            {'id':'expired',
             'title': _('Expired'),
             'contentFilter':{'review_state':'expired',
                              'sort_order': 'reverse',
                              'sort_on':'created'},
             'columns': ['getSampleID',
                         'Client',
                         'Creator',
                         'Created',
                         'Requests',
                         'getClientReference',
                         'getClientSampleID',
                         'getSampleTypeTitle',
                         'getSamplePointTitle',
                         'getStorageLocation',
                         'SamplingDeviation',
                         'AdHoc',
                         'SamplingDate',
                         'getScheduledSamplingSampler',
                         'DateSampled',
                         'getSampler',
                         'getDatePreserved',
                         'getPreserver',
                         'DateReceived']},
            {'id':'disposed',
             'title': _('Disposed'),
             'contentFilter':{'review_state':'disposed',
                              'sort_order': 'reverse',
                              'sort_on':'created'},
             'columns': ['getSampleID',
                         'Client',
                         'Creator',
                         'Created',
                         'Requests',
                         'getClientReference',
                         'getClientSampleID',
                         'getSampleTypeTitle',
                         'getSamplePointTitle',
                         'getStorageLocation',
                         'SamplingDeviation',
                         'AdHoc',
                         'SamplingDate',
                         'getScheduledSamplingSampler',
                         'DateSampled',
                         'getSampler',
                         'getDatePreserved',
                         'getPreserver',
                         'DateReceived']},
            {'id':'cancelled',
             'title': _('Cancelled'),
             'contentFilter': {'cancellation_state': 'cancelled',
                               'sort_order': 'reverse',
                               'sort_on':'created'},
             'transitions': [{'id':'reinstate'}, ],
             'columns': ['getSampleID',
                         'Client',
                         'Creator',
                         'Created',
                         'Requests',
                         'getClientReference',
                         'getClientSampleID',
                         'getSampleTypeTitle',
                         'getSamplePointTitle',
                         'getStorageLocation',
                         'SamplingDeviation',
                         'AdHoc',
                         'SamplingDate',
                         'getScheduledSamplingSampler',
                         'DateReceived',
                         'DateSampled',
                         'getSampler',
                         'getDatePreserved',
                         'getPreserver',
                         'state_title']},
            {'id': 'rejected',
             'title': _('Rejected'),
             'contentFilter': {'review_state': 'rejected',
                               'sort_order': 'reverse',
                               'sort_on': 'created'},
             'transitions': [],
             'columns': ['getSampleID',
                         'Client',
                         'Creator',
                         'Created',
                         'Requests',
                         'getClientReference',
                         'getClientSampleID',
                         'getSampleTypeTitle',
                         'getSamplePointTitle',
                         'getStorageLocation',
                         'SamplingDeviation',
                         'AdHoc',
                         'SamplingDate',
                         'DateReceived',
                         'getDateSampled',
                         'getSampler',
                         'getDatePreserved',
                         'getPreserver',
                         'state_title']},
        ]
Esempio n. 18
0
from bika.lims.browser.fields import InterimFieldsField
from bika.lims.browser.widgets import RecordsWidget as BikaRecordsWidget
from bika.lims.interfaces import ICalculation
from bika.lims.browser.fields import HistoryAwareReferenceField
from bika.lims.config import PROJECTNAME
from bika.lims.content.bikaschema import BikaSchema
from zope.interface import implements
from zope.site.hooks import getSite
from zExceptions import Redirect
import sys, re
from bika.lims import PMF, bikaMessageFactory as _

schema = BikaSchema.copy() + Schema((
    InterimFieldsField(
        'InterimFields',
        schemata=PMF('Calculation'),
        widget=BikaRecordsWidget(
            label=_("Calculation Interim Fields"),
            description=
            _("Define interim fields such as vessel mass, dilution factors, "
              "should your calculation require them. The field title specified "
              "here will be used as column headers and field descriptors where "
              "the interim fields are displayed"),
        )),
    HistoryAwareReferenceField(
        'DependentServices',
        schemata=PMF('Calculation'),
        required=1,
        multiValued=1,
        vocabulary_display_path_bound=sys.maxint,
        allowed_types=('AnalysisService', ),
Esempio n. 19
0
    def __call__(self):
        form = self.request.form
        plone.protect.CheckAuthenticator(form)
        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

            analyses = WorkflowAction._get_selected_items(self).values()

            if analyses:
                analyses = sorted(analyses, key=methodcaller('getRequestID'))
                for analysis in analyses:
                    if self.isAddable(analysis):
                        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. 20
0
    def _create_user(self):
        """Create a new user
        """
        def error(field, message):
            if field:
                message = "%s: %s" % (field, message)
            self.context.plone_utils.addPortalMessage(message, 'error')
            return self.request.response.redirect(self.context.absolute_url() +
                                                  "/login_details")

        form = self.request.form
        contact = self.context

        password = safe_unicode(form.get('password', '')).encode('utf-8')
        username = safe_unicode(form.get('username', '')).encode('utf-8')
        confirm = form.get('confirm', '')
        email = safe_unicode(form.get('email', '')).encode('utf-8')

        if not username:
            return error('username', PMF("Input is required but not given."))

        if not email:
            return error('email', PMF("Input is required but not given."))

        reg_tool = self.context.portal_registration
        # properties = self.context.portal_properties.site_properties
        # if properties.validate_email:
        #     password = reg_tool.generatePassword()
        # else:
        if password != confirm:
            return error('password', PMF("Passwords do not match."))

        if not password:
            return error('password', PMF("Input is required but not given."))

        if not confirm:
            return error('password', PMF("Passwords do not match."))

        if len(password) < 5:
            return error(
                'password',
                PMF("Passwords must contain at least 5 "
                    "characters."))
        # We make use of the existing controlpanel `@@usergroup-userprefs`
        # view logic to make sure we get all users from all plugins (e.g. LDAP)
        users_view = UsersOverviewControlPanel(self.context, self.request)
        users = users_view.doSearch("")
        for user in users:
            userid = user.get("id", None)
            if userid is None:
                continue
            user_obj = api.user.get(userid=userid)
            if user_obj.getUserName() == username:
                msg = "Username {} already exists, please, choose " \
                      "another one.".format(username)
                return error(None, msg)

        try:
            reg_tool.addMember(username,
                               password,
                               properties={
                                   'username': username,
                                   'email': email,
                                   'fullname': username
                               })
        except ValueError, msg:
            return error(None, msg)
Esempio n. 21
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 = bsc(UID=service_uid)[0].getObject()
                keyword = service.getKeyword()
                specs[service_uid] = {
                    "min": form["min"][0][service_uid],
                    "max": form["max"][0][service_uid],
                    "error": form["error"][0][service_uid],
                    "keyword": keyword,
                    "uid": service_uid,
                }
        else:
            for service_uid in Analyses:
                service = bsc(UID=service_uid)[0].getObject()
                keyword = service.getKeyword()
                specs[service_uid] = {"min": "", "max": "", "error": "",
                                      "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()

        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. 22
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. 23
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. 24
0
    security = ClassSecurityInfo()

LABEL_AUTO_OPTIONS = DisplayList((
    ('None', _('None')),
    ('register', _('Register')),
    ('receive', _('Receive')),
))

LABEL_AUTO_SIZES = DisplayList((
    ('small', _('Small')),
    ('normal', _('Normal')),
))

schema = BikaFolderSchema.copy() + Schema((
    IntegerField('PasswordLifetime',
        schemata = PMF("Security"),
        required = 1,
        default = 0,
        widget = IntegerWidget(
            label = _("Password lifetime"),
            description = _("The number of days before a password expires. 0 disables password expiry"),
        )
    ),
    IntegerField('AutoLogOff',
        schemata = PMF("Security"),
        required = 1,
        default = 0,
        widget = IntegerWidget(
            label = _("Automatic log-off"),
            description = _("The number of minutes before a user is automatically logged off. "
                            "0 disables automatic log-off"),
Esempio n. 25
0
                       checkbox_bound=0,
                       label=_('Default Container'),
                       description=_(
                           "Select the default container to be used for this "
                           "analysis service. If the container to be used "
                           "depends on the sample type and preservation "
                           "combination, specify the container in the sample "
                           "type table below"),
                       catalog_name='bika_setup_catalog',
                       base_query={'inactive_state': 'active'},
                   ),
    ),
    PartitionSetupField('PartitionSetup',
                        schemata='Container and Preservation',
                        widget=PartitionSetupWidget(
                            label=PMF("Preservation per sample type"),
                            description=_(
                                "Please specify preservations that differ from the "
                                "analysis service's default preservation per sample "
                                "type here."),
                        ),
    ),
))

schema['id'].widget.visible = False
schema['description'].schemata = 'Description'
schema['description'].widget.visible = True
schema['title'].required = True
schema['title'].widget.visible = True
schema['title'].schemata = 'Description'
schema.moveField('ShortTitle', after='title')
Esempio n. 26
0
    def folderitems(self, full_objects = False):
        """
        >>> portal = layer['portal']
        >>> portal_url = portal.absolute_url()
        >>> from plone.app.testing import SITE_OWNER_NAME
        >>> from plone.app.testing import SITE_OWNER_PASSWORD

        Test page batching https://github.com/bikalabs/Bika-LIMS/issues/1276
        When visiting the second page, the Water sampletype should be displayed:

        >>> browser = layer['getBrowser'](portal, loggedIn=True, username=SITE_OWNER_NAME, password=SITE_OWNER_PASSWORD)
        >>> browser.open(portal_url+"/bika_setup/bika_sampletypes/folder_view?",
        ... "list_pagesize=10&list_review_state=default&list_pagenumber=2")
        >>> browser.contents
        '...Water...'
        """

        #self.contentsMethod = self.context.getFolderContents
        if not hasattr(self, 'contentsMethod'):
            self.contentsMethod = getToolByName(self.context, self.catalog)

        context = aq_inner(self.context)
        plone_layout = getMultiAdapter((context, self.request), name = u'plone_layout')
        plone_utils = getToolByName(context, 'plone_utils')
        plone_view = getMultiAdapter((context, self.request), name = u'plone')
        portal_properties = getToolByName(context, 'portal_properties')
        portal_types = getToolByName(context, 'portal_types')
        workflow = getToolByName(context, 'portal_workflow')
        site_properties = portal_properties.site_properties
        norm = getUtility(IIDNormalizer).normalize
        if self.request.get('show_all', '').lower() == 'true' \
                or self.show_all == True \
                or self.pagesize == 0:
            show_all = True
        else:
            show_all = False

        pagenumber = int(self.request.get('pagenumber', 1) or 1)
        pagesize = self.pagesize
        start = (pagenumber - 1) * pagesize
        end = start + pagesize - 1

        if (hasattr(self, 'And') and self.And) \
           or (hasattr(self, 'Or') and self.Or):
            # if contentsMethod is capable, we do an AdvancedQuery.
            if hasattr(self.contentsMethod, 'makeAdvancedQuery'):
                aq = self.contentsMethod.makeAdvancedQuery(self.contentFilter)
                if hasattr(self, 'And') and self.And:
                    tmpAnd = And()
                    for q in self.And:
                        tmpAnd.addSubquery(q)
                    aq &= tmpAnd
                if hasattr(self, 'Or') and self.Or:
                    tmpOr = Or()
                    for q in self.Or:
                        tmpOr.addSubquery(q)
                    aq &= tmpOr
                brains = self.contentsMethod.evalAdvancedQuery(aq)
            else:
                # otherwise, self.contentsMethod must handle contentFilter
                brains = self.contentsMethod(self.contentFilter)
        else:
            brains = self.contentsMethod(self.contentFilter)

        results = []
        self.page_start_index = 0
        current_index = -1
        for i, obj in enumerate(brains):
            # we don't know yet if it's a brain or an object
            path = hasattr(obj, 'getPath') and obj.getPath() or \
                 "/".join(obj.getPhysicalPath())

            if hasattr(obj, 'getObject'):
                obj = obj.getObject()

            # check if the item must be rendered or not (prevents from
            # doing it later in folderitems) and dealing with paging
            if not self.isItemAllowed(obj):
                continue

            # avoid creating unnecessary info for items outside the current
            # batch;  only the path is needed for the "select all" case...
            # we only take allowed items into account
            current_index += 1
            if not show_all and not (start <= current_index <= end):
                results.append(dict(path = path, uid = obj.UID()))
                continue

            uid = obj.UID()
            title = obj.Title()
            description = obj.Description()
            icon = plone_layout.getIcon(obj)
            url = obj.absolute_url()
            relative_url = obj.absolute_url(relative = True)

            fti = portal_types.get(obj.portal_type)
            if fti is not None:
                type_title_msgid = fti.Title()
            else:
                type_title_msgid = obj.portal_type

            url_href_title = '%s at %s: %s' % (
                t(type_title_msgid),
                path,
                to_utf8(description))

            modified = self.ulocalized_time(obj.modified()),

            # element css classes
            type_class = 'contenttype-' + \
                plone_utils.normalizeString(obj.portal_type)

            state_class = ''
            states = {}
            for w in workflow.getWorkflowsFor(obj):
                state = w._getWorkflowStateOf(obj).id
                states[w.state_var] = state
                state_class += "state-%s " % state

            results_dict = dict(
                obj = obj,
                id = obj.getId(),
                title = title,
                uid = uid,
                path = path,
                url = url,
                fti = fti,
                item_data = json.dumps([]),
                url_href_title = url_href_title,
                obj_type = obj.Type,
                size = obj.getObjSize,
                modified = modified,
                icon = icon.html_tag(),
                type_class = type_class,
                # a list of lookups for single-value-select fields
                choices = {},
                state_class = state_class,
                relative_url = relative_url,
                view_url = url,
                table_row_class = "",
                category = 'None',

                # a list of names of fields that may be edited on this item
                allow_edit = [],

                # a list of names of fields that are compulsory (if editable)
                required = [],

                # "before", "after" and replace: dictionary (key is column ID)
                # A snippet of HTML which will be rendered
                # before/after/instead of the table cell content.
                before = {}, # { before : "<a href=..>" }
                after = {},
                replace = {},
            )
            try:
                self.review_state = workflow.getInfoFor(obj, 'review_state')
                state_title = workflow.getTitleForStateOnType(
                    self.review_state, obj.portal_type)
                state_title = t(PMF(state_title))
            except:
                self.review_state = 'active'
                state_title = None
            if self.review_state:
                results_dict['review_state'] = self.review_state
            for state_var, state in states.items():
                if not state_title:
                    state_title = workflow.getTitleForStateOnType(
                        state, obj.portal_type)
                results_dict[state_var] = state
            results_dict['state_title'] = state_title

            # extra classes for individual fields on this item { field_id : "css classes" }
            results_dict['class'] = {}
            for name, adapter in getAdapters((obj, ), IFieldIcons):
                auid = obj.UID() if hasattr(obj, 'UID') and callable(obj.UID) else None
                if not auid:
                    continue
                alerts = adapter()
                # logger.info(str(alerts))
                if alerts and auid in alerts:
                    if auid in self.field_icons:
                        self.field_icons[auid].extend(alerts[auid])
                    else:
                        self.field_icons[auid] = alerts[auid]

            # Search for values for all columns in obj
            for key in self.columns.keys():
                if hasattr(obj, key):
                    # if the key is already in the results dict
                    # then we don't replace it's value
                    if results_dict.has_key(key):
                        continue
                    value = getattr(obj, key)
                    if callable(value):
                        value = value()
                    results_dict[key] = value
            results.append(results_dict)

        return results
Esempio n. 27
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. 28
0
    def get_workflow_actions(self):
        """ Compile a list of possible workflow transitions for items
            in this Table.
        """

        # cbb return empty list if we are unable to select items
        if not self.show_select_column:
            return []

        workflow = getToolByName(self.context, 'portal_workflow')


        # check POST for a specified review_state selection
        selected_state = self.request.get("%s_review_state"%self.form_id,
                                          'default')
        # get review_state id=selected_state
        states = [r for r in self.review_states
                  if r['id'] == selected_state]
        self.review_state = states and states[0] \
            or self.review_states[0]

        # get all transitions for all items.
        transitions = {}
        actions = []
        for obj in [i.get('obj', '') for i in self.items]:
            obj = hasattr(obj, 'getObject') and obj.getObject() or obj
            for it in workflow.getTransitionsFor(obj):
                transitions[it['id']] = it

        # the list is restricted to and ordered by these transitions.
        if 'transitions' in self.review_state:
            for transition_dict in self.review_state['transitions']:
                if transition_dict['id'] in transitions:
                    actions.append(transitions[transition_dict['id']])
        else:
            actions = transitions.values()

        new_actions = []
        # remove any invalid items with a warning
        for a,action in enumerate(actions):
            if isinstance(action, dict) \
                    and 'id' in action:
                new_actions.append(action)
            else:
                logger.warning("bad action in custom_actions: %s. (complete list: %s)."%(action,actions))

        # and these are removed
        if 'hide_transitions' in self.review_state:
            actions = [a for a in actions
                       if a['id'] not in self.review_state['hide_transitions']]

        # cheat: until workflow_action is abolished, all URLs defined in
        # GS workflow setup will be ignored, and the default will apply.
        # (that means, WorkflowAction-bound URL is called).
        for i, action in enumerate(actions):
            actions[i]['url'] = ''

        # if there is a self.review_state['some_state']['custom_actions'] attribute
        # on the BikaListingView, add these actions to the list.
        if 'custom_actions' in self.review_state:
            for action in self.review_state['custom_actions']:
                if isinstance(action, dict) \
                        and 'id' in action:
                    actions.append(action)

        for a,action in enumerate(actions):
            actions[a]['title'] = t(PMF(actions[a]['id'] + "_transition_title"))
        return actions
Esempio n. 29
0
 def translate(id):
     return t(PMF(id + "_transition_title"))
Esempio n. 30
0
    def get_workflow_actions(self):
        """ Compile a list of possible workflow transitions for items
            in this Table.
        """

        # cbb return empty list if we are unable to select items
        if not self.bika_listing.show_select_column:
            return []

        workflow = getToolByName(self.context, 'portal_workflow')
        # get all transitions for all items.
        transitions = {}
        actions = []
        for obj in [i.get('obj', '') for i in self.items]:
            obj = get_object(obj)
            for it in workflow.getTransitionsFor(obj):
                transitions[it['id']] = it

        # the list is restricted to and ordered by these transitions.
        if 'transitions' in self.bika_listing.review_state:
            for tdict in self.bika_listing.review_state['transitions']:
                if tdict['id'] in transitions:
                    actions.append(transitions[tdict['id']])
        else:
            actions = transitions.values()

        new_actions = []
        # remove any invalid items with a warning
        for a, action in enumerate(actions):
            if isinstance(action, dict) \
                    and 'id' in action:
                new_actions.append(action)
            else:
                logger.warning(
                    "bad action in review_state['transitions']: %s. "
                    "(complete list: %s)." % (action, actions))
        actions = new_actions

        # and these are removed
        if 'hide_transitions' in self.bika_listing.review_state:
            hidden_transitions = self.bika_listing.review_state[
                'hide_transitions']
            actions = [a for a in actions if a['id'] not in hidden_transitions]

        # cheat: until workflow_action is abolished, all URLs defined in
        # GS workflow setup will be ignored, and the default will apply.
        # (that means, WorkflowAction-bound URL is called).
        for i, action in enumerate(actions):
            actions[i]['url'] = ''

        # if there is a self.review_state['some_state']['custom_transitions']
        # attribute on the BikaListingView, add these actions to the list.
        if 'custom_transitions' in self.bika_listing.review_state:
            for action in self.bika_listing.review_state['custom_transitions']:
                if isinstance(action, dict) and 'id' in action:
                    actions.append(action)

        for a, action in enumerate(actions):
            actions[a]['title'] = t(PMF(actions[a]['title']))

        return actions