示例#1
0
文件: create.py 项目: doun/Bika-LIMS
    def get_specs_from_request(self):
        """Specifications for analyses are given on the request in *Spec

        >>> portal = layer['portal']
        >>> portal_url = portal.absolute_url()
        >>> from plone.app.testing import SITE_OWNER_NAME
        >>> from plone.app.testing import SITE_OWNER_PASSWORD

        >>> browser = layer['getBrowser'](portal, loggedIn=True, username=SITE_OWNER_NAME, password=SITE_OWNER_PASSWORD)
        >>> browser.open(portal_url+"/@@API/create", "&".join([
        ... "obj_type=AnalysisRequest",
        ... "thing=Fish",
        ... "Client=portal_type:Client|id:client-1",
        ... "SampleType=portal_type:SampleType|title:Apple Pulp",
        ... "Contact=portal_type:Contact|getFullname:Rita Mohale",
        ... "Services:list=portal_type:AnalysisService|title:Calcium",
        ... "Services:list=portal_type:AnalysisService|title:Copper",
        ... "Services:list=portal_type:AnalysisService|title:Magnesium",
        ... "SamplingDate=2013-09-29",
        ... "AR_Specification=portal_type:AnalysisSpec|title:Apple Pulp",
        ... "Analysis_Specification:list=Cu:5:10:10",
        ... "Analysis_Specification:list=Mg:6:11:11"
        ... ]))
        >>> browser.contents
        '{...The following request fields were not used: ...thing...}'

        """

        context = self.context
        request = self.request
        brains = resolve_request_lookup(context, request, "AR_Specification")
        kwspecs = brains[0].getObject().getResultsRangeDict() if brains else {}
        Analysis_Specification = self.request.get("Analysis_Specification", "")
        self.used("AR_Specification")
        self.used("Analysis_Specification")
        if not kwspecs and not Analysis_Specification:
            return {}

        specs = {}
        bsc = getToolByName(context, "bika_setup_catalog")
        for k, v in kwspecs.items():
            uid = bsc(portal_type="AnalysisService", getKeyword=k)[0].UID
            specs[uid] = v

        if Analysis_Specification:
            for string in Analysis_Specification:
                keyword, Min, Max, error = string.split(":")
                brains = bsc(portal_type="AnalysisService", getKeyword=keyword)
                if not brains:
                    raise BadRequest("Service not found: %s" % keyword)
                specs[brains[0].UID] = {
                    "min": Min,
                    "max": Max,
                    "error": error,
                }
        return specs
示例#2
0
    def get_specs_from_request(self):
        """Specifications for analyses are given on the request in *Spec

        >>> portal = layer['portal']
        >>> portal_url = portal.absolute_url()
        >>> from plone.app.testing import SITE_OWNER_NAME
        >>> from plone.app.testing import SITE_OWNER_PASSWORD

        >>> browser = layer['getBrowser'](portal, loggedIn=True, username=SITE_OWNER_NAME, password=SITE_OWNER_PASSWORD)
        >>> browser.open(portal_url+"/@@API/create", "&".join([
        ... "obj_type=AnalysisRequest",
        ... "thing=Fish",
        ... "Client=portal_type:Client|id:client-1",
        ... "SampleType=portal_type:SampleType|title:Apple Pulp",
        ... "Contact=portal_type:Contact|getFullname:Rita Mohale",
        ... "Services:list=portal_type:AnalysisService|title:Calcium",
        ... "Services:list=portal_type:AnalysisService|title:Copper",
        ... "Services:list=portal_type:AnalysisService|title:Magnesium",
        ... "SamplingDate=2013-09-29",
        ... "AR_Specification=portal_type:AnalysisSpec|title:Apple Pulp",
        ... "Analysis_Specification:list=Cu:5:10:10",
        ... "Analysis_Specification:list=Mg:6:11:11"
        ... ]))
        >>> browser.contents
        '{...The following request fields were not used: ...thing...}'

        """

        context = self.context
        request = self.request
        brains = resolve_request_lookup(context, request, "AR_Specification")
        kwspecs = brains[0].getObject().getResultsRangeDict() if brains else {}
        Analysis_Specification = self.request.get("Analysis_Specification", "")
        self.used("AR_Specification")
        self.used("Analysis_Specification")
        if not kwspecs and not Analysis_Specification:
            return {}

        specs = {}
        bsc = getToolByName(context, "bika_setup_catalog")
        for k, v in kwspecs.items():
            uid = bsc(portal_type="AnalysisService", getKeyword=k)[0].UID
            specs[uid] = v

        if Analysis_Specification:
            for string in Analysis_Specification:
                keyword, Min, Max, error = string.split(":")
                brains = bsc(portal_type="AnalysisService", getKeyword=keyword)
                if not brains:
                    raise BadRequest("Service not found: %s" % keyword)
                specs[brains[0].UID] = {"min": Min, "max": Max, "error": error}
        return specs
