Exemple #1
0
class JSONReadExtender(object):
    """- Adds the full details of all analyses to the AR.Analyses field
    """

    implements(IJSONReadExtender)
    adapts(IAnalysisRequest)

    def __init__(self, context):
        self.context = context

    def ar_analysis_values(self):
        ret = []
        analyses = self.context.getAnalyses(cancellation_state='active')
        for proxy in analyses:
            analysis = proxy.getObject()
            service = analysis.getService()
            if proxy.review_state == 'retracted':
                # these are scraped up when Retested analyses are found below.
                continue
            # things that are manually inserted into the analysis.
            # These things will be included even if they are not present in
            # include_fields in the request.
            method = analysis.getMethod()
            if not method:
                method = service.getMethod()
            service = analysis.getService()
            analysis_data = {
                "Uncertainty": service.getUncertainty(analysis.getResult()),
                "Method": method.Title() if method else '',
                "Unit": service.getUnit(),
            }
            # Place all schema fields ino the result.
            analysis_data.update(load_brain_metadata(proxy, []))
            # Place all schema fields ino the result.
            analysis_data.update(load_field_values(analysis, []))
            # call any adapters that care to modify the Analysis data.
            # adapters = getAdapters((analysis, ), IJSONReadExtender)
            # for name, adapter in adapters:
            #     adapter(request, analysis_data)
            if not self.include_fields or "transitions" in self.include_fields:
                analysis_data['transitions'] = get_workflow_actions(analysis)
            if analysis.getRetested():
                retracted = self.context.getAnalyses(review_state='retracted',
                                                     title=analysis.Title(),
                                                     full_objects=True)
                prevs = sorted(retracted, key=lambda item: item.created())
                prevs = [{
                    'created': str(p.created()),
                    'Result': p.getResult(),
                    'InterimFields': p.getInterimFields()
                } for p in prevs]
                analysis_data['Previous Results'] = prevs
            ret.append(analysis_data)
        return ret

    def __call__(self, request, data):
        self.request = request
        self.include_fields = get_include_fields(request)
        if not self.include_fields or "Analyses" in self.include_fields:
            data['Analyses'] = self.ar_analysis_values()
Exemple #2
0
class ResultOutOfRange(object):
    """Return alerts for any analyses inside the context ar
    """
    implements(IFieldIcons)
    adapts(IAnalysisRequest)

    def __init__(self, context):
        self.context = context

    def __call__(self, result=None, **kwargs):
        workflow = getToolByName(self.context, 'portal_workflow')
        items = self.context.getAnalyses()
        field_icons = {}
        for obj in items:
            obj = obj.getObject() if hasattr(obj, 'getObject') else obj
            uid = obj.UID()
            astate = workflow.getInfoFor(obj, 'review_state')
            if astate == 'retracted':
                continue
            adapters = getAdapters((obj, ), IFieldIcons)
            for name, adapter in adapters:
                alerts = adapter(obj)
                if alerts:
                    if uid in field_icons:
                        field_icons[uid].extend(alerts[uid])
                    else:
                        field_icons[uid] = alerts[uid]
        return field_icons
Exemple #3
0
class JSONReadExtender(object):
    """Adds the UID to the ResultsRange dict.  This will go away
    when we stop using keywords for this stuff.
    """

    implements(IJSONReadExtender)
    adapts(IAnalysisSpec)

    def __init__(self, context):
        self.context = context

    def __call__(self, request, data):
        bsc = self.context.bika_setup_catalog
        rr = []
        for i, x in enumerate(data.get("ResultsRange", [])):
            keyword = x.get("keyword")
            proxies = bsc(portal_type="AnalysisService", getKeyword=keyword)
            if proxies:
                data['ResultsRange'][i]['uid'] = proxies[0].UID
