| 1 |  |  | # -*- coding: utf-8 -*- | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  | # | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  | # This file is part of SENAITE.CORE. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  | # | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  | # SENAITE.CORE is free software: you can redistribute it and/or modify it under | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  | # the terms of the GNU General Public License as published by the Free Software | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  | # Foundation, version 2. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  | # | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  | # This program is distributed in the hope that it will be useful, but WITHOUT | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  | # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  | # details. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  | # | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  | # You should have received a copy of the GNU General Public License along with | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  | # this program; if not, write to the Free Software Foundation, Inc., 51 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  | # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  | # | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  | # Copyright 2018-2021 by it's authors. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  | # Some rights reserved, see README and LICENSE. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  | import json | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  | from collections import OrderedDict | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  | from copy import copy | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  | from copy import deepcopy | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  | from operator import itemgetter | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  | from bika.lims import api | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  | from bika.lims import bikaMessageFactory as _ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  | from bika.lims import FieldEditAnalysisConditions | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  | from bika.lims import logger | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  | from bika.lims.api.analysis import get_formatted_interval | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  | from bika.lims.api.analysis import is_out_of_range | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  | from bika.lims.api.analysis import is_result_range_compliant | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 |  |  | from bika.lims.config import LDL | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  | from bika.lims.config import UDL | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 |  |  | from bika.lims.interfaces import IAnalysisRequest | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 |  |  | from bika.lims.interfaces import IFieldIcons | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 |  |  | from bika.lims.interfaces import IRoutineAnalysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 |  |  | from bika.lims.interfaces import IReferenceAnalysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  | from bika.lims.permissions import EditFieldResults | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 |  |  | from bika.lims.permissions import EditResults | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 |  |  | from bika.lims.permissions import FieldEditAnalysisHidden | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 |  |  | from bika.lims.permissions import FieldEditAnalysisResult | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 |  |  | from bika.lims.permissions import TransitionVerify | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  | from bika.lims.permissions import ViewResults | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 |  |  | from bika.lims.permissions import ViewRetractedAnalyses | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 |  |  | from bika.lims.utils import check_permission | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  | from bika.lims.utils import format_supsub | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 |  |  | from bika.lims.utils import formatDecimalMark | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 |  |  | from bika.lims.utils import get_image | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  | from bika.lims.utils import get_link | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  | from bika.lims.utils import get_link_for | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  | from bika.lims.utils import t | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  | from bika.lims.utils.analysis import format_uncertainty | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  | from DateTime import DateTime | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  | from plone.memoize import view as viewcache | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  | from Products.Archetypes.config import REFERENCE_CATALOG | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  | from Products.CMFPlone.utils import safe_unicode | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 |  |  | from senaite.app.listing import ListingView | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 |  |  | from senaite.core.catalog import ANALYSIS_CATALOG | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 |  |  | from senaite.core.catalog import SETUP_CATALOG | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 |  |  | from zope.component import getAdapters | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 |  |  | from zope.component import getMultiAdapter | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 |  |  | class AnalysesView(ListingView): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 |  |  |     """Displays a list of Analyses in a table. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  |     Visible InterimFields from all analyses are added to self.columns[]. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 |  |  |     Keyword arguments are passed directly to senaite_catalog_analysis. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 |  |  |     """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  |     def __init__(self, context, request, **kwargs): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  |         super(AnalysesView, self).__init__(context, request, **kwargs) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 |  |  |         # prepare the content filter of this listing | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  |         self.contentFilter = dict(kwargs) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 |  |  |         self.contentFilter.update({ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 |  |  |             "portal_type": "Analysis", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  |             "sort_on": "sortable_title", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 |  |  |             "sort_order": "ascending", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 |  |  |         }) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  |         # set the listing view config | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  |         self.catalog = ANALYSIS_CATALOG | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  |         self.sort_order = "ascending" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  |         self.context_actions = {} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  |         self.show_select_row = False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 |  |  |         self.show_select_column = False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 |  |  |         self.show_column_toggles = False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 |  |  |         self.pagesize = 9999999 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |         self.form_id = "analyses_form" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 |  |  |         self.context_active = api.is_active(context) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 |  |  |         self.interim_fields = {} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  |         self.interim_columns = OrderedDict() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  |         self.specs = {} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 |  |  |         self.bsc = api.get_tool(SETUP_CATALOG) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 |  |  |         self.portal = api.get_portal() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 |  |  |         self.portal_url = api.get_url(self.portal) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 |  |  |         self.rc = api.get_tool(REFERENCE_CATALOG) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 |  |  |         self.dmk = context.bika_setup.getResultsDecimalMark() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 |  |  |         self.scinot = context.bika_setup.getScientificNotationResults() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 |  |  |         self.categories = [] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 |  |  |         # each editable item needs it's own allow_edit | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 |  |  |         # which is a list of field names. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 |  |  |         self.allow_edit = False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 |  |  |         self.columns = OrderedDict(( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 |  |  |             # Although 'created' column is not displayed in the list (see | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 |  |  |             # review_states to check the columns that will be rendered), this | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 |  |  |             # column is needed to sort the list by create date | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 |  |  |             ("created", { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  |                 "title": _("Date Created"), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 |  |  |                 "toggle": False}), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  |             ("Service", { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  |                 "title": _("Analysis"), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  |                 "attr": "Title", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 |  |  |                 "index": "sortable_title", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 |  |  |                 "sortable": False}), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 |  |  |             ("Method", { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  |                 "title": _("Method"), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 |  |  |                 "sortable": False, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 |  |  |                 "ajax": True, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 |  |  |                 "on_change": "_on_method_change", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 |  |  |                 "toggle": True}), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 |  |  |             ("Instrument", { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 |  |  |                 "title": _("Instrument"), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 |  |  |                 "ajax": True, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 |  |  |                 "sortable": False, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 |  |  |                 "toggle": True}), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 |  |  |             ("Calculation", { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 |  |  |                 "title": _("Calculation"), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 |  |  |                 "sortable": False, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 |  |  |                 "toggle": False}), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 |  |  |             ("Analyst", { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 |  |  |                 "title": _("Analyst"), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 |  |  |                 "sortable": False, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 140 |  |  |                 "ajax": True, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 141 |  |  |                 "toggle": True}), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 142 |  |  |             ("state_title", { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 143 |  |  |                 "title": _("Status"), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 144 |  |  |                 "sortable": False}), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 145 |  |  |             ("DetectionLimitOperand", { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 146 |  |  |                 "title": _("DL"), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 147 |  |  |                 "sortable": False, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 148 |  |  |                 "ajax": True, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 149 |  |  |                 "autosave": True, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 150 |  |  |                 "toggle": False}), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 151 |  |  |             ("Result", { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 152 |  |  |                 "title": _("Result"), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 153 |  |  |                 "input_width": "6", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 154 |  |  |                 "input_class": "ajax_calculate numeric", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 155 |  |  |                 "ajax": True, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 156 |  |  |                 "sortable": False}), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 157 |  |  |             ("Specification", { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 158 |  |  |                 "title": _("Specification"), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 159 |  |  |                 "sortable": False}), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 160 |  |  |             ("Uncertainty", { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 161 |  |  |                 "title": _("+-"), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 162 |  |  |                 "ajax": True, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 163 |  |  |                 "sortable": False}), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 164 |  |  |             ("retested", { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 165 |  |  |                 "title": _("Retested"), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 166 |  |  |                 "type": "boolean", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 167 |  |  |                 "sortable": False}), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 168 |  |  |             ("Attachments", { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 169 |  |  |                 "title": _("Attachments"), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 170 |  |  |                 "sortable": False}), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 171 |  |  |             ("CaptureDate", { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 172 |  |  |                 "title": _("Captured"), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 173 |  |  |                 "index": "getResultCaptureDate", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 174 |  |  |                 "sortable": False}), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 175 |  |  |             ("SubmittedBy", { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 176 |  |  |                 "title": _("Submitter"), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 177 |  |  |                 "sortable": False}), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 178 |  |  |             ("DueDate", { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 179 |  |  |                 "title": _("Due Date"), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 180 |  |  |                 "index": "getDueDate", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 181 |  |  |                 "sortable": False}), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 182 |  |  |             ("Hidden", { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 183 |  |  |                 "title": _("Hidden"), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 184 |  |  |                 "toggle": True, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 185 |  |  |                 "sortable": False, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 186 |  |  |                 "ajax": True, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 187 |  |  |                 "type": "boolean"}), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 188 |  |  |         )) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 189 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 190 |  |  |         # Inject Remarks column for listing | 
            
                                                                                                            
                            
            
                                    
            
            
                | 191 |  |  |         if self.analysis_remarks_enabled(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 192 |  |  |             self.columns["Remarks"] = { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 193 |  |  |                 "title": "Remarks", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 194 |  |  |                 "toggle": False, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 195 |  |  |                 "sortable": False, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 196 |  |  |                 "type": "remarks", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 197 |  |  |                 "ajax": True, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 198 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 199 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 200 |  |  |         self.review_states = [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 201 |  |  |             { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 202 |  |  |                 "id": "default", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 203 |  |  |                 "title": _("Valid"), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 204 |  |  |                 "contentFilter": { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 205 |  |  |                     "review_state": [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 206 |  |  |                         "registered", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 207 |  |  |                         "unassigned", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 208 |  |  |                         "assigned", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 209 |  |  |                         "to_be_verified", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 210 |  |  |                         "verified", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 211 |  |  |                         "published", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 212 |  |  |                     ] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 213 |  |  |                 }, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 214 |  |  |                 "columns": self.columns.keys() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 215 |  |  |             }, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 216 |  |  |             { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 217 |  |  |                 "id": "invalid", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 218 |  |  |                 "contentFilter": { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 219 |  |  |                     "review_state": [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 220 |  |  |                         "cancelled", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 221 |  |  |                         "retracted", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 222 |  |  |                         "rejected", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 223 |  |  |                     ] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 224 |  |  |                 }, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 225 |  |  |                 "title": _("Invalid"), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 226 |  |  |                 "columns": self.columns.keys(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 227 |  |  |             }, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 228 |  |  |             { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 229 |  |  |                 "id": "all", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 230 |  |  |                 "title": _("All"), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 231 |  |  |                 "contentFilter": {}, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 232 |  |  |                 "columns": self.columns.keys() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 233 |  |  |              }, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 234 |  |  |         ] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 235 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 236 |  |  |     def update(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 237 |  |  |         """Update hook | 
            
                                                                                                            
                            
            
                                    
            
            
                | 238 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 239 |  |  |         super(AnalysesView, self).update() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 240 |  |  |         self.load_analysis_categories() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 241 |  |  |         self.append_partition_filters() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 242 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 243 |  |  |     def before_render(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 244 |  |  |         """Before render hook | 
            
                                                                                                            
                            
            
                                    
            
            
                | 245 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 246 |  |  |         super(AnalysesView, self).before_render() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 247 |  |  |         self.request.set("disable_plone.rightcolumn", 1) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 248 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 249 |  |  |     @property | 
            
                                                                                                            
                            
            
                                    
            
            
                | 250 |  |  |     @viewcache.memoize | 
            
                                                                                                            
                            
            
                                    
            
            
                | 251 |  |  |     def senaite_theme(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 252 |  |  |         return getMultiAdapter( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 253 |  |  |             (self.context, self.request), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 254 |  |  |             name="senaite_theme") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 255 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 256 |  |  |     @property | 
            
                                                                                                            
                            
            
                                    
            
            
                | 257 |  |  |     @viewcache.memoize | 
            
                                                                                                            
                            
            
                                    
            
            
                | 258 |  |  |     def show_partitions(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 259 |  |  |         """Returns whether the partitions must be displayed or not | 
            
                                                                                                            
                            
            
                                    
            
            
                | 260 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 261 |  |  |         if api.get_current_client(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 262 |  |  |             # Current user is a client contact | 
            
                                                                                                            
                            
            
                                    
            
            
                | 263 |  |  |             return api.get_setup().getShowPartitions() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 264 |  |  |         return True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 265 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 266 |  |  |     @viewcache.memoize | 
            
                                                                                                            
                            
            
                                    
            
            
                | 267 |  |  |     def analysis_remarks_enabled(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 268 |  |  |         """Check if analysis remarks are enabled | 
            
                                                                                                            
                            
            
                                    
            
            
                | 269 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 270 |  |  |         return self.context.bika_setup.getEnableAnalysisRemarks() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 271 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 272 |  |  |     @viewcache.memoize | 
            
                                                                                                            
                            
            
                                    
            
            
                | 273 |  |  |     def has_permission(self, permission, obj=None): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 274 |  |  |         """Returns if the current user has rights for the permission passed in | 
            
                                                                                                            
                            
            
                                    
            
            
                | 275 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 276 |  |  |         :param permission: permission identifier | 
            
                                                                                                            
                            
            
                                    
            
            
                | 277 |  |  |         :param obj: object to check the permission against | 
            
                                                                                                            
                            
            
                                    
            
            
                | 278 |  |  |         :return: True if the user has rights for the permission passed in | 
            
                                                                                                            
                            
            
                                    
            
            
                | 279 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 280 |  |  |         if not permission: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 281 |  |  |             logger.warn("None permission is not allowed") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 282 |  |  |             return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 283 |  |  |         if obj is None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 284 |  |  |             return check_permission(permission, self.context) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 285 |  |  |         return check_permission(permission, self.get_object(obj)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 286 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 287 |  |  |     @viewcache.memoize | 
            
                                                                                                            
                            
            
                                    
            
            
                | 288 |  |  |     def is_analysis_edition_allowed(self, analysis_brain): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 289 |  |  |         """Returns if the analysis passed in can be edited by the current user | 
            
                                                                                                            
                            
            
                                    
            
            
                | 290 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 291 |  |  |         :param analysis_brain: Brain that represents an analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 292 |  |  |         :return: True if the user can edit the analysis, otherwise False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 293 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 294 |  |  |         if not self.context_active: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 295 |  |  |             # The current context must be active. We cannot edit analyses from | 
            
                                                                                                            
                            
            
                                    
            
            
                | 296 |  |  |             # inside a deactivated Analysis Request, for instance | 
            
                                                                                                            
                            
            
                                    
            
            
                | 297 |  |  |             return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 298 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 299 |  |  |         analysis_obj = self.get_object(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 300 |  |  |         if analysis_obj.getPointOfCapture() == 'field': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 301 |  |  |             # This analysis must be captured on field, during sampling. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 302 |  |  |             if not self.has_permission(EditFieldResults, analysis_obj): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 303 |  |  |                 # Current user cannot edit field analyses. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 304 |  |  |                 return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 305 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 306 |  |  |         elif not self.has_permission(EditResults, analysis_obj): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 307 |  |  |             # The Point of Capture is 'lab' and the current user cannot edit | 
            
                                                                                                            
                            
            
                                    
            
            
                | 308 |  |  |             # lab analyses. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 309 |  |  |             return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 310 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 311 |  |  |         # Check if the user is allowed to enter a value to to Result field | 
            
                                                                                                            
                            
            
                                    
            
            
                | 312 |  |  |         if not self.has_permission(FieldEditAnalysisResult, analysis_obj): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 313 |  |  |             return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 314 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 315 |  |  |         return True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 316 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 317 |  |  |     @viewcache.memoize | 
            
                                                                                                            
                            
            
                                    
            
            
                | 318 |  |  |     def is_result_edition_allowed(self, analysis_brain): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 319 |  |  |         """Checks if the edition of the result field is allowed | 
            
                                                                                                            
                            
            
                                    
            
            
                | 320 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 321 |  |  |         :param analysis_brain: Brain that represents an analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 322 |  |  |         :return: True if the user can edit the result field, otherwise False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 323 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 324 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 325 |  |  |         # Always check general edition first | 
            
                                                                                                            
                            
            
                                    
            
            
                | 326 |  |  |         if not self.is_analysis_edition_allowed(analysis_brain): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 327 |  |  |             return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 328 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 329 |  |  |         # Get the ananylsis object | 
            
                                                                                                            
                            
            
                                    
            
            
                | 330 |  |  |         obj = self.get_object(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 331 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 332 |  |  |         if not obj.getDetectionLimitOperand(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 333 |  |  |             # This is a regular result (not a detection limit) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 334 |  |  |             return True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 335 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 336 |  |  |         # Detection limit selector is enabled in the Analysis Service | 
            
                                                                                                            
                            
            
                                    
            
            
                | 337 |  |  |         if obj.getDetectionLimitSelector(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 338 |  |  |             # Manual detection limit entry is *not* allowed | 
            
                                                                                                            
                            
            
                                    
            
            
                | 339 |  |  |             if not obj.getAllowManualDetectionLimit(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 340 |  |  |                 return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 341 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 342 |  |  |         return True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 343 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 344 |  |  |     @viewcache.memoize | 
            
                                                                                                            
                            
            
                                    
            
            
                | 345 |  |  |     def is_uncertainty_edition_allowed(self, analysis_brain): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 346 |  |  |         """Checks if the edition of the uncertainty field is allowed | 
            
                                                                                                            
                            
            
                                    
            
            
                | 347 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 348 |  |  |         :param analysis_brain: Brain that represents an analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 349 |  |  |         :return: True if the user can edit the result field, otherwise False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 350 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 351 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 352 |  |  |         # Only allow to edit the uncertainty if result edition is allowed | 
            
                                                                                                            
                            
            
                                    
            
            
                | 353 |  |  |         if not self.is_result_edition_allowed(analysis_brain): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 354 |  |  |             return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 355 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 356 |  |  |         # Get the ananylsis object | 
            
                                                                                                            
                            
            
                                    
            
            
                | 357 |  |  |         obj = self.get_object(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 358 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 359 |  |  |         # Manual setting of uncertainty is not allowed | 
            
                                                                                                            
                            
            
                                    
            
            
                | 360 |  |  |         if not obj.getAllowManualUncertainty(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 361 |  |  |             return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 362 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 363 |  |  |         # Result is a detection limit -> uncertainty setting makes no sense! | 
            
                                                                                                            
                            
            
                                    
            
            
                | 364 |  |  |         if obj.getDetectionLimitOperand() in [LDL, UDL]: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 365 |  |  |             return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 366 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 367 |  |  |         return True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 368 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 369 |  |  |     @viewcache.memoize | 
            
                                                                                                            
                            
            
                                    
            
            
                | 370 |  |  |     def is_analysis_conditions_edition_allowed(self, analysis_brain): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 371 |  |  |         """Returns whether the conditions of the analysis can be edited or not | 
            
                                                                                                            
                            
            
                                    
            
            
                | 372 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 373 |  |  |         # Check if permission is granted for the given analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 374 |  |  |         obj = self.get_object(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 375 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 376 |  |  |         if IReferenceAnalysis.providedBy(obj): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 377 |  |  |             return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 378 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 379 |  |  |         if not self.has_permission(FieldEditAnalysisConditions, obj): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 380 |  |  |             return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 381 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 382 |  |  |         # Omit analysis does not have conditions set | 
            
                                                                                                            
                            
            
                                    
            
            
                | 383 |  |  |         if not obj.getConditions(empties=True): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 384 |  |  |             return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 385 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 386 |  |  |         return True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 387 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 388 |  |  |     def get_instrument(self, analysis_brain): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 389 |  |  |         """Returns the instrument assigned to the analysis passed in, if any | 
            
                                                                                                            
                            
            
                                    
            
            
                | 390 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 391 |  |  |         :param analysis_brain: Brain that represents an analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 392 |  |  |         :return: Instrument object or None | 
            
                                                                                                            
                            
            
                                    
            
            
                | 393 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 394 |  |  |         obj = self.get_object(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 395 |  |  |         return obj.getInstrument() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 396 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 397 |  |  |     def get_calculation(self, analysis_brain): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 398 |  |  |         """Returns the calculation assigned to the analysis passed in, if any | 
            
                                                                                                            
                            
            
                                    
            
            
                | 399 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 400 |  |  |         :param analysis_brain: Brain that represents an analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 401 |  |  |         :return: Calculation object or None | 
            
                                                                                                            
                            
            
                                    
            
            
                | 402 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 403 |  |  |         obj = self.get_object(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 404 |  |  |         return obj.getCalculation() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 405 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 406 |  |  |     @viewcache.memoize | 
            
                                                                                                            
                            
            
                                    
            
            
                | 407 |  |  |     def get_object(self, brain_or_object_or_uid): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 408 |  |  |         """Get the full content object. Returns None if the param passed in is | 
            
                                                                                                            
                            
            
                                    
            
            
                | 409 |  |  |         not a valid, not a valid object or not found | 
            
                                                                                                            
                            
            
                                    
            
            
                | 410 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 411 |  |  |         :param brain_or_object_or_uid: UID/Catalog brain/content object | 
            
                                                                                                            
                            
            
                                    
            
            
                | 412 |  |  |         :returns: content object | 
            
                                                                                                            
                            
            
                                    
            
            
                | 413 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 414 |  |  |         return api.get_object(brain_or_object_or_uid, default=None) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 415 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 416 |  |  |     def get_methods_vocabulary(self, analysis_brain): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 417 |  |  |         """Returns a vocabulary with all the methods available for the passed in | 
            
                                                                                                            
                            
            
                                    
            
            
                | 418 |  |  |         analysis, either those assigned to an instrument that are capable to | 
            
                                                                                                            
                            
            
                                    
            
            
                | 419 |  |  |         perform the test (option "Allow Entry of Results") and those assigned | 
            
                                                                                                            
                            
            
                                    
            
            
                | 420 |  |  |         manually in the associated Analysis Service. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 421 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 422 |  |  |         The vocabulary is a list of dictionaries. Each dictionary has the | 
            
                                                                                                            
                            
            
                                    
            
            
                | 423 |  |  |         following structure: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 424 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 425 |  |  |             {'ResultValue': <method_UID>, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 426 |  |  |              'ResultText': <method_Title>} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 427 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 428 |  |  |         :param analysis_brain: A single Analysis brain | 
            
                                                                                                            
                            
            
                                    
            
            
                | 429 |  |  |         :type analysis_brain: CatalogBrain | 
            
                                                                                                            
                            
            
                                    
            
            
                | 430 |  |  |         :returns: A list of dicts | 
            
                                                                                                            
                            
            
                                    
            
            
                | 431 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 432 |  |  |         obj = self.get_object(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 433 |  |  |         methods = obj.getAllowedMethods() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 434 |  |  |         if not methods: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 435 |  |  |             return [{"ResultValue": "", "ResultText": _("None")}] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 436 |  |  |         vocab = [] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 437 |  |  |         for method in methods: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 438 |  |  |             vocab.append({ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 439 |  |  |                 "ResultValue": api.get_uid(method), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 440 |  |  |                 "ResultText": api.get_title(method), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 441 |  |  |             }) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 442 |  |  |         return vocab | 
            
                                                                                                            
                            
            
                                    
            
            
                | 443 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 444 |  |  |     def get_instruments_vocabulary(self, analysis, method=None): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 445 |  |  |         """Returns a vocabulary with the valid and active instruments available | 
            
                                                                                                            
                            
            
                                    
            
            
                | 446 |  |  |         for the analysis passed in. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 447 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 448 |  |  |         If the option "Allow instrument entry of results" for the Analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 449 |  |  |         is disabled, the function returns an empty vocabulary. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 450 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 451 |  |  |         If the analysis passed in is a Reference Analysis (Blank or Control), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 452 |  |  |         the vocabulary, the invalid instruments will be included in the | 
            
                                                                                                            
                            
            
                                    
            
            
                | 453 |  |  |         vocabulary too. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 454 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 455 |  |  |         The vocabulary is a list of dictionaries. Each dictionary has the | 
            
                                                                                                            
                            
            
                                    
            
            
                | 456 |  |  |         following structure: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 457 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 458 |  |  |             {'ResultValue': <instrument_UID>, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 459 |  |  |              'ResultText': <instrument_Title>} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 460 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 461 |  |  |         :param analysis: A single Analysis or ReferenceAnalysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 462 |  |  |         :type analysis_brain: Analysis or.ReferenceAnalysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 463 |  |  |         :return: A vocabulary with the instruments for the analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 464 |  |  |         :rtype: A list of dicts: [{'ResultValue':UID, 'ResultText':Title}] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 465 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 466 |  |  |         obj = self.get_object(analysis) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 467 |  |  |         # get the allowed interfaces from the analysis service | 
            
                                                                                                            
                            
            
                                    
            
            
                | 468 |  |  |         instruments = obj.getAllowedInstruments() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 469 |  |  |         # if no method is passed, get the assigned method of the analyis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 470 |  |  |         if method is None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 471 |  |  |             method = obj.getMethod() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 472 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 473 |  |  |         # check if the analysis has a method | 
            
                                                                                                            
                            
            
                                    
            
            
                | 474 |  |  |         if method: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 475 |  |  |             # supported instrument from the method | 
            
                                                                                                            
                            
            
                                    
            
            
                | 476 |  |  |             method_instruments = method.getInstruments() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 477 |  |  |             # allow only method instruments that are set in service | 
            
                                                                                                            
                            
            
                                    
            
            
                | 478 |  |  |             instruments = list( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 479 |  |  |                 set(instruments).intersection(method_instruments)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 480 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 481 |  |  |         # If the analysis is a QC analysis, display all instruments, including | 
            
                                                                                                            
                            
            
                                    
            
            
                | 482 |  |  |         # those uncalibrated or for which the last QC test failed. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 483 |  |  |         is_qc = api.get_portal_type(obj) == "ReferenceAnalysis" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 484 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 485 |  |  |         vocab = [] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 486 |  |  |         for instrument in instruments: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 487 |  |  |             uid = api.get_uid(instrument) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 488 |  |  |             title = api.safe_unicode(api.get_title(instrument)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 489 |  |  |             # append all valid instruments | 
            
                                                                                                            
                            
            
                                    
            
            
                | 490 |  |  |             if instrument.isValid(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 491 |  |  |                 vocab.append({ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 492 |  |  |                     "ResultValue": uid, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 493 |  |  |                     "ResultText": title, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 494 |  |  |                 }) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 495 |  |  |             elif is_qc: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 496 |  |  |                 # Is a QC analysis, include instrument also if is not valid | 
            
                                                                                                            
                            
            
                                    
            
            
                | 497 |  |  |                 if instrument.isOutOfDate(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 498 |  |  |                     title = _(u"{} (Out of date)".format(title)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 499 |  |  |                 vocab.append({ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 500 |  |  |                     "ResultValue": uid, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 501 |  |  |                     "ResultText": title, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 502 |  |  |                 }) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 503 |  |  |             elif instrument.isOutOfDate(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 504 |  |  |                 # disable out of date instruments | 
            
                                                                                                            
                            
            
                                    
            
            
                | 505 |  |  |                 title = _(u"{} (Out of date)".format(title)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 506 |  |  |                 vocab.append({ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 507 |  |  |                     "disabled": True, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 508 |  |  |                     "ResultValue": None, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 509 |  |  |                     "ResultText": title, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 510 |  |  |                 }) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 511 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 512 |  |  |         # sort the vocabulary | 
            
                                                                                                            
                            
            
                                    
            
            
                | 513 |  |  |         vocab = list(sorted(vocab, key=itemgetter("ResultText"))) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 514 |  |  |         # prepend empty item | 
            
                                                                                                            
                            
            
                                    
            
            
                | 515 |  |  |         vocab = [{"ResultValue": "", "ResultText": _("None")}] + vocab | 
            
                                                                                                            
                            
            
                                    
            
            
                | 516 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 517 |  |  |         return vocab | 
            
                                                                                                            
                            
            
                                    
            
            
                | 518 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 519 |  |  |     def load_analysis_categories(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 520 |  |  |         # Getting analysis categories | 
            
                                                                                                            
                            
            
                                    
            
            
                | 521 |  |  |         bsc = api.get_tool('senaite_catalog_setup') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 522 |  |  |         analysis_categories = bsc(portal_type="AnalysisCategory", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 523 |  |  |                                   sort_on="sortable_title") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 524 |  |  |         # Sorting analysis categories | 
            
                                                                                                            
                            
            
                                    
            
            
                | 525 |  |  |         self.analysis_categories_order = dict([ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 526 |  |  |             (b.Title, "{:04}".format(a)) for a, b in | 
            
                                                                                                            
                            
            
                                    
            
            
                | 527 |  |  |             enumerate(analysis_categories)]) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 528 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 529 |  |  |     def append_partition_filters(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 530 |  |  |         """Append additional review state filters for partitions | 
            
                                                                                                            
                            
            
                                    
            
            
                | 531 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 532 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 533 |  |  |         # view is used for instrument QC view as well | 
            
                                                                                                            
                            
            
                                    
            
            
                | 534 |  |  |         if not IAnalysisRequest.providedBy(self.context): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 535 |  |  |             return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 536 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 537 |  |  |         # check if the sample has partitions | 
            
                                                                                                            
                            
            
                                    
            
            
                | 538 |  |  |         partitions = self.context.getDescendants() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 539 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 540 |  |  |         # root partition w/o partitions | 
            
                                                                                                            
                            
            
                                    
            
            
                | 541 |  |  |         if not partitions: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 542 |  |  |             return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 543 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 544 |  |  |         new_states = [] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 545 |  |  |         valid_states = [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 546 |  |  |             "registered", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 547 |  |  |             "unassigned", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 548 |  |  |             "assigned", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 549 |  |  |             "to_be_verified", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 550 |  |  |             "verified", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 551 |  |  |             "published", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 552 |  |  |         ] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 553 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 554 |  |  |         if self.context.isRootAncestor(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 555 |  |  |             root_id = api.get_id(self.context) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 556 |  |  |             new_states.append({ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 557 |  |  |                 "id": root_id, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 558 |  |  |                 "title": root_id, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 559 |  |  |                 "contentFilter": { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 560 |  |  |                     "getAncestorsUIDs": api.get_uid(self.context), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 561 |  |  |                     "review_state": valid_states, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 562 |  |  |                     "path": { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 563 |  |  |                         "query": api.get_path(self.context), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 564 |  |  |                         "level": 0, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 565 |  |  |                     }, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 566 |  |  |                 }, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 567 |  |  |                 "columns": self.columns.keys(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 568 |  |  |             }) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 569 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 570 |  |  |         for partition in partitions: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 571 |  |  |             part_id = api.get_id(partition) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 572 |  |  |             new_states.append({ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 573 |  |  |                 "id": part_id, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 574 |  |  |                 "title": part_id, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 575 |  |  |                 "contentFilter": { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 576 |  |  |                     "getAncestorsUIDs": api.get_uid(partition), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 577 |  |  |                     "review_state": valid_states, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 578 |  |  |                 }, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 579 |  |  |                 "columns": self.columns.keys(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 580 |  |  |             }) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 581 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 582 |  |  |         for state in sorted(new_states, key=lambda s: s.get("id")): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 583 |  |  |             if state not in self.review_states: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 584 |  |  |                 self.review_states.append(state) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 585 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 586 |  |  |     def isItemAllowed(self, obj): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 587 |  |  |         """Checks if the passed in Analysis must be displayed in the list. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 588 |  |  |         :param obj: A single Analysis brain or content object | 
            
                                                                                                            
                            
            
                                    
            
            
                | 589 |  |  |         :type obj: ATContentType/CatalogBrain | 
            
                                                                                                            
                            
            
                                    
            
            
                | 590 |  |  |         :returns: True if the item can be added to the list. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 591 |  |  |         :rtype: bool | 
            
                                                                                                            
                            
            
                                    
            
            
                | 592 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 593 |  |  |         if not obj: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 594 |  |  |             return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 595 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 596 |  |  |         # Does the user has enough privileges to see retracted analyses? | 
            
                                                                                                            
                            
            
                                    
            
            
                | 597 |  |  |         if obj.review_state == 'retracted' and \ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 598 |  |  |                 not self.has_permission(ViewRetractedAnalyses): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 599 |  |  |             return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 600 |  |  |         return True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 601 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 602 |  |  |     def folderitem(self, obj, item, index): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 603 |  |  |         """Prepare a data item for the listing. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 604 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 605 |  |  |         :param obj: The catalog brain or content object | 
            
                                                                                                            
                            
            
                                    
            
            
                | 606 |  |  |         :param item: Listing item (dictionary) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 607 |  |  |         :param index: Index of the listing item | 
            
                                                                                                            
                            
            
                                    
            
            
                | 608 |  |  |         :returns: Augmented listing data item | 
            
                                                                                                            
                            
            
                                    
            
            
                | 609 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 610 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 611 |  |  |         item['Service'] = obj.Title | 
            
                                                                                                            
                            
            
                                    
            
            
                | 612 |  |  |         item['class']['service'] = 'service_title' | 
            
                                                                                                            
                            
            
                                    
            
            
                | 613 |  |  |         item['service_uid'] = obj.getServiceUID | 
            
                                                                                                            
                            
            
                                    
            
            
                | 614 |  |  |         item['Keyword'] = obj.getKeyword | 
            
                                                                                                            
                            
            
                                    
            
            
                | 615 |  |  |         item['Unit'] = format_supsub(obj.getUnit) if obj.getUnit else '' | 
            
                                                                                                            
                            
            
                                    
            
            
                | 616 |  |  |         item['retested'] = obj.getRetestOfUID and True or False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 617 |  |  |         item['class']['retested'] = 'center' | 
            
                                                                                                            
                            
            
                                    
            
            
                | 618 |  |  |         item['replace']['Service'] = '<strong>{}</strong>'.format(obj.Title) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 619 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 620 |  |  |         # Append info link before the service | 
            
                                                                                                            
                            
            
                                    
            
            
                | 621 |  |  |         # see: bika.lims.site.coffee for the attached event handler | 
            
                                                                                                            
                            
            
                                    
            
            
                | 622 |  |  |         item["before"]["Service"] = get_link( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 623 |  |  |             "analysisservice_info?service_uid={}&analysis_uid={}" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 624 |  |  |             .format(obj.getServiceUID, obj.UID), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 625 |  |  |             value="<i class='fas fa-info-circle'></i>", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 626 |  |  |             css_class="overlay_panel", tabindex="-1") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 627 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 628 |  |  |         # Append conditions link before the analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 629 |  |  |         # see: bika.lims.site.coffee for the attached event handler | 
            
                                                                                                            
                            
            
                                    
            
            
                | 630 |  |  |         if self.is_analysis_conditions_edition_allowed(obj): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 631 |  |  |             url = api.get_url(self.context) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 632 |  |  |             url = "{}/set_analysis_conditions?uid={}".format(url, obj.UID) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 633 |  |  |             ico = "<i class='fas fa-list' style='padding-top: 5px;'/>" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 634 |  |  |             conditions = get_link(url, value=ico, css_class="overlay_panel", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 635 |  |  |                                   tabindex="-1") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 636 |  |  |             info = item["before"]["Service"] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 637 |  |  |             item["before"]["Service"] = "<br/>".join([info, conditions]) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 638 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 639 |  |  |         # Note that getSampleTypeUID returns the type of the Sample, no matter | 
            
                                                                                                            
                            
            
                                    
            
            
                | 640 |  |  |         # if the sample associated to the analysis is a regular Sample (routine | 
            
                                                                                                            
                            
            
                                    
            
            
                | 641 |  |  |         # analysis) or if is a Reference Sample (Reference Analysis). If the | 
            
                                                                                                            
                            
            
                                    
            
            
                | 642 |  |  |         # analysis is a duplicate, it returns the Sample Type of the sample | 
            
                                                                                                            
                            
            
                                    
            
            
                | 643 |  |  |         # associated to the source analysis. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 644 |  |  |         item['st_uid'] = obj.getSampleTypeUID | 
            
                                                                                                            
                            
            
                                    
            
            
                | 645 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 646 |  |  |         # Fill item's category | 
            
                                                                                                            
                            
            
                                    
            
            
                | 647 |  |  |         self._folder_item_category(obj, item) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 648 |  |  |         # Fill item's row class | 
            
                                                                                                            
                            
            
                                    
            
            
                | 649 |  |  |         self._folder_item_css_class(obj, item) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 650 |  |  |         # Fill result and/or result options | 
            
                                                                                                            
                            
            
                                    
            
            
                | 651 |  |  |         self._folder_item_result(obj, item) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 652 |  |  |         # Fill calculation and interim fields | 
            
                                                                                                            
                            
            
                                    
            
            
                | 653 |  |  |         self._folder_item_calculation(obj, item) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 654 |  |  |         # Fill method | 
            
                                                                                                            
                            
            
                                    
            
            
                | 655 |  |  |         self._folder_item_method(obj, item) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 656 |  |  |         # Fill instrument | 
            
                                                                                                            
                            
            
                                    
            
            
                | 657 |  |  |         self._folder_item_instrument(obj, item) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 658 |  |  |         # Fill analyst | 
            
                                                                                                            
                            
            
                                    
            
            
                | 659 |  |  |         self._folder_item_analyst(obj, item) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 660 |  |  |         # Fill submitted by | 
            
                                                                                                            
                            
            
                                    
            
            
                | 661 |  |  |         self._folder_item_submitted_by(obj, item) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 662 |  |  |         # Fill attachments | 
            
                                                                                                            
                            
            
                                    
            
            
                | 663 |  |  |         self._folder_item_attachments(obj, item) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 664 |  |  |         # Fill uncertainty | 
            
                                                                                                            
                            
            
                                    
            
            
                | 665 |  |  |         self._folder_item_uncertainty(obj, item) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 666 |  |  |         # Fill Detection Limits | 
            
                                                                                                            
                            
            
                                    
            
            
                | 667 |  |  |         self._folder_item_detection_limits(obj, item) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 668 |  |  |         # Fill Specifications | 
            
                                                                                                            
                            
            
                                    
            
            
                | 669 |  |  |         self._folder_item_specifications(obj, item) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 670 |  |  |         self._folder_item_out_of_range(obj, item) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 671 |  |  |         self._folder_item_result_range_compliance(obj, item) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 672 |  |  |         # Fill Partition | 
            
                                                                                                            
                            
            
                                    
            
            
                | 673 |  |  |         self._folder_item_partition(obj, item) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 674 |  |  |         # Fill Due Date and icon if late/overdue | 
            
                                                                                                            
                            
            
                                    
            
            
                | 675 |  |  |         self._folder_item_duedate(obj, item) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 676 |  |  |         # Fill verification criteria | 
            
                                                                                                            
                            
            
                                    
            
            
                | 677 |  |  |         self._folder_item_verify_icons(obj, item) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 678 |  |  |         # Fill worksheet anchor/icon | 
            
                                                                                                            
                            
            
                                    
            
            
                | 679 |  |  |         self._folder_item_assigned_worksheet(obj, item) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 680 |  |  |         # Fill accredited icon | 
            
                                                                                                            
                            
            
                                    
            
            
                | 681 |  |  |         self._folder_item_accredited_icon(obj, item) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 682 |  |  |         # Fill hidden field (report visibility) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 683 |  |  |         self._folder_item_report_visibility(obj, item) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 684 |  |  |         # Renders additional icons to be displayed | 
            
                                                                                                            
                            
            
                                    
            
            
                | 685 |  |  |         self._folder_item_fieldicons(obj) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 686 |  |  |         # Renders remarks toggle button | 
            
                                                                                                            
                            
            
                                    
            
            
                | 687 |  |  |         self._folder_item_remarks(obj, item) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 688 |  |  |         # Renders the analysis conditions | 
            
                                                                                                            
                            
            
                                    
            
            
                | 689 |  |  |         self._folder_item_conditions(obj, item) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 690 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 691 |  |  |         return item | 
            
                                                                                                            
                            
            
                                    
            
            
                | 692 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 693 |  |  |     def folderitems(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 694 |  |  |         # This shouldn't be required here, but there are some views that calls | 
            
                                                                                                            
                            
            
                                    
            
            
                | 695 |  |  |         # directly contents_table() instead of __call__, so before_render is | 
            
                                                                                                            
                            
            
                                    
            
            
                | 696 |  |  |         # never called. :( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 697 |  |  |         self.before_render() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 698 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 699 |  |  |         # Gettin all the items | 
            
                                                                                                            
                            
            
                                    
            
            
                | 700 |  |  |         items = super(AnalysesView, self).folderitems() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 701 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 702 |  |  |         # the TAL requires values for all interim fields on all | 
            
                                                                                                            
                            
            
                                    
            
            
                | 703 |  |  |         # items, so we set blank values in unused cells | 
            
                                                                                                            
                            
            
                                    
            
            
                | 704 |  |  |         for item in items: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 705 |  |  |             for field in self.interim_columns: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 706 |  |  |                 if field not in item: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 707 |  |  |                     item[field] = "" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 708 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 709 |  |  |             # Graceful handling of new item key introduced in | 
            
                                                                                                            
                            
            
                                    
            
            
                | 710 |  |  |             # https://github.com/senaite/senaite.app.listing/pull/81 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 711 |  |  |             item["help"] = item.get("help", {}) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 712 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 713 |  |  |         # XXX order the list of interim columns | 
            
                                                                                                            
                            
            
                                    
            
            
                | 714 |  |  |         interim_keys = self.interim_columns.keys() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 715 |  |  |         interim_keys.reverse() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 716 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 717 |  |  |         # add InterimFields keys to columns | 
            
                                                                                                            
                            
            
                                    
            
            
                | 718 |  |  |         for col_id in interim_keys: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 719 |  |  |             if col_id not in self.columns: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 720 |  |  |                 self.columns[col_id] = { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 721 |  |  |                     "title": self.interim_columns[col_id], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 722 |  |  |                     "input_width": "6", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 723 |  |  |                     "input_class": "ajax_calculate numeric", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 724 |  |  |                     "sortable": False, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 725 |  |  |                     "toggle": True, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 726 |  |  |                     "ajax": True, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 727 |  |  |                 } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 728 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 729 |  |  |         if self.allow_edit: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 730 |  |  |             new_states = [] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 731 |  |  |             for state in self.review_states: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 732 |  |  |                 # InterimFields are displayed in review_state | 
            
                                                                                                            
                            
            
                                    
            
            
                | 733 |  |  |                 # They are anyway available through View.columns though. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 734 |  |  |                 # In case of hidden fields, the calcs.py should check | 
            
                                                                                                            
                            
            
                                    
            
            
                | 735 |  |  |                 # calcs/services | 
            
                                                                                                            
                            
            
                                    
            
            
                | 736 |  |  |                 # for additional InterimFields!! | 
            
                                                                                                            
                            
            
                                    
            
            
                | 737 |  |  |                 pos = "Result" in state["columns"] and \ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 738 |  |  |                       state["columns"].index("Result") or len(state["columns"]) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 739 |  |  |                 for col_id in interim_keys: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 740 |  |  |                     if col_id not in state["columns"]: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 741 |  |  |                         state["columns"].insert(pos, col_id) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 742 |  |  |                 # retested column is added after Result. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 743 |  |  |                 pos = "Result" in state["columns"] and \ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 744 |  |  |                       state["columns"].index("Uncertainty") + 1 or len( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 745 |  |  |                     state["columns"]) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 746 |  |  |                 if "retested" in state["columns"]: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 747 |  |  |                     state["columns"].remove("retested") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 748 |  |  |                 state["columns"].insert(pos, "retested") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 749 |  |  |                 new_states.append(state) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 750 |  |  |             self.review_states = new_states | 
            
                                                                                                            
                            
            
                                    
            
            
                | 751 |  |  |             # Allow selecting individual analyses | 
            
                                                                                                            
                            
            
                                    
            
            
                | 752 |  |  |             self.show_select_column = True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 753 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 754 |  |  |         if self.show_categories: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 755 |  |  |             self.categories = map(lambda x: x[0], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 756 |  |  |                                   sorted(self.categories, key=lambda x: x[1])) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 757 |  |  |         else: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 758 |  |  |             self.categories.sort() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 759 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 760 |  |  |         # self.json_specs = json.dumps(self.specs) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 761 |  |  |         self.json_interim_fields = json.dumps(self.interim_fields) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 762 |  |  |         self.items = items | 
            
                                                                                                            
                            
            
                                    
            
            
                | 763 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 764 |  |  |         # Display method and instrument columns only if at least one of the | 
            
                                                                                                            
                            
            
                                    
            
            
                | 765 |  |  |         # analyses requires them to be displayed for selection | 
            
                                                                                                            
                            
            
                                    
            
            
                | 766 |  |  |         self.columns["Method"]["toggle"] = self.is_method_column_required() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 767 |  |  |         self.columns["Instrument"]["toggle"] = self.is_instrument_column_required() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 768 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 769 |  |  |         return items | 
            
                                                                                                            
                            
            
                                    
            
            
                | 770 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 771 |  |  |     def render_unit(self, unit, css_class="unit small text-secondary"): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 772 |  |  |         """Render HTML element for unit | 
            
                                                                                                            
                            
            
                                    
            
            
                | 773 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 774 |  |  |         return "<span class='{css_class}'>{unit}</span>".format( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 775 |  |  |             unit=unit, css_class=css_class) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 776 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 777 |  |  |     def _folder_item_category(self, analysis_brain, item): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 778 |  |  |         """Sets the category to the item passed in | 
            
                                                                                                            
                            
            
                                    
            
            
                | 779 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 780 |  |  |         :param analysis_brain: Brain that represents an analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 781 |  |  |         :param item: analysis' dictionary counterpart that represents a row | 
            
                                                                                                            
                            
            
                                    
            
            
                | 782 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 783 |  |  |         if not self.show_categories: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 784 |  |  |             return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 785 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 786 |  |  |         cat = analysis_brain.getCategoryTitle | 
            
                                                                                                            
                            
            
                                    
            
            
                | 787 |  |  |         item["category"] = cat | 
            
                                                                                                            
                            
            
                                    
            
            
                | 788 |  |  |         cat_order = self.analysis_categories_order.get(cat) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 789 |  |  |         if (cat, cat_order) not in self.categories: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 790 |  |  |             self.categories.append((cat, cat_order)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 791 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 792 |  |  |     def _folder_item_css_class(self, analysis_brain, item): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 793 |  |  |         """Sets the suitable css class name(s) to `table_row_class` from the | 
            
                                                                                                            
                            
            
                                    
            
            
                | 794 |  |  |         item passed in, depending on the properties of the analysis object | 
            
                                                                                                            
                            
            
                                    
            
            
                | 795 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 796 |  |  |         :param analysis_brain: Brain that represents an analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 797 |  |  |         :param item: analysis' dictionary counterpart that represents a row | 
            
                                                                                                            
                            
            
                                    
            
            
                | 798 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 799 |  |  |         meta_type = analysis_brain.meta_type | 
            
                                                                                                            
                            
            
                                    
            
            
                | 800 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 801 |  |  |         # Default css names for table_row_class | 
            
                                                                                                            
                            
            
                                    
            
            
                | 802 |  |  |         css_names = item.get('table_row_class', '').split() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 803 |  |  |         css_names.extend(['state-{}'.format(analysis_brain.review_state), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 804 |  |  |                           'type-{}'.format(meta_type.lower())]) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 805 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 806 |  |  |         if meta_type == 'ReferenceAnalysis': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 807 |  |  |             css_names.append('qc-analysis') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 808 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 809 |  |  |         elif meta_type == 'DuplicateAnalysis': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 810 |  |  |             if analysis_brain.getAnalysisPortalType == 'ReferenceAnalysis': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 811 |  |  |                 css_names.append('qc-analysis') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 812 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 813 |  |  |         item['table_row_class'] = ' '.join(css_names) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 814 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 815 |  |  |     def _folder_item_duedate(self, analysis_brain, item): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 816 |  |  |         """Set the analysis' due date to the item passed in. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 817 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 818 |  |  |         :param analysis_brain: Brain that represents an analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 819 |  |  |         :param item: analysis' dictionary counterpart that represents a row | 
            
                                                                                                            
                            
            
                                    
            
            
                | 820 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 821 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 822 |  |  |         # Note that if the analysis is a Reference Analysis, `getDueDate` | 
            
                                                                                                            
                            
            
                                    
            
            
                | 823 |  |  |         # returns the date when the ReferenceSample expires. If the analysis is | 
            
                                                                                                            
                            
            
                                    
            
            
                | 824 |  |  |         # a duplicate, `getDueDate` returns the due date of the source analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 825 |  |  |         due_date = analysis_brain.getDueDate | 
            
                                                                                                            
                            
            
                                    
            
            
                | 826 |  |  |         if not due_date: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 827 |  |  |             return None | 
            
                                                                                                            
                            
            
                                    
            
            
                | 828 |  |  |         due_date_str = self.ulocalized_time(due_date, long_format=0) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 829 |  |  |         item['DueDate'] = due_date_str | 
            
                                                                                                            
                            
            
                                    
            
            
                | 830 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 831 |  |  |         # If the Analysis is late/overdue, display an icon | 
            
                                                                                                            
                            
            
                                    
            
            
                | 832 |  |  |         capture_date = analysis_brain.getResultCaptureDate | 
            
                                                                                                            
                            
            
                                    
            
            
                | 833 |  |  |         capture_date = capture_date or DateTime() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 834 |  |  |         if capture_date > due_date: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 835 |  |  |             # The analysis is late or overdue | 
            
                                                                                                            
                            
            
                                    
            
            
                | 836 |  |  |             img = get_image('late.png', title=t(_("Late Analysis")), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 837 |  |  |                             width='16px', height='16px') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 838 |  |  |             item['replace']['DueDate'] = '{} {}'.format(due_date_str, img) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 839 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 840 |  |  |     def _folder_item_result(self, analysis_brain, item): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 841 |  |  |         """Set the analysis' result to the item passed in. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 842 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 843 |  |  |         :param analysis_brain: Brain that represents an analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 844 |  |  |         :param item: analysis' dictionary counterpart that represents a row | 
            
                                                                                                            
                            
            
                                    
            
            
                | 845 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 846 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 847 |  |  |         item["Result"] = "" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 848 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 849 |  |  |         # TODO: The permission `ViewResults` is managed on the sample. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 850 |  |  |         #       -> Change to a proper field permission! | 
            
                                                                                                            
                            
            
                                    
            
            
                | 851 |  |  |         if not self.has_permission(ViewResults, self.context): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 852 |  |  |             # If user has no permissions, don"t display the result but an icon | 
            
                                                                                                            
                            
            
                                    
            
            
                | 853 |  |  |             img = get_image("to_follow.png", width="16px", height="16px") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 854 |  |  |             item["before"]["Result"] = img | 
            
                                                                                                            
                            
            
                                    
            
            
                | 855 |  |  |             return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 856 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 857 |  |  |         result = analysis_brain.getResult | 
            
                                                                                                            
                            
            
                                    
            
            
                | 858 |  |  |         capture_date = analysis_brain.getResultCaptureDate | 
            
                                                                                                            
                            
            
                                    
            
            
                | 859 |  |  |         capture_date_str = self.ulocalized_time(capture_date, long_format=0) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 860 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 861 |  |  |         item["Result"] = result | 
            
                                                                                                            
                            
            
                                    
            
            
                | 862 |  |  |         item["CaptureDate"] = capture_date_str | 
            
                                                                                                            
                            
            
                                    
            
            
                | 863 |  |  |         item["result_captured"] = capture_date_str | 
            
                                                                                                            
                            
            
                                    
            
            
                | 864 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 865 |  |  |         # Add the unit after the result | 
            
                                                                                                            
                            
            
                                    
            
            
                | 866 |  |  |         unit = item.get("Unit") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 867 |  |  |         if unit: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 868 |  |  |             item["after"]["Result"] = self.render_unit(unit) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 869 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 870 |  |  |         # Get the analysis object | 
            
                                                                                                            
                            
            
                                    
            
            
                | 871 |  |  |         obj = self.get_object(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 872 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 873 |  |  |         # Edit mode enabled of this Analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 874 |  |  |         if self.is_analysis_edition_allowed(analysis_brain): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 875 |  |  |             # Allow to set Remarks | 
            
                                                                                                            
                            
            
                                    
            
            
                | 876 |  |  |             item["allow_edit"].append("Remarks") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 877 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 878 |  |  |             # Set the results field editable | 
            
                                                                                                            
                            
            
                                    
            
            
                | 879 |  |  |             if self.is_result_edition_allowed(analysis_brain): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 880 |  |  |                 item["allow_edit"].append("Result") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 881 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 882 |  |  |             # Prepare result options | 
            
                                                                                                            
                            
            
                                    
            
            
                | 883 |  |  |             choices = obj.getResultOptions() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 884 |  |  |             if choices: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 885 |  |  |                 # N.B.we copy here the list to avoid persistent changes | 
            
                                                                                                            
                            
            
                                    
            
            
                | 886 |  |  |                 choices = copy(choices) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 887 |  |  |                 choices_type = obj.getResultOptionsType() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 888 |  |  |                 if choices_type == "select": | 
            
                                                                                                            
                            
            
                                    
            
            
                | 889 |  |  |                     # By default set empty as the default selected choice | 
            
                                                                                                            
                            
            
                                    
            
            
                | 890 |  |  |                     choices.insert(0, dict(ResultValue="", ResultText="")) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 891 |  |  |                 item["choices"]["Result"] = choices | 
            
                                                                                                            
                            
            
                                    
            
            
                | 892 |  |  |                 item["result_type"] = choices_type | 
            
                                                                                                            
                            
            
                                    
            
            
                | 893 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 894 |  |  |             elif obj.getStringResult(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 895 |  |  |                 item["result_type"] = "string" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 896 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 897 |  |  |             else: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 898 |  |  |                 item["result_type"] = "numeric" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 899 |  |  |                 item["help"]["result"] = _( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 900 |  |  |                     "Enter the result either in decimal or scientific " | 
            
                                                                                                            
                            
            
                                    
            
            
                | 901 |  |  |                     "notation, e.g. 0.00005 or 1e-5, 10000 or 1e5") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 902 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 903 |  |  |         if not result: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 904 |  |  |             return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 905 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 906 |  |  |         formatted_result = obj.getFormattedResult( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 907 |  |  |             sciformat=int(self.scinot), decimalmark=self.dmk) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 908 |  |  |         item["formatted_result"] = formatted_result | 
            
                                                                                                            
                            
            
                                    
            
            
                | 909 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 910 |  |  |     def is_multi_interim(self, interim): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 911 |  |  |         """Returns whether the interim stores a list of values instead of a | 
            
                                                                                                            
                            
            
                                    
            
            
                | 912 |  |  |         single value | 
            
                                                                                                            
                            
            
                                    
            
            
                | 913 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 914 |  |  |         result_type = interim.get("result_type", "") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 915 |  |  |         return result_type.startswith("multi") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 916 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 917 |  |  |     def to_list(self, value): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 918 |  |  |         """Converts the value to a list | 
            
                                                                                                            
                            
            
                                    
            
            
                | 919 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 920 |  |  |         try: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 921 |  |  |             val = json.loads(value) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 922 |  |  |             if isinstance(val, (list, tuple, set)): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 923 |  |  |                 value = val | 
            
                                                                                                            
                            
            
                                    
            
            
                | 924 |  |  |         except (ValueError, TypeError): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 925 |  |  |             pass | 
            
                                                                                                            
                            
            
                                    
            
            
                | 926 |  |  |         if not isinstance(value, (list, tuple, set)): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 927 |  |  |             value = [value] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 928 |  |  |         return value | 
            
                                                                                                            
                            
            
                                    
            
            
                | 929 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 930 |  |  |     def _folder_item_calculation(self, analysis_brain, item): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 931 |  |  |         """Set the analysis' calculation and interims to the item passed in. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 932 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 933 |  |  |         :param analysis_brain: Brain that represents an analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 934 |  |  |         :param item: analysis' dictionary counterpart that represents a row | 
            
                                                                                                            
                            
            
                                    
            
            
                | 935 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 936 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 937 |  |  |         if not self.has_permission(ViewResults, analysis_brain): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 938 |  |  |             # Hide interims and calculation if user cannot view results | 
            
                                                                                                            
                            
            
                                    
            
            
                | 939 |  |  |             return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 940 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 941 |  |  |         is_editable = self.is_analysis_edition_allowed(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 942 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 943 |  |  |         # calculation | 
            
                                                                                                            
                            
            
                                    
            
            
                | 944 |  |  |         calculation = self.get_calculation(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 945 |  |  |         calculation_uid = api.get_uid(calculation) if calculation else "" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 946 |  |  |         calculation_title = api.get_title(calculation) if calculation else "" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 947 |  |  |         calculation_link = get_link_for(calculation) if calculation else "" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 948 |  |  |         item["calculation"] = calculation_uid | 
            
                                                                                                            
                            
            
                                    
            
            
                | 949 |  |  |         item["Calculation"] = calculation_title | 
            
                                                                                                            
                            
            
                                    
            
            
                | 950 |  |  |         item["replace"]["Calculation"] = calculation_link or _("Manual") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 951 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 952 |  |  |         # Set interim fields. Note we add the key 'formatted_value' to the list | 
            
                                                                                                            
                            
            
                                    
            
            
                | 953 |  |  |         # of interims the analysis has already assigned. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 954 |  |  |         analysis_obj = self.get_object(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 955 |  |  |         interim_fields = analysis_obj.getInterimFields() or list() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 956 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 957 |  |  |         # Copy to prevent to avoid persistent changes | 
            
                                                                                                            
                            
            
                                    
            
            
                | 958 |  |  |         interim_fields = deepcopy(interim_fields) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 959 |  |  |         for interim_field in interim_fields: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 960 |  |  |             interim_keyword = interim_field.get('keyword', '') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 961 |  |  |             if not interim_keyword: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 962 |  |  |                 continue | 
            
                                                                                                            
                            
            
                                    
            
            
                | 963 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 964 |  |  |             interim_value = interim_field.get("value", "") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 965 |  |  |             interim_unit = interim_field.get("unit", "") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 966 |  |  |             interim_formatted = formatDecimalMark(interim_value, self.dmk) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 967 |  |  |             interim_field["formatted_value"] = interim_formatted | 
            
                                                                                                            
                            
            
                                    
            
            
                | 968 |  |  |             item[interim_keyword] = interim_field | 
            
                                                                                                            
                            
            
                                    
            
            
                | 969 |  |  |             item["class"][interim_keyword] = "interim" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 970 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 971 |  |  |             # render the unit after the interim field | 
            
                                                                                                            
                            
            
                                    
            
            
                | 972 |  |  |             if interim_unit: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 973 |  |  |                 formatted_interim_unit = format_supsub(interim_unit) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 974 |  |  |                 item["after"][interim_keyword] = self.render_unit( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 975 |  |  |                     formatted_interim_unit) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 976 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 977 |  |  |             # Note: As soon as we have a separate content type for field | 
            
                                                                                                            
                            
            
                                    
            
            
                | 978 |  |  |             #       analysis, we can solely rely on the field permission | 
            
                                                                                                            
                            
            
                                    
            
            
                | 979 |  |  |             #       "senaite.core: Field: Edit Analysis Result" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 980 |  |  |             if is_editable: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 981 |  |  |                 if self.has_permission( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 982 |  |  |                         FieldEditAnalysisResult, analysis_brain): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 983 |  |  |                     item["allow_edit"].append(interim_keyword) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 984 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 985 |  |  |             # Add this analysis' interim fields to the interim_columns list | 
            
                                                                                                            
                            
            
                                    
            
            
                | 986 |  |  |             interim_hidden = interim_field.get("hidden", False) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 987 |  |  |             if not interim_hidden: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 988 |  |  |                 interim_title = interim_field.get("title") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 989 |  |  |                 self.interim_columns[interim_keyword] = interim_title | 
            
                                                                                                            
                            
            
                                    
            
            
                | 990 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 991 |  |  |             # Does interim's results list needs to be rendered? | 
            
                                                                                                            
                            
            
                                    
            
            
                | 992 |  |  |             choices = interim_field.get("choices") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 993 |  |  |             if choices: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 994 |  |  |                 # Process the value as a list | 
            
                                                                                                            
                            
            
                                    
            
            
                | 995 |  |  |                 interim_value = self.to_list(interim_value) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 996 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 997 |  |  |                 # Get the {value:text} dict | 
            
                                                                                                            
                            
            
                                    
            
            
                | 998 |  |  |                 choices = choices.split("|") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 999 |  |  |                 choices = dict(map(lambda ch: ch.strip().split(":"), choices)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1000 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1001 |  |  |                 # Generate the display list | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1002 |  |  |                 # [{"ResultValue": value, "ResultText": text},] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1003 |  |  |                 headers = ["ResultValue", "ResultText"] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1004 |  |  |                 dl = map(lambda it: dict(zip(headers, it)), choices.items()) | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1005 |  |  |                 item.setdefault("choices", {})[interim_keyword] = dl | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1006 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1007 |  |  |                 # Set the text as the formatted value | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1008 |  |  |                 texts = [choices.get(v, "") for v in interim_value] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1009 |  |  |                 text = "<br/>".join(filter(None, texts)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1010 |  |  |                 interim_field["formatted_value"] = text | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1011 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1012 |  |  |                 if not is_editable: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1013 |  |  |                     # Display the text instead of the value | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1014 |  |  |                     interim_field["value"] = text | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1015 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1016 |  |  |                 item[interim_keyword] = interim_field | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1017 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1018 |  |  |             elif self.is_multi_interim(interim_field): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1019 |  |  |                 # Process the value as a list | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1020 |  |  |                 interim_value = self.to_list(interim_value) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1021 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1022 |  |  |                 # Set the text as the formatted value | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1023 |  |  |                 text = "<br/>".join(filter(None, interim_value)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1024 |  |  |                 interim_field["formatted_value"] = text | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1025 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1026 |  |  |                 if not is_editable: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1027 |  |  |                     # Display the text instead of the value | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1028 |  |  |                     interim_field["value"] = text | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1029 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1030 |  |  |                 item[interim_keyword] = interim_field | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1031 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1032 |  |  |         item["interimfields"] = interim_fields | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1033 |  |  |         self.interim_fields[analysis_brain.UID] = interim_fields | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1034 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1035 |  |  |     def _folder_item_method(self, analysis_brain, item): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1036 |  |  |         """Fills the analysis' method to the item passed in. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1037 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1038 |  |  |         :param analysis_brain: Brain that represents an analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1039 |  |  |         :param item: analysis' dictionary counterpart that represents a row | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1040 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1041 |  |  |         obj = self.get_object(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1042 |  |  |         is_editable = self.is_analysis_edition_allowed(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1043 |  |  |         if is_editable: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1044 |  |  |             method_vocabulary = self.get_methods_vocabulary(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1045 |  |  |             item["Method"] = obj.getRawMethod() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1046 |  |  |             item["choices"]["Method"] = method_vocabulary | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1047 |  |  |             item["allow_edit"].append("Method") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1048 |  |  |         else: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1049 |  |  |             item["Method"] = _("Manual") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1050 |  |  |             method = obj.getMethod() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1051 |  |  |             if method: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1052 |  |  |                 item["Method"] = api.get_title(method) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1053 |  |  |                 item["replace"]["Method"] = get_link_for(method, tabindex="-1") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1054 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1055 |  |  |     def _on_method_change(self, uid=None, value=None, item=None, **kw): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1056 |  |  |         """Update instrument and calculation when the method changes | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1057 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1058 |  |  |         :param uid: object UID | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1059 |  |  |         :value: UID of the new method | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1060 |  |  |         :item: old folderitem | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1061 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1062 |  |  |         :returns: updated folderitem | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1063 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1064 |  |  |         obj = api.get_object_by_uid(uid, None) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1065 |  |  |         method = api.get_object_by_uid(value, None) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1066 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1067 |  |  |         if not all([obj, method, item]): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1068 |  |  |             return None | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1069 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1070 |  |  |         # update the available instruments | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1071 |  |  |         inst_vocab = self.get_instruments_vocabulary(obj, method=method) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1072 |  |  |         item["choices"]["Instrument"] = inst_vocab | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1073 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1074 |  |  |         return item | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1075 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1076 |  |  |     def _folder_item_instrument(self, analysis_brain, item): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1077 |  |  |         """Fills the analysis' instrument to the item passed in. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1078 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1079 |  |  |         :param analysis_brain: Brain that represents an analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1080 |  |  |         :param item: analysis' dictionary counterpart that represents a row | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1081 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1082 |  |  |         item["Instrument"] = "" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1083 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1084 |  |  |         # Instrument can be assigned to this analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1085 |  |  |         is_editable = self.is_analysis_edition_allowed(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1086 |  |  |         instrument = self.get_instrument(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1087 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1088 |  |  |         if is_editable: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1089 |  |  |             # Edition allowed | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1090 |  |  |             voc = self.get_instruments_vocabulary(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1091 |  |  |             item["Instrument"] = instrument.UID() if instrument else "" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1092 |  |  |             item["choices"]["Instrument"] = voc | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1093 |  |  |             item["allow_edit"].append("Instrument") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1094 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1095 |  |  |         elif instrument: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1096 |  |  |             # Edition not allowed | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1097 |  |  |             item["Instrument"] = api.get_title(instrument) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1098 |  |  |             instrument_link = get_link_for(instrument, tabindex="-1") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1099 |  |  |             item["replace"]["Instrument"] = instrument_link | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1100 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1101 |  |  |         else: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1102 |  |  |             item["Instrument"] = _("Manual") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1103 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1104 |  |  |     def _folder_item_analyst(self, obj, item): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1105 |  |  |         obj = self.get_object(obj) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1106 |  |  |         analyst = obj.getAnalyst() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1107 |  |  |         item["Analyst"] = self.get_user_name(analyst) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1108 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1109 |  |  |     def _folder_item_submitted_by(self, obj, item): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1110 |  |  |         obj = self.get_object(obj) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1111 |  |  |         submitted_by = obj.getSubmittedBy() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1112 |  |  |         item["SubmittedBy"] = self.get_user_name(submitted_by) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1113 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1114 |  |  |     @viewcache.memoize | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1115 |  |  |     def get_user_name(self, user_id): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1116 |  |  |         if not user_id: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1117 |  |  |             return "" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1118 |  |  |         user = api.get_user_properties(user_id) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1119 |  |  |         return user and user.get("fullname") or user_id | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1120 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1121 |  |  |     def _folder_item_attachments(self, obj, item): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1122 |  |  |         if not self.has_permission(ViewResults, obj): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1123 |  |  |             return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1124 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1125 |  |  |         attachments_names = [] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1126 |  |  |         attachments_html = [] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1127 |  |  |         analysis = self.get_object(obj) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1128 |  |  |         for at in analysis.getAttachment(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1129 |  |  |             at_file = at.getAttachmentFile() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1130 |  |  |             url = "{}/at_download/AttachmentFile".format(api.get_url(at)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1131 |  |  |             link = get_link(url, at_file.filename, tabindex="-1") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1132 |  |  |             attachments_html.append(link) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1133 |  |  |             attachments_names.append(at_file.filename) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1134 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1135 |  |  |         if attachments_html: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1136 |  |  |             item["replace"]["Attachments"] = "<br/>".join(attachments_html) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1137 |  |  |             item["Attachments"] = ", ".join(attachments_names) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1138 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1139 |  |  |         elif analysis.getAttachmentRequired(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1140 |  |  |             img = get_image("warning.png", title=_("Attachment required")) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1141 |  |  |             item["replace"]["Attachments"] = img | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 1142 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 1143 |  |  |     def _folder_item_uncertainty(self, analysis_brain, item): | 
            
                                                                        
                            
            
                                    
            
            
                | 1144 |  |  |         """Fills the analysis' uncertainty to the item passed in. | 
            
                                                                        
                            
            
                                    
            
            
                | 1145 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 1146 |  |  |         :param analysis_brain: Brain that represents an analysis | 
            
                                                                        
                            
            
                                    
            
            
                | 1147 |  |  |         :param item: analysis' dictionary counterpart that represents a row | 
            
                                                                        
                            
            
                                    
            
            
                | 1148 |  |  |         """ | 
            
                                                                        
                            
            
                                    
            
            
                | 1149 |  |  |         item["Uncertainty"] = "" | 
            
                                                                        
                            
            
                                    
            
            
                | 1150 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 1151 |  |  |         if not self.has_permission(ViewResults, analysis_brain): | 
            
                                                                        
                            
            
                                    
            
            
                | 1152 |  |  |             return | 
            
                                                                        
                            
            
                                    
            
            
                | 1153 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 1154 |  |  |         # Wake up the Analysis object | 
            
                                                                        
                            
            
                                    
            
            
                | 1155 |  |  |         obj = self.get_object(analysis_brain) | 
            
                                                                        
                            
            
                                    
            
            
                | 1156 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 1157 |  |  |         # NOTE: When we allow to edit the uncertainty, we want to have the raw | 
            
                                                                        
                            
            
                                    
            
            
                | 1158 |  |  |         #       uncertainty value and not the formatted (and possibly rounded)! | 
            
                                                                        
                            
            
                                    
            
            
                | 1159 |  |  |         #       This ensures that not the rounded value get stored | 
            
                                                                        
                            
            
                                    
            
            
                | 1160 |  |  |         allow_edit = self.is_uncertainty_edition_allowed(analysis_brain) | 
            
                                                                        
                            
            
                                    
            
            
                | 1161 |  |  |         if allow_edit: | 
            
                                                                        
                            
            
                                    
            
            
                | 1162 |  |  |             item["Uncertainty"] = obj.getUncertainty() | 
            
                                                                        
                            
            
                                    
            
            
                | 1163 |  |  |             item["allow_edit"].append("Uncertainty") | 
            
                                                                        
                            
            
                                    
            
            
                | 1164 |  |  |             return | 
            
                                                                        
                            
            
                                    
            
            
                | 1165 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 1166 |  |  |         result = obj.getResult() | 
            
                                                                        
                            
            
                                    
            
            
                | 1167 |  |  |         formatted = format_uncertainty( | 
            
                                                                        
                            
            
                                    
            
            
                | 1168 |  |  |             obj, result, decimalmark=self.dmk, sciformat=int(self.scinot)) | 
            
                                                                        
                            
            
                                    
            
            
                | 1169 |  |  |         if formatted: | 
            
                                                                        
                            
            
                                    
            
            
                | 1170 |  |  |             item["replace"]["Uncertainty"] = formatted | 
            
                                                                        
                            
            
                                    
            
            
                | 1171 |  |  |             item["before"]["Uncertainty"] = "± " | 
            
                                                                        
                            
            
                                    
            
            
                | 1172 |  |  |             item["after"]["Uncertainty"] = obj.getUnit() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1173 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1174 |  |  |     def _folder_item_detection_limits(self, analysis_brain, item): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1175 |  |  |         """Fills the analysis' detection limits to the item passed in. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1176 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1177 |  |  |         :param analysis_brain: Brain that represents an analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1178 |  |  |         :param item: analysis' dictionary counterpart that represents a row | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1179 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1180 |  |  |         item["DetectionLimitOperand"] = "" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1181 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1182 |  |  |         if not self.is_analysis_edition_allowed(analysis_brain): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1183 |  |  |             # Return immediately if the we are not in edit mode | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1184 |  |  |             return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1185 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1186 |  |  |         # TODO: Performance, we wake-up the full object here | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1187 |  |  |         obj = self.get_object(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1188 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1189 |  |  |         # No Detection Limit Selection | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1190 |  |  |         if not obj.getDetectionLimitSelector(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1191 |  |  |             return None | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1192 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1193 |  |  |         # Show Detection Limit Operand Selector | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1194 |  |  |         item["DetectionLimitOperand"] = obj.getDetectionLimitOperand() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1195 |  |  |         item["allow_edit"].append("DetectionLimitOperand") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1196 |  |  |         self.columns["DetectionLimitOperand"]["toggle"] = True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1197 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1198 |  |  |         # Prepare selection list for LDL/UDL | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1199 |  |  |         choices = [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1200 |  |  |             {"ResultValue": "", "ResultText": ""}, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1201 |  |  |             {"ResultValue": LDL, "ResultText": LDL}, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1202 |  |  |             {"ResultValue": UDL, "ResultText": UDL} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1203 |  |  |         ] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1204 |  |  |         # Set the choices to the item | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1205 |  |  |         item["choices"]["DetectionLimitOperand"] = choices | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1206 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1207 |  |  |     def _folder_item_specifications(self, analysis_brain, item): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1208 |  |  |         """Set the results range to the item passed in""" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1209 |  |  |         analysis = self.get_object(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1210 |  |  |         results_range = analysis.getResultsRange() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1211 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1212 |  |  |         item["Specification"] = "" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1213 |  |  |         if results_range: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1214 |  |  |             item["Specification"] = get_formatted_interval(results_range, "") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1215 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1216 |  |  |     def _folder_item_out_of_range(self, analysis_brain, item): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1217 |  |  |         """Displays an icon if result is out of range | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1218 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1219 |  |  |         if not self.has_permission(ViewResults, analysis_brain): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1220 |  |  |             # Users without permissions to see the result should not be able | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1221 |  |  |             # to see if the result is out of range naither | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1222 |  |  |             return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1223 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1224 |  |  |         analysis = self.get_object(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1225 |  |  |         out_range, out_shoulders = is_out_of_range(analysis) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1226 |  |  |         if out_range: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1227 |  |  |             msg = _("Result out of range") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1228 |  |  |             img = get_image("exclamation.png", title=msg) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1229 |  |  |             if not out_shoulders: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1230 |  |  |                 msg = _("Result in shoulder range") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1231 |  |  |                 img = get_image("warning.png", title=msg) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1232 |  |  |             self._append_html_element(item, "Result", img) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1233 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1234 |  |  |     def _folder_item_result_range_compliance(self, analysis_brain, item): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1235 |  |  |         """Displays an icon if the range is different from the results ranges | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1236 |  |  |         defined in the Sample | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1237 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1238 |  |  |         if not IAnalysisRequest.providedBy(self.context): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1239 |  |  |             return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1240 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1241 |  |  |         analysis = self.get_object(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1242 |  |  |         if is_result_range_compliant(analysis): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1243 |  |  |             return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1244 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1245 |  |  |         # Non-compliant range, display an icon | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1246 |  |  |         service_uid = analysis_brain.getServiceUID | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1247 |  |  |         original = self.context.getResultsRange(search_by=service_uid) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1248 |  |  |         original = get_formatted_interval(original, "") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1249 |  |  |         msg = _("Result range is different from Specification: {}" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1250 |  |  |                 .format(original)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1251 |  |  |         img = get_image("warning.png", title=msg) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1252 |  |  |         self._append_html_element(item, "Specification", img) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1253 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1254 |  |  |     def _folder_item_verify_icons(self, analysis_brain, item): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1255 |  |  |         """Set the analysis' verification icons to the item passed in. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1256 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1257 |  |  |         :param analysis_brain: Brain that represents an analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1258 |  |  |         :param item: analysis' dictionary counterpart that represents a row | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1259 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1260 |  |  |         submitter = analysis_brain.getSubmittedBy | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1261 |  |  |         if not submitter: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1262 |  |  |             # This analysis hasn't yet been submitted, no verification yet | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1263 |  |  |             return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1264 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1265 |  |  |         if analysis_brain.review_state == 'retracted': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1266 |  |  |             # Don't display icons and additional info about verification | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1267 |  |  |             return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1268 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1269 |  |  |         verifiers = analysis_brain.getVerificators | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1270 |  |  |         in_verifiers = submitter in verifiers | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1271 |  |  |         if in_verifiers: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1272 |  |  |             # If analysis has been submitted and verified by the same person, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1273 |  |  |             # display a warning icon | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1274 |  |  |             msg = t(_("Submitted and verified by the same user: {}")) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1275 |  |  |             icon = get_image('warning.png', title=msg.format(submitter)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1276 |  |  |             self._append_html_element(item, 'state_title', icon) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1277 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1278 |  |  |         num_verifications = analysis_brain.getNumberOfRequiredVerifications | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1279 |  |  |         if num_verifications > 1: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1280 |  |  |             # More than one verification required, place an icon and display | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1281 |  |  |             # the number of verifications done vs. total required | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1282 |  |  |             done = analysis_brain.getNumberOfVerifications | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1283 |  |  |             pending = num_verifications - done | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1284 |  |  |             ratio = float(done) / float(num_verifications) if done > 0 else 0 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1285 |  |  |             ratio = int(ratio * 100) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1286 |  |  |             scale = ratio == 0 and 0 or (ratio / 25) * 25 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1287 |  |  |             anchor = "<a href='#' tabindex='-1' title='{} 
{} {}' " \ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1288 |  |  |                      "class='multi-verification scale-{}'>{}/{}</a>" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1289 |  |  |             anchor = anchor.format(t(_("Multi-verification required")), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1290 |  |  |                                    str(pending), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1291 |  |  |                                    t(_("verification(s) pending")), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1292 |  |  |                                    str(scale), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1293 |  |  |                                    str(done), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1294 |  |  |                                    str(num_verifications)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1295 |  |  |             self._append_html_element(item, 'state_title', anchor) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1296 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1297 |  |  |         if analysis_brain.review_state != 'to_be_verified': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1298 |  |  |             # The verification of analysis has already been done or first | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1299 |  |  |             # verification has not been done yet. Nothing to do | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1300 |  |  |             return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1301 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1302 |  |  |         # Check if the user has "Bika: Verify" privileges | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1303 |  |  |         if not self.has_permission(TransitionVerify): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1304 |  |  |             # User cannot verify, do nothing | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1305 |  |  |             return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1306 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1307 |  |  |         username = api.get_current_user().id | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1308 |  |  |         if username not in verifiers: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1309 |  |  |             # Current user has not verified this analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1310 |  |  |             if submitter != username: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1311 |  |  |                 # Current user is neither a submitter nor a verifier | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1312 |  |  |                 return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1313 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1314 |  |  |             # Current user is the same who submitted the result | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1315 |  |  |             if analysis_brain.isSelfVerificationEnabled: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1316 |  |  |                 # Same user who submitted can verify | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1317 |  |  |                 title = t(_("Can verify, but submitted by current user")) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1318 |  |  |                 html = get_image('warning.png', title=title) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1319 |  |  |                 self._append_html_element(item, 'state_title', html) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1320 |  |  |                 return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1321 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1322 |  |  |             # User who submitted cannot verify | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1323 |  |  |             title = t(_("Cannot verify, submitted by current user")) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1324 |  |  |             html = get_image('submitted-by-current-user.png', title=title) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1325 |  |  |             self._append_html_element(item, 'state_title', html) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1326 |  |  |             return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1327 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1328 |  |  |         # This user verified this analysis before | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1329 |  |  |         multi_verif = self.context.bika_setup.getTypeOfmultiVerification() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1330 |  |  |         if multi_verif != 'self_multi_not_cons': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1331 |  |  |             # Multi verification by same user is not allowed | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1332 |  |  |             title = t(_("Cannot verify, was verified by current user")) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1333 |  |  |             html = get_image('submitted-by-current-user.png', title=title) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1334 |  |  |             self._append_html_element(item, 'state_title', html) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1335 |  |  |             return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1336 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1337 |  |  |         # Multi-verification by same user, but non-consecutively, is allowed | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1338 |  |  |         if analysis_brain.getLastVerificator != username: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1339 |  |  |             # Current user was not the last user to verify | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1340 |  |  |             title = t( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1341 |  |  |                 _("Can verify, but was already verified by current user")) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1342 |  |  |             html = get_image('warning.png', title=title) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1343 |  |  |             self._append_html_element(item, 'state_title', html) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1344 |  |  |             return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1345 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1346 |  |  |         # Last user who verified is the same as current user | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1347 |  |  |         title = t(_("Cannot verify, last verified by current user")) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1348 |  |  |         html = get_image('submitted-by-current-user.png', title=title) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1349 |  |  |         self._append_html_element(item, 'state_title', html) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1350 |  |  |         return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1351 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1352 |  |  |     def _folder_item_assigned_worksheet(self, analysis_brain, item): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1353 |  |  |         """Adds an icon to the item dict if the analysis is assigned to a | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1354 |  |  |         worksheet and if the icon is suitable for the current context | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1355 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1356 |  |  |         :param analysis_brain: Brain that represents an analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1357 |  |  |         :param item: analysis' dictionary counterpart that represents a row | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1358 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1359 |  |  |         if not IAnalysisRequest.providedBy(self.context): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1360 |  |  |             # We want this icon to only appear if the context is an AR | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1361 |  |  |             return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1362 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1363 |  |  |         analysis_obj = self.get_object(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1364 |  |  |         worksheet = analysis_obj.getWorksheet() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1365 |  |  |         if not worksheet: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1366 |  |  |             # No worksheet assigned. Do nothing | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1367 |  |  |             return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1368 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1369 |  |  |         title = t(_("Assigned to: ${worksheet_id}", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1370 |  |  |                     mapping={'worksheet_id': safe_unicode(worksheet.id)})) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1371 |  |  |         img = get_image('worksheet.png', title=title) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1372 |  |  |         anchor = get_link(worksheet.absolute_url(), img, tabindex="-1") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1373 |  |  |         self._append_html_element(item, 'state_title', anchor) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1374 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1375 |  |  |     def _folder_item_accredited_icon(self, analysis_brain, item): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1376 |  |  |         """Adds an icon to the item dictionary if it is an accredited analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1377 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1378 |  |  |         full_obj = self.get_object(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1379 |  |  |         if full_obj.getAccredited(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1380 |  |  |             img = get_image("accredited.png", title=t(_("Accredited"))) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1381 |  |  |             self._append_html_element(item, "Service", img) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1382 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1383 |  |  |     def _folder_item_partition(self, analysis_brain, item): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1384 |  |  |         """Adds an anchor to the partition if the current analysis is from a | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1385 |  |  |         partition that does not match with the current context | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1386 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1387 |  |  |         if not IAnalysisRequest.providedBy(self.context): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1388 |  |  |             return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1389 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1390 |  |  |         sample_id = analysis_brain.getRequestID | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1391 |  |  |         if sample_id != api.get_id(self.context): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1392 |  |  |             if not self.show_partitions: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1393 |  |  |                 # Do not display the link | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1394 |  |  |                 return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1395 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1396 |  |  |             part_url = analysis_brain.getRequestURL | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1397 |  |  |             kwargs = {"class": "small", "tabindex": "-1"} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1398 |  |  |             url = get_link(part_url, value=sample_id, **kwargs) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1399 |  |  |             title = item["replace"].get("Service") or item["Service"] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1400 |  |  |             item["replace"]["Service"] = "{}<br/>{}".format(title, url) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1401 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1402 |  |  |     def _folder_item_report_visibility(self, analysis_brain, item): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1403 |  |  |         """Set if the hidden field can be edited (enabled/disabled) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1404 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1405 |  |  |         :analysis_brain: Brain that represents an analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1406 |  |  |         :item: analysis' dictionary counterpart to be represented as a row""" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1407 |  |  |         # Users that can Add Analyses to an Analysis Request must be able to | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1408 |  |  |         # set the visibility of the analysis in results report, also if the | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1409 |  |  |         # current state of the Analysis Request (e.g. verified) does not allow | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1410 |  |  |         # the edition of other fields. Note that an analyst has no privileges | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1411 |  |  |         # by default to edit this value, cause this "visibility" field is | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1412 |  |  |         # related with results reporting and/or visibility from the client | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1413 |  |  |         # side. This behavior only applies to routine analyses, the visibility | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1414 |  |  |         # of QC analyses is managed in publish and are not visible to clients. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1415 |  |  |         if 'Hidden' not in self.columns: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1416 |  |  |             return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1417 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1418 |  |  |         full_obj = self.get_object(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1419 |  |  |         item['Hidden'] = full_obj.getHidden() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1420 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1421 |  |  |         # Hidden checkbox is not reachable by tabbing | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1422 |  |  |         item["tabindex"]["Hidden"] = "disabled" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1423 |  |  |         if self.has_permission(FieldEditAnalysisHidden, obj=full_obj): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1424 |  |  |             item['allow_edit'].append('Hidden') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1425 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1426 |  |  |     def _folder_item_fieldicons(self, analysis_brain): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1427 |  |  |         """Resolves if field-specific icons must be displayed for the object | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1428 |  |  |         passed in. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1429 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1430 |  |  |         :param analysis_brain: Brain that represents an analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1431 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1432 |  |  |         full_obj = self.get_object(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1433 |  |  |         uid = api.get_uid(full_obj) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1434 |  |  |         for name, adapter in getAdapters((full_obj,), IFieldIcons): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1435 |  |  |             alerts = adapter() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1436 |  |  |             if not alerts or uid not in alerts: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1437 |  |  |                 continue | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1438 |  |  |             alerts = alerts[uid] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1439 |  |  |             if uid not in self.field_icons: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1440 |  |  |                 self.field_icons[uid] = alerts | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1441 |  |  |                 continue | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1442 |  |  |             self.field_icons[uid].extend(alerts) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1443 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1444 |  |  |     def _folder_item_remarks(self, analysis_brain, item): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1445 |  |  |         """Renders the Remarks field for the passed in analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1446 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1447 |  |  |         If the edition of the analysis is permitted, adds the field into the | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1448 |  |  |         list of editable fields. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1449 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1450 |  |  |         :param analysis_brain: Brain that represents an analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1451 |  |  |         :param item: analysis' dictionary counterpart that represents a row | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1452 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1453 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1454 |  |  |         if self.analysis_remarks_enabled(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1455 |  |  |             item["Remarks"] = analysis_brain.getRemarks | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1456 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1457 |  |  |         if self.is_analysis_edition_allowed(analysis_brain): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1458 |  |  |             item["allow_edit"].extend(["Remarks"]) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1459 |  |  |         else: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1460 |  |  |             # render HTMLified text in readonly mode | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1461 |  |  |             item["Remarks"] = api.text_to_html( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1462 |  |  |                 analysis_brain.getRemarks, wrap=None) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1463 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1464 |  |  |     def _append_html_element(self, item, element, html, glue=" ", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1465 |  |  |                              after=True): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1466 |  |  |         """Appends an html value after or before the element in the item dict | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1467 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1468 |  |  |         :param item: dictionary that represents an analysis row | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1469 |  |  |         :param element: id of the element the html must be added thereafter | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1470 |  |  |         :param html: element to append | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1471 |  |  |         :param glue: glue to use for appending | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1472 |  |  |         :param after: if the html content must be added after or before""" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1473 |  |  |         position = after and 'after' or 'before' | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1474 |  |  |         item[position] = item.get(position, {}) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1475 |  |  |         original = item[position].get(element, '') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1476 |  |  |         if not original: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1477 |  |  |             item[position][element] = html | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1478 |  |  |             return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1479 |  |  |         item[position][element] = glue.join([original, html]) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1480 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1481 |  |  |     def _folder_item_conditions(self, analysis_brain, item): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1482 |  |  |         """Renders the analysis conditions | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1483 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1484 |  |  |         analysis = self.get_object(analysis_brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1485 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1486 |  |  |         if not IRoutineAnalysis.providedBy(analysis): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1487 |  |  |             return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1488 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1489 |  |  |         conditions = analysis.getConditions() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1490 |  |  |         if conditions: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1491 |  |  |             conditions = map(lambda it: ": ".join([it["title"], it["value"]]), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1492 |  |  |                              conditions) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1493 |  |  |             conditions = "<br/>".join(conditions) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1494 |  |  |             service = item["replace"].get("Service") or item["Service"] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1495 |  |  |             item["replace"]["Service"] = "{}<br/>{}".format(service, conditions) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1496 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1497 |  |  |     def is_method_required(self, analysis): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1498 |  |  |         """Returns whether the render of the selection list with methods is | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1499 |  |  |         required for the method passed-in, even if only option "None" is | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1500 |  |  |         displayed for selection | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1501 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1502 |  |  |         # Always return true if the analysis has a method assigned | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1503 |  |  |         obj = self.get_object(analysis) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1504 |  |  |         method = obj.getMethod() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1505 |  |  |         if method: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1506 |  |  |             return True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1507 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1508 |  |  |         methods = obj.getAllowedMethods() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1509 |  |  |         return len(methods) > 0 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1510 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1511 |  |  |     def is_instrument_required(self, analysis): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1512 |  |  |         """Returns whether the render of the selection list with instruments is | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1513 |  |  |         required for the analysis passed-in, even if only option "None" is | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1514 |  |  |         displayed for selection. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1515 |  |  |         :param analysis: Brain or object that represents an analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1516 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1517 |  |  |         # If method selection list is required, the instrument selection too | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1518 |  |  |         if self.is_method_required(analysis): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1519 |  |  |             return True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1520 |  |  |          | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1521 |  |  |         # Always return true if the analysis has an instrument assigned | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1522 |  |  |         if self.get_instrument(analysis): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1523 |  |  |             return True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1524 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1525 |  |  |         obj = self.get_object(analysis) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1526 |  |  |         instruments = obj.getAllowedInstruments() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1527 |  |  |         # There is no need to check for the instruments of the method assigned | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1528 |  |  |         # to # the analysis (if any), because the instruments rendered in the | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1529 |  |  |         # selection list are always a subset of the allowed instruments when | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1530 |  |  |         # a method is selected | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1531 |  |  |         return len(instruments) > 0 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1532 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1533 |  |  |     def is_method_column_required(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1534 |  |  |         """Returns whether the method column has to be rendered or not. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1535 |  |  |         Returns True if at least one of the analyses from the listing requires | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1536 |  |  |         the list for method selection to be rendered | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1537 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1538 |  |  |         for item in self.items: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1539 |  |  |             obj = item.get("obj") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1540 |  |  |             if self.is_method_required(obj): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1541 |  |  |                 return True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1542 |  |  |         return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1543 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1544 |  |  |     def is_instrument_column_required(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1545 |  |  |         """Returns whether the instrument column has to be rendered or not. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1546 |  |  |         Returns True if at least one of the analyses from the listing requires | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1547 |  |  |         the list for instrument selection to be rendered | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1548 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1549 |  |  |         for item in self.items: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1550 |  |  |             obj = item.get("obj") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1551 |  |  |             if self.is_instrument_required(obj): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1552 |  |  |                 return True | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 1553 |  |  |         return False | 
            
                                                        
            
                                    
            
            
                | 1554 |  |  |  |