示例#3
0
    def get_specs_from_request(self, dicts_to_dict_rr=None):
        """Specifications for analyses are given on the request in *Spec

        >>> portal = layer['portal']
        >>> portal_url = portal.absolute_url()
        >>> from plone.app.testing import SITE_OWNER_NAME
        >>> from plone.app.testing import SITE_OWNER_PASSWORD

        >>> browser = layer['getBrowser'](portal, loggedIn=True, username=SITE_OWNER_NAME, password=SITE_OWNER_PASSWORD)
        >>> browser.open(portal_url+"/@@API/create", "&".join([
        ... "obj_type=AnalysisRequest",
        ... "Client=portal_type:Client|id:client-1",
        ... "SampleType=portal_type:SampleType|title:Apple Pulp",
        ... "Contact=portal_type:Contact|getFullname:Rita Mohale",
        ... "Services:list=portal_type:AnalysisService|title:Calcium",
        ... "Services:list=portal_type:AnalysisService|title:Copper",
        ... "Services:list=portal_type:AnalysisService|title:Magnesium",
        ... "SamplingDate=2013-09-29",
        ... "Specification=portal_type:AnalysisSpec|title:Apple Pulp",
        ... 'ResultsRange=[{"keyword":"Cu","min":5,"max":10,"error":10},{"keyword":"Mg","min":6,"max":11,"error":11}]',
        ... ]))
        >>> browser.contents
        '{..."success": true...}'

        """

        # valid output for ResultsRange goes here.
        specs = []

        context = self.context
        request = self.request
        brains = resolve_request_lookup(context, request, "Specification")
        spec_rr = brains[0].getObject().getResultsRange() if brains else {}
        spec_rr = dicts_to_dict(spec_rr, 'keyword')
        #
        bsc = getToolByName(context, "bika_setup_catalog")
        req_rr = request.get('ResultsRange', "[]")
        try:
            req_rr = json.loads(req_rr)
        except:
            raise BadRequest("Invalid value for ResultsRange (%s)"%req_rr)
        req_rr = dicts_to_dict(req_rr, 'keyword')
        #
        spec_rr.update(req_rr)

        return spec_rr.values()