Exemple #4
0
class CalculationResultAlerts(object):
    """This uses IAnalysis.ResultOutOfRange on values in request.
    To validate results at ajax calculation time, make more adapters like this
    one, from IFieldIcons.  Any existing IAnalysis/IFieldIcon adapters
    (AnalysisOutOfRange) have already been called.
    """

    adapts(IAnalysis)
    implements(IFieldIcons)

    def __init__(self, context):
        self.context = context

    def __call__(self, result=None, specification=None, **kwargs):
        workflow = getToolByName(self.context, 'portal_workflow')
        astate = workflow.getInfoFor(self.context, 'review_state')
        if astate == 'retracted':
            return {}
        result = self.context.getResult() if result is None else result
        alerts = {}
        path = '++resource++bika.lims.images'
        uid = self.context.UID()
        try:
            indet = result.startswith("<") or result.startswith(">")
        except AttributeError:
            indet = False
        if indet:
            alert = {
                'field': 'Result',
                'icon': path + '/exclamation.png',
                'msg': t(_("Indeterminate result"))
            }
            if uid in alerts:
                alerts[uid].append(alert)
            else:
                alerts[uid] = [
                    alert,
                ]
        return alerts
Exemple #5
0
class JSONReadExtender(object):
    """- Adds the specification from Analysis Request to Analysis in JSON response
    """

    implements(IJSONReadExtender)
    adapts(IAnalysis)

    def __init__(self, context):
        self.context = context

    def analysis_specification(self):
        ar = self.context.aq_parent
        rr = dicts_to_dict(ar.getResultsRange(), 'keyword')

        return rr[self.context.getService().getKeyword()]

    def __call__(self, request, data):
        self.request = request
        self.include_fields = get_include_fields(request)
        if not self.include_fields or "specification" in self.include_fields:
            data['specification'] = self.analysis_specification()
        return data
Exemple #6
0
class JSONReadExtender(object):
    """- Place additional information about profile services
    into the returned records.
    Used in AR Add to prevent extra requests
    """

    implements(IJSONReadExtender)
    adapts(IAnalysisProfile)

    def __init__(self, context):
        self.context = context

    def __call__(self, request, data):
        service_data = []
        for service in self.context.getService():
            this_service = {'UID': service.UID(),
                            'Title': service.Title(),
                            'Keyword': service.getKeyword(),
                            'Price': service.getPrice(),
                            'VAT': service.getVAT(),
                            'PointOfCapture': service.getPointOfCapture(),
                            'CategoryTitle': service.getCategory().Title()}
            service_data.append(this_service)
        data['service_data'] = service_data