示例#4
0
    def _create_ar(self, context, request):
        """Creates AnalysisRequest object, with supporting Sample, Partition
        and Analysis objects.  The client is retrieved from the obj_path
        key in the request.

        Required request parameters:

            - Contact: One client contact Fullname.  The contact must exist
              in the specified client.  The first Contact with the specified
              value in it's Fullname field will be used.

            - SampleType_<index> - Must be an existing sample type.

        Optional request parameters:

        - CCContacts: A list of contact Fullnames, which will be copied on
          all messages related to this AR and it's sample or results.

        - CCEmails: A list of email addresses to include as above.

        - Sample_id: Create a secondary AR with an existing sample.  If
          unspecified, a new sample is created.

        - Specification: a lookup to set Analysis specs default values
          for all analyses

        - Analysis_Specification: specs (or overrides) per analysis, using
          a special lookup format.

            &Analysis_Specification:list=<Keyword>:min:max:error&...


        """

        wftool = getToolByName(context, 'portal_workflow')
        bc = getToolByName(context, 'bika_catalog')
        bsc = getToolByName(context, 'bika_setup_catalog')
        pc = getToolByName(context, 'portal_catalog')
        ret = {
            "url": router.url_for("create", force_external=True),
            "success": True,
            "error": False,
        }
        SamplingWorkflowEnabled = context.bika_setup.getSamplingWorkflowEnabled()
        for field in [
            'Client',
            'SampleType',
            'Contact',
            'SamplingDate',
            'Services']:
            self.require(field)
            self.used(field)

        try:
            client = resolve_request_lookup(context, request, 'Client')[0].getObject()
        except IndexError:
            raise Exception("Client not found")

        # Sample_id
        if 'Sample' in request:
            try:
                sample = resolve_request_lookup(context, request, 'Sample')[0].getObject()
            except IndexError:
                raise Exception("Sample not found")
        else:
            # Primary AR
            sample = _createObjectByType("Sample", client, tmpID())
            sample.unmarkCreationFlag()
            fields = set_fields_from_request(sample, request)
            for field in fields:
                self.used(field)
            sample._renameAfterCreation()
            sample.setSampleID(sample.getId())
            event.notify(ObjectInitializedEvent(sample))
            sample.at_post_create_script()

            if SamplingWorkflowEnabled:
                wftool.doActionFor(sample, 'sampling_workflow')
            else:
                wftool.doActionFor(sample, 'no_sampling_workflow')

        ret['sample_id'] = sample.getId()

        parts = [{'services': [],
                  'container': [],
                  'preservation': '',
                  'separate': False}]

        specs = self.get_specs_from_request()
        ar = _createObjectByType("AnalysisRequest", client, tmpID())
        ar.unmarkCreationFlag()
        fields = set_fields_from_request(ar, request)
        for field in fields:
            self.used(field)
        ar.setSample(sample.UID())
        ar._renameAfterCreation()
        ret['ar_id'] = ar.getId()
        brains = resolve_request_lookup(context, request, 'Services')
        service_uids = [p.UID for p in brains]
        new_analyses = ar.setAnalyses(service_uids, specs=specs)
        ar.setRequestID(ar.getId())
        ar.reindexObject()
        event.notify(ObjectInitializedEvent(ar))
        ar.at_post_create_script()

        # Create sample partitions
        parts_and_services = {}
        for _i in range(len(parts)):
            p = parts[_i]
            part_prefix = sample.getId() + "-P"
            if '%s%s' % (part_prefix, _i + 1) in sample.objectIds():
                parts[_i]['object'] = sample['%s%s' % (part_prefix, _i + 1)]
                parts_and_services['%s%s' % (part_prefix, _i + 1)] = p['services']
                part = parts[_i]['object']
            else:
                part = _createObjectByType("SamplePartition", sample, tmpID())
                parts[_i]['object'] = part
                container = None
                preservation = p['preservation']
                parts[_i]['prepreserved'] = False
                part.edit(
                    Container=container,
                    Preservation=preservation,
                )
                part.processForm()
                if SamplingWorkflowEnabled:
                    wftool.doActionFor(part, 'sampling_workflow')
                else:
                    wftool.doActionFor(part, 'no_sampling_workflow')
                parts_and_services[part.id] = p['services']

        if SamplingWorkflowEnabled:
            wftool.doActionFor(ar, 'sampling_workflow')
        else:
            wftool.doActionFor(ar, 'no_sampling_workflow')

        # Add analyses to sample partitions
        # XXX jsonapi create AR: right now, all new analyses are linked to the first samplepartition
        if new_analyses:
            analyses = list(part.getAnalyses())
            analyses.extend(new_analyses)
            part.edit(
                Analyses=analyses,
            )
            for analysis in new_analyses:
                analysis.setSamplePartition(part)

        # If Preservation is required for some partitions,
        # and the SamplingWorkflow is disabled, we need
        # to transition to to_be_preserved manually.
        if not SamplingWorkflowEnabled:
            to_be_preserved = []
            sample_due = []
            lowest_state = 'sample_due'
            for p in sample.objectValues('SamplePartition'):
                if p.getPreservation():
                    lowest_state = 'to_be_preserved'
                    to_be_preserved.append(p)
                else:
                    sample_due.append(p)
            for p in to_be_preserved:
                doActionFor(p, 'to_be_preserved')
            for p in sample_due:
                doActionFor(p, 'sample_due')
            doActionFor(sample, lowest_state)
            for analysis in ar.objectValues('Analysis'):
                doActionFor(analysis, lowest_state)
            doActionFor(ar, lowest_state)

        # receive secondary AR
        if request.get('Sample_id', ''):
            doActionFor(ar, 'sampled')
            doActionFor(ar, 'sample_due')
            not_receive = ['to_be_sampled', 'sample_due', 'sampled',
                           'to_be_preserved']
            sample_state = wftool.getInfoFor(sample, 'review_state')
            if sample_state not in not_receive:
                doActionFor(ar, 'receive')
            for analysis in ar.getAnalyses(full_objects=1):
                doActionFor(analysis, 'sampled')
                doActionFor(analysis, 'sample_due')
                if sample_state not in not_receive:
                    doActionFor(analysis, 'receive')

        if self.unused:
            raise BadRequest("The following request fields were not used: %s.  Request aborted." % self.unused)

        return ret