Exemple #7
0
class JSONReadExtender(object):
    """- Place additional information about profile services
    into the returned records.
    Used in AR Add to prevent extra requests
    """

    implements(IJSONReadExtender)
    adapts(IARTemplate)

    def __init__(self, context):
        self.context = context

    def render_template_partitions(self):
        """
        Supplies a more detailed view of the Partitions for this
        template.  It's built to mimic the partitions that are stored in the
        ar_add form state variable, so that when a partition is chosen, there
        is no further translation necessary.

        It combines the Analyses and Partitions AT schema field values.

        For some fields (separate, minvol) there is no information, when partitions
        are specified in the AR Template.

        :return a list of dictionaries like this:

            container
                     []
            container_titles
                     []
            preservation
                     []
            preservation_titles
                     []
            separate
                     false
            minvol
                     "0.0000 m3 "
            services
                     ["2fdc040e05bb42ca8b52e41761fdb795", 6 more...]
            service_titles
                     ["Copper", "Iron", "Magnesium", 4 more...]

        """
        Analyses = self.context.Schema()['Analyses'].get(self.context)
        Parts = self.context.Schema()['Partitions'].get(self.context)
        if not Parts:
            # default value copied in from content/artemplate.py
            Parts = [{'part_id': 'part-1',
                      'Container': '',
                      'Preservation': '',
                      'container_uid': '',
                      'preservation_uid': ''}]
        parts = []
        not_found = set()
        for Part in Parts:
            part = {
                'part_id': Part.get("part_id", "part-1"),
                'container_titles': Part.get("Container", ""),
                'container': Part.get("container_uid", ""),
                'preservation_titles': Part.get("Preservation", ""),
                'preservation': Part.get("preservation_uid", ""),
                'services': [],
                'service_titles': [],
            }
            for analysis in Analyses:
                uid = analysis['service_uid']
                partiton = analysis['partition']
                if partiton == part['part_id']:
                    part['services'].append(uid)
                    part['service_titles'].append(uid)
                    not_found.discard(analysis['service_uid'])
                else:
                    if uid in part['services']:
                        part['services'].remove(uid)
                    if uid in part['service_titles']:
                        part['service_titles'].remove(uid)
                    not_found.add(analysis['service_uid'])

            parts.append(part)

        # all others go into the first part.  Mostly this will be due to
        # partition info not being defined?
        for uid in not_found:
            if uid not in part['services']:
                parts[0]['services'].append(uid)
            if uid not in part['service_titles']:
               parts[0]['service_titles'].append(uid)

        return parts

    def __call__(self, request, data):
        bsc = self.context.bika_setup_catalog
        service_data = []
        for item in self.context.getAnalyses():
            service_uid = item['service_uid']
            service = bsc(UID=service_uid)[0].getObject()
            this_service = {'UID': service.UID(),
                            'Title': service.Title(),
                            'Keyword': service.getKeyword(),
                            'Price': service.getPrice(),
                            'VAT': service.getVAT(),
                            'PointOfCapture': service.getPointOfCapture(),
                            'CategoryTitle': service.getCategory().Title()}
            service_data.append(this_service)
        data['service_data'] = service_data
        data['Partitions'] = self.render_template_partitions()
Exemple #8
0
class JSONReadExtender(object):
    """- Adds fields to Analysis Service:

    ServiceDependencies - services our calculation depends on
    ServiceDependants - services who's calculation depend on us
    MethodInstruments - A dictionary of instruments:
        keys: Method UID
        values: list of instrument UIDs

    """

    implements(IJSONReadExtender)
    adapts(IAnalysisService)

    def __init__(self, context):
        self.context = context

    def service_info(self, service):
        ret = {
            "Category":
            service.getCategory().Title(),
            "Category_uid":
            service.getCategory().UID(),
            "Service":
            service.Title(),
            "Service_uid":
            service.UID(),
            "Keyword":
            service.getKeyword(),
            "PointOfCapture":
            service.getPointOfCapture(),
            "PointOfCapture_title":
            POINTS_OF_CAPTURE.getValue(service.getPointOfCapture()),
        }
        return ret

    def __call__(self, request, data):
        include_fields = get_include_fields(request)

        if not include_fields or "ServiceDependencies" in include_fields:
            data["ServiceDependencies"] = []
            calc = self.context.getCalculation()
            if calc:
                services = [
                    self.service_info(service)
                    for service in calc.getCalculationDependencies(flat=True)
                    if service.UID() != self.context.UID()
                ]
                data["ServiceDependencies"] = services

        if not include_fields or "ServiceDependants" in include_fields:
            data["ServiceDependants"] = []
            calcs = self.context.getBackReferences(
                'CalculationAnalysisService')
            if calcs:
                for calc in calcs:
                    services = [
                        self.service_info(service)
                        for service in calc.getCalculationDependants()
                        if service.UID() != self.context.UID()
                    ]
                    data["ServiceDependants"].extend(services)

        if not include_fields or "MethodInstruments" in include_fields:
            data["MethodInstruments"] = {}
            for method in self.context.getAvailableMethods():
                for instrument in method.getInstruments():
                    if method.UID() not in data["MethodInstruments"]:
                        data["MethodInstruments"][method.UID()] = []
                    data["MethodInstruments"][method.UID()].append(
                        load_field_values(instrument, include_fields=[]))