| 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 |  |  | import six | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  | from collections import OrderedDict | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  | from datetime import datetime | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  | from bika.lims import POINTS_OF_CAPTURE | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  | from bika.lims import api | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  | from bika.lims import bikaMessageFactory as _ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  | from bika.lims import logger | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  | from bika.lims.api.analysisservice import get_calculation_dependencies_for | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  | from bika.lims.api.analysisservice import get_service_dependencies_for | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  | from bika.lims.interfaces import IAddSampleConfirmation | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 |  |  | from bika.lims.interfaces import IAddSampleFieldsFlush | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  | from bika.lims.interfaces import IAddSampleObjectInfo | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 |  |  | from bika.lims.interfaces import IAddSampleRecordsValidator | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 |  |  | from bika.lims.interfaces import IGetDefaultFieldValueARAddHook | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 |  |  | from bika.lims.utils import tmpID | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 |  |  | from bika.lims.utils.analysisrequest import create_analysisrequest as crar | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  | from bika.lims.workflow import ActionHandlerPool | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 |  |  | from BTrees.OOBTree import OOBTree | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 |  |  | from DateTime import DateTime | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 |  |  | from plone import protect | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 |  |  | from plone.memoize import view as viewcache | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  | from plone.memoize.volatile import DontCache | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 |  |  | from plone.memoize.volatile import cache | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 |  |  | from plone.protect.interfaces import IDisableCSRFProtection | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  | from Products.CMFPlone.utils import _createObjectByType | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 |  |  | from Products.CMFPlone.utils import safe_unicode | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 |  |  | from Products.Five.browser import BrowserView | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  | from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  | from senaite.core.p3compat import cmp | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  | from zope.annotation.interfaces import IAnnotations | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  | from zope.component import getAdapters | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  | from zope.component import queryAdapter | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  | from zope.i18n.locales import locales | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  | from zope.interface import alsoProvides | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  | from zope.interface import implements | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 |  |  | from zope.publisher.interfaces import IPublishTraverse | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 |  |  | AR_CONFIGURATION_STORAGE = "bika.lims.browser.analysisrequest.manage.add" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 |  |  | SKIP_FIELD_ON_COPY = ["Sample", "PrimaryAnalysisRequest", "Remarks"] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 |  |  |  | 
            
                                                                                                            
                            
            
                                                                    
                                                                                                        
            
            
                | 65 |  | View Code Duplication | def returns_json(func): | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 |  |  |     """Decorator for functions which return JSON | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 |  |  |     """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 |  |  |     def decorator(*args, **kwargs): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  |         instance = args[0] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 |  |  |         request = getattr(instance, 'request', None) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 |  |  |         request.response.setHeader("Content-Type", "application/json") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 |  |  |         result = func(*args, **kwargs) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  |         return json.dumps(result) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  |     return decorator | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  | def cache_key(method, self, obj): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 |  |  |     if obj is None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 |  |  |         raise DontCache | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  |     return api.get_cache_key(obj) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 |  |  | class AnalysisRequestAddView(BrowserView): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  |     """AR Add view | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  |     """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  |     template = ViewPageTemplateFile("templates/ar_add2.pt") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  |     def __init__(self, context, request): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  |         super(AnalysisRequestAddView, self).__init__(context, request) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 |  |  |         # disable CSRF protection | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 |  |  |         alsoProvides(request, IDisableCSRFProtection) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 |  |  |         self.request = request | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |         self.context = context | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 |  |  |         self.fieldvalues = {} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 |  |  |         self.tmp_ar = None | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  |     def __call__(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 |  |  |         self.portal = api.get_portal() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 |  |  |         self.portal_url = self.portal.absolute_url() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 |  |  |         self.setup = api.get_setup() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 |  |  |         self.request.set("disable_plone.rightcolumn", 1) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 |  |  |         self.came_from = "add" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 |  |  |         self.tmp_ar = self.get_ar() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 |  |  |         self.ar_count = self.get_ar_count() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 |  |  |         self.fieldvalues = self.generate_fieldvalues(self.ar_count) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 |  |  |         self.ShowPrices = self.setup.getShowPrices() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 |  |  |         self.theme = api.get_view("senaite_theme") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 |  |  |         self.icon = self.theme.icon_url("Sample") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 |  |  |         logger.debug("*** Prepared data for {} ARs ***".format(self.ar_count)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 |  |  |         return self.template() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 |  |  |     def get_view_url(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 |  |  |         """Return the current view url including request parameters | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  |         request = self.request | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 |  |  |         url = request.getURL() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  |         qs = request.getHeader("query_string") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  |         if not qs: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  |             return url | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 |  |  |         return "{}?{}".format(url, qs) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 |  |  |     # N.B.: We are caching here persistent objects! | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  |     #       It should be safe to do this but only on the view object, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 |  |  |     #       because it get recreated per request (transaction border). | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 |  |  |     @viewcache.memoize | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 |  |  |     def get_object_by_uid(self, uid): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 |  |  |         """Get the object by UID | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 |  |  |         logger.debug("get_object_by_uid::UID={}".format(uid)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 |  |  |         obj = api.get_object_by_uid(uid, None) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 |  |  |         if obj is None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 |  |  |             logger.warn("!! No object found for UID #{} !!") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 |  |  |         return obj | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 |  |  |     @viewcache.memoize | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 |  |  |     def analyses_required(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 |  |  |         """Check if analyses are required | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 |  |  |         setup = api.get_setup() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 140 |  |  |         return setup.getSampleAnalysesRequired() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 141 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 142 |  |  |     def get_currency(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 143 |  |  |         """Returns the configured currency | 
            
                                                                                                            
                            
            
                                    
            
            
                | 144 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 145 |  |  |         setup = api.get_setup() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 146 |  |  |         currency = setup.getCurrency() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 147 |  |  |         currencies = locales.getLocale('en').numbers.currencies | 
            
                                                                                                            
                            
            
                                    
            
            
                | 148 |  |  |         return currencies[currency] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 149 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 150 |  |  |     def get_ar_count(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 151 |  |  |         """Return the ar_count request paramteter | 
            
                                                                                                            
                            
            
                                    
            
            
                | 152 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 153 |  |  |         ar_count = 1 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 154 |  |  |         try: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 155 |  |  |             ar_count = int(self.request.form.get("ar_count", 1)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 156 |  |  |         except (TypeError, ValueError): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 157 |  |  |             ar_count = 1 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 158 |  |  |         return ar_count | 
            
                                                                                                            
                            
            
                                    
            
            
                | 159 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 160 |  |  |     def get_ar(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 161 |  |  |         """Create a temporary AR to fetch the fields from | 
            
                                                                                                            
                            
            
                                    
            
            
                | 162 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 163 |  |  |         if not self.tmp_ar: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 164 |  |  |             logger.debug("*** CREATING TEMPORARY AR ***") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 165 |  |  |             self.tmp_ar = self.context.restrictedTraverse( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 166 |  |  |                 "portal_factory/AnalysisRequest/Request new analyses") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 167 |  |  |         return self.tmp_ar | 
            
                                                                                                            
                            
            
                                    
            
            
                | 168 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 169 |  |  |     def get_ar_schema(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 170 |  |  |         """Return the AR schema | 
            
                                                                                                            
                            
            
                                    
            
            
                | 171 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 172 |  |  |         logger.debug("*** GET AR SCHEMA ***") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 173 |  |  |         ar = self.get_ar() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 174 |  |  |         return ar.Schema() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 175 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 176 |  |  |     def get_ar_fields(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 177 |  |  |         """Return the AR schema fields (including extendend fields) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 178 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 179 |  |  |         logger.debug("*** GET AR FIELDS ***") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 180 |  |  |         schema = self.get_ar_schema() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 181 |  |  |         return schema.fields() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 182 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 183 |  |  |     def get_fieldname(self, field, arnum): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 184 |  |  |         """Generate a new fieldname with a '-<arnum>' suffix | 
            
                                                                                                            
                            
            
                                    
            
            
                | 185 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 186 |  |  |         name = field.getName() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 187 |  |  |         # ensure we have only *one* suffix | 
            
                                                                                                            
                            
            
                                    
            
            
                | 188 |  |  |         base_name = name.split("-")[0] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 189 |  |  |         suffix = "-{}".format(arnum) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 190 |  |  |         return "{}{}".format(base_name, suffix) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 191 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 192 |  |  |     def get_input_widget(self, fieldname, arnum=0, **kw): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 193 |  |  |         """Get the field widget of the AR in column <arnum> | 
            
                                                                                                            
                            
            
                                    
            
            
                | 194 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 195 |  |  |         :param fieldname: The base fieldname | 
            
                                                                                                            
                            
            
                                    
            
            
                | 196 |  |  |         :type fieldname: string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 197 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 198 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 199 |  |  |         # temporary AR Context | 
            
                                                                                                            
                            
            
                                    
            
            
                | 200 |  |  |         context = self.get_ar() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 201 |  |  |         # request = self.request | 
            
                                                                                                            
                            
            
                                    
            
            
                | 202 |  |  |         schema = context.Schema() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 203 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 204 |  |  |         # get original field in the schema from the base_fieldname | 
            
                                                                                                            
                            
            
                                    
            
            
                | 205 |  |  |         base_fieldname = fieldname.split("-")[0] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 206 |  |  |         field = context.getField(base_fieldname) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 207 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 208 |  |  |         # fieldname with -<arnum> suffix | 
            
                                                                                                            
                            
            
                                    
            
            
                | 209 |  |  |         new_fieldname = self.get_fieldname(field, arnum) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 210 |  |  |         new_field = field.copy(name=new_fieldname) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 211 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 212 |  |  |         # get the default value for this field | 
            
                                                                                                            
                            
            
                                    
            
            
                | 213 |  |  |         fieldvalues = self.fieldvalues | 
            
                                                                                                            
                            
            
                                    
            
            
                | 214 |  |  |         field_value = fieldvalues.get(new_fieldname) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 215 |  |  |         # request_value = request.form.get(new_fieldname) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 216 |  |  |         # value = request_value or field_value | 
            
                                                                                                            
                            
            
                                    
            
            
                | 217 |  |  |         value = field_value | 
            
                                                                                                            
                            
            
                                    
            
            
                | 218 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 219 |  |  |         def getAccessor(instance): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 220 |  |  |             def accessor(**kw): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 221 |  |  |                 return value | 
            
                                                                                                            
                            
            
                                    
            
            
                | 222 |  |  |             return accessor | 
            
                                                                                                            
                            
            
                                    
            
            
                | 223 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 224 |  |  |         # inject the new context for the widget renderer | 
            
                                                                                                            
                            
            
                                    
            
            
                | 225 |  |  |         # see: Products.Archetypes.Renderer.render | 
            
                                                                                                            
                            
            
                                    
            
            
                | 226 |  |  |         kw["here"] = context | 
            
                                                                                                            
                            
            
                                    
            
            
                | 227 |  |  |         kw["context"] = context | 
            
                                                                                                            
                            
            
                                    
            
            
                | 228 |  |  |         kw["fieldName"] = new_fieldname | 
            
                                                                                                            
                            
            
                                    
            
            
                | 229 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 230 |  |  |         # make the field available with this name | 
            
                                                                                                            
                            
            
                                    
            
            
                | 231 |  |  |         # XXX: This is a hack to make the widget available in the template | 
            
                                                                                                            
                            
            
                                    
            
            
                | 232 |  |  |         schema._fields[new_fieldname] = new_field | 
            
                                                                                                            
                            
            
                                    
            
            
                | 233 |  |  |         new_field.getAccessor = getAccessor | 
            
                                                                                                            
                            
            
                                    
            
            
                | 234 |  |  |         new_field.getEditAccessor = getAccessor | 
            
                                                                                                            
                            
            
                                    
            
            
                | 235 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 236 |  |  |         # set the default value | 
            
                                                                                                            
                            
            
                                    
            
            
                | 237 |  |  |         form = dict() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 238 |  |  |         form[new_fieldname] = value | 
            
                                                                                                            
                            
            
                                    
            
            
                | 239 |  |  |         self.request.form.update(form) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 240 |  |  |         logger.debug("get_input_widget: fieldname={} arnum={} " | 
            
                                                                                                            
                            
            
                                    
            
            
                | 241 |  |  |                      "-> new_fieldname={} value={}".format( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 242 |  |  |                          fieldname, arnum, new_fieldname, value)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 243 |  |  |         widget = context.widget(new_fieldname, **kw) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 244 |  |  |         return widget | 
            
                                                                                                            
                            
            
                                    
            
            
                | 245 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 246 |  |  |     def get_copy_from(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 247 |  |  |         """Returns a mapping of UID index -> AR object | 
            
                                                                                                            
                            
            
                                    
            
            
                | 248 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 249 |  |  |         # Create a mapping of source ARs for copy | 
            
                                                                                                            
                            
            
                                    
            
            
                | 250 |  |  |         copy_from = self.request.form.get("copy_from", "").split(",") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 251 |  |  |         # clean out empty strings | 
            
                                                                                                            
                            
            
                                    
            
            
                | 252 |  |  |         copy_from_uids = filter(lambda x: x, copy_from) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 253 |  |  |         out = dict().fromkeys(range(len(copy_from_uids))) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 254 |  |  |         for n, uid in enumerate(copy_from_uids): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 255 |  |  |             ar = self.get_object_by_uid(uid) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 256 |  |  |             if ar is None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 257 |  |  |                 continue | 
            
                                                                                                            
                            
            
                                    
            
            
                | 258 |  |  |             out[n] = ar | 
            
                                                                                                            
                            
            
                                    
            
            
                | 259 |  |  |         logger.info("get_copy_from: uids={}".format(copy_from_uids)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 260 |  |  |         return out | 
            
                                                                                                            
                            
            
                                    
            
            
                | 261 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 262 |  |  |     def get_default_value(self, field, context, arnum): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 263 |  |  |         """Get the default value of the field | 
            
                                                                                                            
                            
            
                                    
            
            
                | 264 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 265 |  |  |         name = field.getName() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 266 |  |  |         default = field.getDefault(context) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 267 |  |  |         if name == "Batch": | 
            
                                                                                                            
                            
            
                                    
            
            
                | 268 |  |  |             batch = self.get_batch() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 269 |  |  |             if batch is not None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 270 |  |  |                 default = batch | 
            
                                                                                                            
                            
            
                                    
            
            
                | 271 |  |  |         if name == "Client": | 
            
                                                                                                            
                            
            
                                    
            
            
                | 272 |  |  |             client = self.get_client() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 273 |  |  |             if client is not None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 274 |  |  |                 default = client | 
            
                                                                                                            
                            
            
                                    
            
            
                | 275 |  |  |         # only set default contact for first column | 
            
                                                                                                            
                            
            
                                    
            
            
                | 276 |  |  |         if name == "Contact" and arnum == 0: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 277 |  |  |             contact = self.get_default_contact() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 278 |  |  |             if contact is not None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 279 |  |  |                 default = contact | 
            
                                                                                                            
                            
            
                                    
            
            
                | 280 |  |  |         if name == "Sample": | 
            
                                                                                                            
                            
            
                                    
            
            
                | 281 |  |  |             sample = self.get_sample() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 282 |  |  |             if sample is not None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 283 |  |  |                 default = sample | 
            
                                                                                                            
                            
            
                                    
            
            
                | 284 |  |  |         # Querying for adapters to get default values from add-ons': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 285 |  |  |         # We don't know which fields the form will render since | 
            
                                                                                                            
                            
            
                                    
            
            
                | 286 |  |  |         # some of them may come from add-ons. In order to obtain the default | 
            
                                                                                                            
                            
            
                                    
            
            
                | 287 |  |  |         # value for those fields we take advantage of adapters. Adapters | 
            
                                                                                                            
                            
            
                                    
            
            
                | 288 |  |  |         # registration should have the following format: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 289 |  |  |         # < adapter | 
            
                                                                                                            
                            
            
                                    
            
            
                | 290 |  |  |         #   factory = ... | 
            
                                                                                                            
                            
            
                                    
            
            
                | 291 |  |  |         #   for = "*" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 292 |  |  |         #   provides = "bika.lims.interfaces.IGetDefaultFieldValueARAddHook" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 293 |  |  |         #   name = "<fieldName>_default_value_hook" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 294 |  |  |         # / > | 
            
                                                                                                            
                            
            
                                    
            
            
                | 295 |  |  |         hook_name = name + '_default_value_hook' | 
            
                                                                                                            
                            
            
                                    
            
            
                | 296 |  |  |         adapter = queryAdapter( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 297 |  |  |             self.request, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 298 |  |  |             name=hook_name, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 299 |  |  |             interface=IGetDefaultFieldValueARAddHook) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 300 |  |  |         if adapter is not None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 301 |  |  |             default = adapter(self.context) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 302 |  |  |         logger.debug("get_default_value: context={} field={} value={} arnum={}" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 303 |  |  |                      .format(context, name, default, arnum)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 304 |  |  |         return default | 
            
                                                                                                            
                            
            
                                    
            
            
                | 305 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 306 |  |  |     def get_field_value(self, field, context): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 307 |  |  |         """Get the stored value of the field | 
            
                                                                                                            
                            
            
                                    
            
            
                | 308 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 309 |  |  |         name = field.getName() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 310 |  |  |         value = context.getField(name).get(context) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 311 |  |  |         logger.debug("get_field_value: context={} field={} value={}".format( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 312 |  |  |             context, name, value)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 313 |  |  |         return value | 
            
                                                                                                            
                            
            
                                    
            
            
                | 314 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 315 |  |  |     def get_client(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 316 |  |  |         """Returns the Client | 
            
                                                                                                            
                            
            
                                    
            
            
                | 317 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 318 |  |  |         context = self.context | 
            
                                                                                                            
                            
            
                                    
            
            
                | 319 |  |  |         parent = api.get_parent(context) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 320 |  |  |         if context.portal_type == "Client": | 
            
                                                                                                            
                            
            
                                    
            
            
                | 321 |  |  |             return context | 
            
                                                                                                            
                            
            
                                    
            
            
                | 322 |  |  |         elif parent.portal_type == "Client": | 
            
                                                                                                            
                            
            
                                    
            
            
                | 323 |  |  |             return parent | 
            
                                                                                                            
                            
            
                                    
            
            
                | 324 |  |  |         elif context.portal_type == "Batch": | 
            
                                                                                                            
                            
            
                                    
            
            
                | 325 |  |  |             return context.getClient() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 326 |  |  |         elif parent.portal_type == "Batch": | 
            
                                                                                                            
                            
            
                                    
            
            
                | 327 |  |  |             return context.getClient() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 328 |  |  |         return None | 
            
                                                                                                            
                            
            
                                    
            
            
                | 329 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 330 |  |  |     def get_sample(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 331 |  |  |         """Returns the Sample | 
            
                                                                                                            
                            
            
                                    
            
            
                | 332 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 333 |  |  |         context = self.context | 
            
                                                                                                            
                            
            
                                    
            
            
                | 334 |  |  |         if context.portal_type == "Sample": | 
            
                                                                                                            
                            
            
                                    
            
            
                | 335 |  |  |             return context | 
            
                                                                                                            
                            
            
                                    
            
            
                | 336 |  |  |         return None | 
            
                                                                                                            
                            
            
                                    
            
            
                | 337 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 338 |  |  |     def get_batch(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 339 |  |  |         """Returns the Batch | 
            
                                                                                                            
                            
            
                                    
            
            
                | 340 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 341 |  |  |         context = self.context | 
            
                                                                                                            
                            
            
                                    
            
            
                | 342 |  |  |         parent = api.get_parent(context) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 343 |  |  |         if context.portal_type == "Batch": | 
            
                                                                                                            
                            
            
                                    
            
            
                | 344 |  |  |             return context | 
            
                                                                                                            
                            
            
                                    
            
            
                | 345 |  |  |         elif parent.portal_type == "Batch": | 
            
                                                                                                            
                            
            
                                    
            
            
                | 346 |  |  |             return parent | 
            
                                                                                                            
                            
            
                                    
            
            
                | 347 |  |  |         return None | 
            
                                                                                                            
                            
            
                                    
            
            
                | 348 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 349 |  |  |     def get_parent_ar(self, ar): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 350 |  |  |         """Returns the parent AR | 
            
                                                                                                            
                            
            
                                    
            
            
                | 351 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 352 |  |  |         parent = ar.getParentAnalysisRequest() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 353 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 354 |  |  |         # Return immediately if we have no parent | 
            
                                                                                                            
                            
            
                                    
            
            
                | 355 |  |  |         if parent is None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 356 |  |  |             return None | 
            
                                                                                                            
                            
            
                                    
            
            
                | 357 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 358 |  |  |         # Walk back the chain until we reach the source AR | 
            
                                                                                                            
                            
            
                                    
            
            
                | 359 |  |  |         while True: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 360 |  |  |             pparent = parent.getParentAnalysisRequest() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 361 |  |  |             if pparent is None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 362 |  |  |                 break | 
            
                                                                                                            
                            
            
                                    
            
            
                | 363 |  |  |             # remember the new parent | 
            
                                                                                                            
                            
            
                                    
            
            
                | 364 |  |  |             parent = pparent | 
            
                                                                                                            
                            
            
                                    
            
            
                | 365 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 366 |  |  |         return parent | 
            
                                                                                                            
                            
            
                                    
            
            
                | 367 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 368 |  |  |     def generate_fieldvalues(self, count=1): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 369 |  |  |         """Returns a mapping of '<fieldname>-<count>' to the default value | 
            
                                                                                                            
                            
            
                                    
            
            
                | 370 |  |  |         of the field or the field value of the source AR | 
            
                                                                                                            
                            
            
                                    
            
            
                | 371 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 372 |  |  |         ar_context = self.get_ar() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 373 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 374 |  |  |         # mapping of UID index to AR objects {1: <AR1>, 2: <AR2> ...} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 375 |  |  |         copy_from = self.get_copy_from() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 376 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 377 |  |  |         out = {} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 378 |  |  |         # the original schema fields of an AR (including extended fields) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 379 |  |  |         fields = self.get_ar_fields() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 380 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 381 |  |  |         # generate fields for all requested ARs | 
            
                                                                                                            
                            
            
                                    
            
            
                | 382 |  |  |         for arnum in range(count): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 383 |  |  |             source = copy_from.get(arnum) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 384 |  |  |             parent = None | 
            
                                                                                                            
                            
            
                                    
            
            
                | 385 |  |  |             if source is not None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 386 |  |  |                 parent = self.get_parent_ar(source) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 387 |  |  |             for field in fields: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 388 |  |  |                 value = None | 
            
                                                                                                            
                            
            
                                    
            
            
                | 389 |  |  |                 fieldname = field.getName() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 390 |  |  |                 if source and fieldname not in SKIP_FIELD_ON_COPY: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 391 |  |  |                     # get the field value stored on the source | 
            
                                                                                                            
                            
            
                                    
            
            
                | 392 |  |  |                     context = parent or source | 
            
                                                                                                            
                            
            
                                    
            
            
                | 393 |  |  |                     value = self.get_field_value(field, context) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 394 |  |  |                 else: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 395 |  |  |                     # get the default value of this field | 
            
                                                                                                            
                            
            
                                    
            
            
                | 396 |  |  |                     value = self.get_default_value( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 397 |  |  |                         field, ar_context, arnum=arnum) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 398 |  |  |                 # store the value on the new fieldname | 
            
                                                                                                            
                            
            
                                    
            
            
                | 399 |  |  |                 new_fieldname = self.get_fieldname(field, arnum) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 400 |  |  |                 out[new_fieldname] = value | 
            
                                                                                                            
                            
            
                                    
            
            
                | 401 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 402 |  |  |         return out | 
            
                                                                                                            
                            
            
                                    
            
            
                | 403 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 404 |  |  |     def get_default_contact(self, client=None): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 405 |  |  |         """Logic refactored from JavaScript: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 406 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 407 |  |  |         * If client only has one contact, and the analysis request comes from | 
            
                                                                                                            
                            
            
                                    
            
            
                | 408 |  |  |         * a client, then Auto-complete first Contact field. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 409 |  |  |         * If client only has one contect, and the analysis request comes from | 
            
                                                                                                            
                            
            
                                    
            
            
                | 410 |  |  |         * a batch, then Auto-complete all Contact field. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 411 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 412 |  |  |         :returns: The default contact for the AR | 
            
                                                                                                            
                            
            
                                    
            
            
                | 413 |  |  |         :rtype: Client object or None | 
            
                                                                                                            
                            
            
                                    
            
            
                | 414 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 415 |  |  |         catalog = api.get_tool("portal_catalog") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 416 |  |  |         client = client or self.get_client() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 417 |  |  |         path = api.get_path(self.context) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 418 |  |  |         if client: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 419 |  |  |             path = api.get_path(client) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 420 |  |  |         query = { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 421 |  |  |             "portal_type": "Contact", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 422 |  |  |             "path": { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 423 |  |  |                 "query": path, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 424 |  |  |                 "depth": 1 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 425 |  |  |             }, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 426 |  |  |             "is_active": True, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 427 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 428 |  |  |         contacts = catalog(query) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 429 |  |  |         if len(contacts) == 1: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 430 |  |  |             return api.get_object(contacts[0]) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 431 |  |  |         elif client == api.get_current_client(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 432 |  |  |             # Current user is a Client contact. Use current contact | 
            
                                                                                                            
                            
            
                                    
            
            
                | 433 |  |  |             current_user = api.get_current_user() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 434 |  |  |             return api.get_user_contact(current_user, contact_types=["Contact"]) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 435 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 436 |  |  |         return None | 
            
                                                                                                            
                            
            
                                    
            
            
                | 437 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 438 |  |  |     def getMemberDiscountApplies(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 439 |  |  |         """Return if the member discount applies for this client | 
            
                                                                                                            
                            
            
                                    
            
            
                | 440 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 441 |  |  |         :returns: True if member discount applies for the client | 
            
                                                                                                            
                            
            
                                    
            
            
                | 442 |  |  |         :rtype: bool | 
            
                                                                                                            
                            
            
                                    
            
            
                | 443 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 444 |  |  |         client = self.get_client() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 445 |  |  |         if client is None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 446 |  |  |             return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 447 |  |  |         return client.getMemberDiscountApplies() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 448 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 449 |  |  |     def is_field_visible(self, field): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 450 |  |  |         """Check if the field is visible | 
            
                                                                                                            
                            
            
                                    
            
            
                | 451 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 452 |  |  |         context = self.context | 
            
                                                                                                            
                            
            
                                    
            
            
                | 453 |  |  |         fieldname = field.getName() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 454 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 455 |  |  |         # hide the Client field on client and batch contexts | 
            
                                                                                                            
                            
            
                                    
            
            
                | 456 |  |  |         if fieldname == "Client" and context.portal_type in ("Client", ): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 457 |  |  |             return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 458 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 459 |  |  |         # hide the Batch field on batch contexts | 
            
                                                                                                            
                            
            
                                    
            
            
                | 460 |  |  |         if fieldname == "Batch" and context.portal_type in ("Batch", ): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 461 |  |  |             return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 462 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 463 |  |  |         return True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 464 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 465 |  |  |     def get_fields_with_visibility(self, visibility, mode="add"): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 466 |  |  |         """Return the AR fields with the current visibility | 
            
                                                                                                            
                            
            
                                    
            
            
                | 467 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 468 |  |  |         ar = self.get_ar() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 469 |  |  |         mv = api.get_view("ar_add_manage", context=ar) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 470 |  |  |         mv.get_field_order() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 471 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 472 |  |  |         out = [] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 473 |  |  |         for field in mv.get_fields_with_visibility(visibility, mode): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 474 |  |  |             # check custom field condition | 
            
                                                                                                            
                            
            
                                    
            
            
                | 475 |  |  |             visible = self.is_field_visible(field) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 476 |  |  |             if visible is False and visibility != "hidden": | 
            
                                                                                                            
                            
            
                                    
            
            
                | 477 |  |  |                 continue | 
            
                                                                                                            
                            
            
                                    
            
            
                | 478 |  |  |             out.append(field) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 479 |  |  |         return out | 
            
                                                                                                            
                            
            
                                    
            
            
                | 480 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 481 |  |  |     def get_service_categories(self, restricted=True): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 482 |  |  |         """Return all service categories in the right order | 
            
                                                                                                            
                            
            
                                    
            
            
                | 483 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 484 |  |  |         :param restricted: Client settings restrict categories | 
            
                                                                                                            
                            
            
                                    
            
            
                | 485 |  |  |         :type restricted: bool | 
            
                                                                                                            
                            
            
                                    
            
            
                | 486 |  |  |         :returns: Category catalog results | 
            
                                                                                                            
                            
            
                                    
            
            
                | 487 |  |  |         :rtype: brains | 
            
                                                                                                            
                            
            
                                    
            
            
                | 488 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 489 |  |  |         bsc = api.get_tool("senaite_catalog_setup") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 490 |  |  |         query = { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 491 |  |  |             "portal_type": "AnalysisCategory", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 492 |  |  |             "is_active": True, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 493 |  |  |             "sort_on": "sortable_title", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 494 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 495 |  |  |         categories = bsc(query) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 496 |  |  |         client = self.get_client() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 497 |  |  |         if client and restricted: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 498 |  |  |             restricted_categories = client.getRestrictedCategories() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 499 |  |  |             restricted_category_ids = map( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 500 |  |  |                 lambda c: c.getId(), restricted_categories) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 501 |  |  |             # keep correct order of categories | 
            
                                                                                                            
                            
            
                                    
            
            
                | 502 |  |  |             if restricted_category_ids: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 503 |  |  |                 categories = filter( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 504 |  |  |                     lambda c: c.getId in restricted_category_ids, categories) | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 505 |  |  |         return categories | 
            
                                                                                                            
                            
            
                                    
            
            
                | 506 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 507 |  |  |     def get_points_of_capture(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 508 |  |  |         items = POINTS_OF_CAPTURE.items() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 509 |  |  |         return OrderedDict(items) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 510 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 511 |  |  |     def get_services(self, poc="lab"): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 512 |  |  |         """Return all Services | 
            
                                                                                                            
                            
            
                                    
            
            
                | 513 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 514 |  |  |         :param poc: Point of capture (lab/field) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 515 |  |  |         :type poc: string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 516 |  |  |         :returns: Mapping of category -> list of services | 
            
                                                                                                            
                            
            
                                    
            
            
                | 517 |  |  |         :rtype: dict | 
            
                                                                                                            
                            
            
                                    
            
            
                | 518 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 519 |  |  |         bsc = api.get_tool("senaite_catalog_setup") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 520 |  |  |         query = { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 521 |  |  |             "portal_type": "AnalysisService", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 522 |  |  |             "point_of_capture": poc, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 523 |  |  |             "is_active": True, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 524 |  |  |             "sort_on": "sortable_title", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 525 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 526 |  |  |         services = bsc(query) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 527 |  |  |         categories = self.get_service_categories(restricted=False) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 528 |  |  |         analyses = {key: [] for key in map(lambda c: c.Title, categories)} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 529 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 530 |  |  |         # append the empty category as well | 
            
                                                                                                            
                            
            
                                    
            
            
                | 531 |  |  |         analyses[""] = [] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 532 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 533 |  |  |         for brain in services: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 534 |  |  |             category = brain.getCategoryTitle | 
            
                                                                                                            
                            
            
                                    
            
            
                | 535 |  |  |             if category in analyses: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 536 |  |  |                 analyses[category].append(brain) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 537 |  |  |         return analyses | 
            
                                                                                                            
                            
            
                                    
            
            
                | 538 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 539 |  |  |     @cache(cache_key) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 540 |  |  |     def get_service_uid_from(self, analysis): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 541 |  |  |         """Return the service from the analysis | 
            
                                                                                                            
                            
            
                                    
            
            
                | 542 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 543 |  |  |         analysis = api.get_object(analysis) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 544 |  |  |         return api.get_uid(analysis.getAnalysisService()) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 545 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 546 |  |  |     def is_service_selected(self, service): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 547 |  |  |         """Checks if the given service is selected by one of the ARs. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 548 |  |  |         This is used to make the whole line visible or not. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 549 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 550 |  |  |         service_uid = api.get_uid(service) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 551 |  |  |         for arnum in range(self.ar_count): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 552 |  |  |             analyses = self.fieldvalues.get("Analyses-{}".format(arnum)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 553 |  |  |             if not analyses: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 554 |  |  |                 continue | 
            
                                                                                                            
                            
            
                                    
            
            
                | 555 |  |  |             service_uids = map(self.get_service_uid_from, analyses) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 556 |  |  |             if service_uid in service_uids: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 557 |  |  |                 return True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 558 |  |  |         return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 559 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 560 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 561 |  |  | class AnalysisRequestManageView(BrowserView): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 562 |  |  |     """AR Manage View | 
            
                                                                                                            
                            
            
                                    
            
            
                | 563 |  |  |     """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 564 |  |  |     template = ViewPageTemplateFile("templates/ar_add_manage.pt") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 565 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 566 |  |  |     def __init__(self, context, request): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 567 |  |  |         # disable CSRF protection | 
            
                                                                                                            
                            
            
                                    
            
            
                | 568 |  |  |         alsoProvides(request, IDisableCSRFProtection) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 569 |  |  |         self.context = context | 
            
                                                                                                            
                            
            
                                    
            
            
                | 570 |  |  |         self.request = request | 
            
                                                                                                            
                            
            
                                    
            
            
                | 571 |  |  |         self.tmp_ar = None | 
            
                                                                                                            
                            
            
                                    
            
            
                | 572 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 573 |  |  |     def __call__(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 574 |  |  |         protect.CheckAuthenticator(self.request.form) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 575 |  |  |         form = self.request.form | 
            
                                                                                                            
                            
            
                                    
            
            
                | 576 |  |  |         if form.get("submitted", False) and form.get("save", False): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 577 |  |  |             order = form.get("order") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 578 |  |  |             self.set_field_order(order) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 579 |  |  |             visibility = form.get("visibility") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 580 |  |  |             self.set_field_visibility(visibility) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 581 |  |  |         if form.get("submitted", False) and form.get("reset", False): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 582 |  |  |             self.flush() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 583 |  |  |         return self.template() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 584 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 585 |  |  |     def get_ar(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 586 |  |  |         if not self.tmp_ar: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 587 |  |  |             self.tmp_ar = self.context.restrictedTraverse( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 588 |  |  |                 "portal_factory/AnalysisRequest/Request new analyses") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 589 |  |  |         return self.tmp_ar | 
            
                                                                                                            
                            
            
                                    
            
            
                | 590 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 591 |  |  |     def get_annotation(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 592 |  |  |         setup = api.get_setup() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 593 |  |  |         return IAnnotations(setup) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 594 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 595 |  |  |     @property | 
            
                                                                                                            
                            
            
                                    
            
            
                | 596 |  |  |     def storage(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 597 |  |  |         annotation = self.get_annotation() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 598 |  |  |         if annotation.get(AR_CONFIGURATION_STORAGE) is None: | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 599 |  |  |             annotation[AR_CONFIGURATION_STORAGE] = OOBTree() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 600 |  |  |         return annotation[AR_CONFIGURATION_STORAGE] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 601 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 602 |  |  |     def flush(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 603 |  |  |         annotation = self.get_annotation() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 604 |  |  |         if annotation.get(AR_CONFIGURATION_STORAGE) is not None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 605 |  |  |             del annotation[AR_CONFIGURATION_STORAGE] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 606 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 607 |  |  |     def set_field_order(self, order): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 608 |  |  |         self.storage.update({"order": order}) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 609 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 610 |  |  |     def get_field_order(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 611 |  |  |         order = self.storage.get("order") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 612 |  |  |         if order is None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 613 |  |  |             return map(lambda f: f.getName(), self.get_fields()) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 614 |  |  |         return order | 
            
                                                                                                            
                            
            
                                    
            
            
                | 615 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 616 |  |  |     def set_field_visibility(self, visibility): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 617 |  |  |         self.storage.update({"visibility": visibility}) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 618 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 619 |  |  |     def get_field_visibility(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 620 |  |  |         return self.storage.get("visibility") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 621 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 622 |  |  |     def is_field_visible(self, field): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 623 |  |  |         if field.required: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 624 |  |  |             return True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 625 |  |  |         visibility = self.get_field_visibility() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 626 |  |  |         if visibility is None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 627 |  |  |             return True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 628 |  |  |         return visibility.get(field.getName(), True) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 629 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 630 |  |  |     def get_field(self, name): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 631 |  |  |         """Get AR field by name | 
            
                                                                                                            
                            
            
                                    
            
            
                | 632 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 633 |  |  |         ar = self.get_ar() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 634 |  |  |         return ar.getField(name) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 635 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 636 |  |  |     def get_fields(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 637 |  |  |         """Return all AR fields | 
            
                                                                                                            
                            
            
                                    
            
            
                | 638 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 639 |  |  |         ar = self.get_ar() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 640 |  |  |         return ar.Schema().fields() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 641 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 642 |  |  |     def get_sorted_fields(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 643 |  |  |         """Return the sorted fields | 
            
                                                                                                            
                            
            
                                    
            
            
                | 644 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 645 |  |  |         inf = float("inf") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 646 |  |  |         order = self.get_field_order() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 647 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 648 |  |  |         def field_cmp(field1, field2): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 649 |  |  |             _n1 = field1.getName() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 650 |  |  |             _n2 = field2.getName() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 651 |  |  |             _i1 = _n1 in order and order.index(_n1) + 1 or inf | 
            
                                                                                                            
                            
            
                                    
            
            
                | 652 |  |  |             _i2 = _n2 in order and order.index(_n2) + 1 or inf | 
            
                                                                                                            
                            
            
                                    
            
            
                | 653 |  |  |             return cmp(_i1, _i2) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 654 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 655 |  |  |         return sorted(self.get_fields(), cmp=field_cmp) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 656 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 657 |  |  |     def get_fields_with_visibility(self, visibility="edit", mode="add"): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 658 |  |  |         """Return the fields with visibility | 
            
                                                                                                            
                            
            
                                    
            
            
                | 659 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 660 |  |  |         fields = self.get_sorted_fields() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 661 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 662 |  |  |         out = [] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 663 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 664 |  |  |         for field in fields: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 665 |  |  |             v = field.widget.isVisible( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 666 |  |  |                 self.context, mode, default='invisible', field=field) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 667 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 668 |  |  |             if self.is_field_visible(field) is False: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 669 |  |  |                 v = "hidden" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 670 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 671 |  |  |             visibility_guard = True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 672 |  |  |             # visibility_guard is a widget field defined in the schema in order | 
            
                                                                                                            
                            
            
                                    
            
            
                | 673 |  |  |             # to know the visibility of the widget when the field is related to | 
            
                                                                                                            
                            
            
                                    
            
            
                | 674 |  |  |             # a dynamically changing content such as workflows. For instance | 
            
                                                                                                            
                            
            
                                    
            
            
                | 675 |  |  |             # those fields related to the workflow will be displayed only if | 
            
                                                                                                            
                            
            
                                    
            
            
                | 676 |  |  |             # the workflow is enabled, otherwise they should not be shown. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 677 |  |  |             if 'visibility_guard' in dir(field.widget): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 678 |  |  |                 visibility_guard = eval(field.widget.visibility_guard) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 679 |  |  |             if v == visibility and visibility_guard: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 680 |  |  |                 out.append(field) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 681 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 682 |  |  |         return out | 
            
                                                                                                            
                            
            
                                    
            
            
                | 683 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 684 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 685 |  |  | class ajaxAnalysisRequestAddView(AnalysisRequestAddView): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 686 |  |  |     """Ajax helpers for the analysis request add form | 
            
                                                                                                            
                            
            
                                    
            
            
                | 687 |  |  |     """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 688 |  |  |     implements(IPublishTraverse) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 689 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 690 |  |  |     def __init__(self, context, request): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 691 |  |  |         super(ajaxAnalysisRequestAddView, self).__init__(context, request) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 692 |  |  |         self.context = context | 
            
                                                                                                            
                            
            
                                    
            
            
                | 693 |  |  |         self.request = request | 
            
                                                                                                            
                            
            
                                    
            
            
                | 694 |  |  |         self.traverse_subpath = [] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 695 |  |  |         # Errors are aggregated here, and returned together to the browser | 
            
                                                                                                            
                            
            
                                    
            
            
                | 696 |  |  |         self.errors = {} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 697 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 698 |  |  |     def publishTraverse(self, request, name): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 699 |  |  |         """ get's called before __call__ for each path name | 
            
                                                                                                            
                            
            
                                    
            
            
                | 700 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 701 |  |  |         self.traverse_subpath.append(name) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 702 |  |  |         return self | 
            
                                                                                                            
                            
            
                                    
            
            
                | 703 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 704 |  |  |     @returns_json | 
            
                                                                                                            
                            
            
                                    
            
            
                | 705 |  |  |     def __call__(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 706 |  |  |         """Dispatch the path to a method and return JSON. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 707 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 708 |  |  |         protect.CheckAuthenticator(self.request.form) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 709 |  |  |         protect.PostOnly(self.request.form) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 710 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 711 |  |  |         if len(self.traverse_subpath) != 1: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 712 |  |  |             return self.error("Not found", status=404) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 713 |  |  |         func_name = "ajax_{}".format(self.traverse_subpath[0]) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 714 |  |  |         func = getattr(self, func_name, None) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 715 |  |  |         if func is None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 716 |  |  |             return self.error("Invalid function", status=400) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 717 |  |  |         return func() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 718 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 719 |  |  |     def error(self, message, status=500, **kw): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 720 |  |  |         """Set a JSON error object and a status to the response | 
            
                                                                                                            
                            
            
                                    
            
            
                | 721 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 722 |  |  |         self.request.response.setStatus(status) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 723 |  |  |         result = {"success": False, "errors": message} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 724 |  |  |         result.update(kw) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 725 |  |  |         return result | 
            
                                                                                                            
                            
            
                                    
            
            
                | 726 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 727 |  |  |     def to_iso_date(self, dt): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 728 |  |  |         """Return the ISO representation of a date object | 
            
                                                                                                            
                            
            
                                    
            
            
                | 729 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 730 |  |  |         if dt is None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 731 |  |  |             return "" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 732 |  |  |         if isinstance(dt, DateTime): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 733 |  |  |             return dt.ISO8601() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 734 |  |  |         if isinstance(dt, datetime): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 735 |  |  |             return dt.isoformat() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 736 |  |  |         raise TypeError("{} is neiter an instance of DateTime nor datetime" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 737 |  |  |                         .format(repr(dt))) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 738 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 739 |  |  |     def get_records(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 740 |  |  |         """Returns a list of AR records | 
            
                                                                                                            
                            
            
                                    
            
            
                | 741 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 742 |  |  |         Fields coming from `request.form` have a number prefix, e.g. Contact-0. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 743 |  |  |         Fields with the same suffix number are grouped together in a record. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 744 |  |  |         Each record represents the data for one column in the AR Add form and | 
            
                                                                                                            
                            
            
                                    
            
            
                | 745 |  |  |         contains a mapping of the fieldName (w/o prefix) -> value. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 746 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 747 |  |  |         Example: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 748 |  |  |         [{"Contact": "Rita Mohale", ...}, {Contact: "Neil Standard"} ...] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 749 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 750 |  |  |         form = self.request.form | 
            
                                                                                                            
                            
            
                                    
            
            
                | 751 |  |  |         ar_count = self.get_ar_count() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 752 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 753 |  |  |         records = [] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 754 |  |  |         # Group belonging AR fields together | 
            
                                                                                                            
                            
            
                                    
            
            
                | 755 |  |  |         for arnum in range(ar_count): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 756 |  |  |             record = {} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 757 |  |  |             s1 = "-{}".format(arnum) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 758 |  |  |             keys = filter(lambda key: s1 in key, form.keys()) | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 759 |  |  |             for key in keys: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 760 |  |  |                 new_key = key.replace(s1, "") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 761 |  |  |                 value = form.get(key) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 762 |  |  |                 record[new_key] = value | 
            
                                                                                                            
                            
            
                                    
            
            
                | 763 |  |  |             records.append(record) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 764 |  |  |         return records | 
            
                                                                                                            
                            
            
                                    
            
            
                | 765 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 766 |  |  |     def get_uids_from_record(self, record, key): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 767 |  |  |         """Returns a list of parsed UIDs from a single form field identified by | 
            
                                                                                                            
                            
            
                                    
            
            
                | 768 |  |  |         the given key. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 769 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 770 |  |  |         A form field ending with `_uid` can contain an empty value, a | 
            
                                                                                                            
                            
            
                                    
            
            
                | 771 |  |  |         single UID or multiple UIDs separated by a comma. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 772 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 773 |  |  |         This method parses the UID value and returns a list of non-empty UIDs. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 774 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 775 |  |  |         value = record.get(key, None) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 776 |  |  |         if value is None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 777 |  |  |             return [] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 778 |  |  |         if isinstance(value, six.string_types): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 779 |  |  |             value = value.split(",") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 780 |  |  |         return filter(lambda uid: uid, value) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 781 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 782 |  |  |     @cache(cache_key) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 783 |  |  |     def get_base_info(self, obj): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 784 |  |  |         """Returns the base info of an object | 
            
                                                                                                            
                            
            
                                    
            
            
                | 785 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 786 |  |  |         if obj is None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 787 |  |  |             return {} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 788 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 789 |  |  |         info = { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 790 |  |  |             "id": api.get_id(obj), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 791 |  |  |             "uid": api.get_uid(obj), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 792 |  |  |             "title": api.get_title(obj), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 793 |  |  |             "field_values": {}, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 794 |  |  |             "filter_queries": {}, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 795 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 796 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 797 |  |  |         return info | 
            
                                                                                                            
                            
            
                                    
            
            
                | 798 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 799 |  |  |     @cache(cache_key) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 800 |  |  |     def get_client_info(self, obj): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 801 |  |  |         """Returns the client info of an object | 
            
                                                                                                            
                            
            
                                    
            
            
                | 802 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 803 |  |  |         info = self.get_base_info(obj) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 804 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 805 |  |  |         # Set the default contact, but only if empty. The Contact field is | 
            
                                                                                                            
                            
            
                                    
            
            
                | 806 |  |  |         # flushed each time the Client changes, so we can assume that if there | 
            
                                                                                                            
                            
            
                                    
            
            
                | 807 |  |  |         # is a selected contact, it belongs to current client already | 
            
                                                                                                            
                            
            
                                    
            
            
                | 808 |  |  |         default_contact = self.get_default_contact(client=obj) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 809 |  |  |         if default_contact: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 810 |  |  |             contact_info = self.get_contact_info(default_contact) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 811 |  |  |             contact_info.update({"if_empty": True}) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 812 |  |  |             info["field_values"].update({ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 813 |  |  |                 "Contact": contact_info | 
            
                                                                                                            
                            
            
                                    
            
            
                | 814 |  |  |             }) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 815 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 816 |  |  |         # Set default CC Email field | 
            
                                                                                                            
                            
            
                                    
            
            
                | 817 |  |  |         info["field_values"].update({ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 818 |  |  |             "CCEmails": {"value": obj.getCCEmails(), "if_empty": True} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 819 |  |  |         }) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 820 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 821 |  |  |         # UID of the client | 
            
                                                                                                            
                            
            
                                    
            
            
                | 822 |  |  |         uid = api.get_uid(obj) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 823 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 824 |  |  |         # catalog queries for UI field filtering | 
            
                                                                                                            
                            
            
                                    
            
            
                | 825 |  |  |         filter_queries = { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 826 |  |  |             "Contact": { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 827 |  |  |                 "getParentUID": [uid] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 828 |  |  |             }, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 829 |  |  |             "CCContact": { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 830 |  |  |                 "getParentUID": [uid] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 831 |  |  |             }, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 832 |  |  |             "InvoiceContact": { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 833 |  |  |                 "getParentUID": [uid] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 834 |  |  |             }, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 835 |  |  |             "SamplePoint": { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 836 |  |  |                 "getClientUID": [uid, ""], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 837 |  |  |             }, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 838 |  |  |             "Template": { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 839 |  |  |                 "getClientUID": [uid, ""], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 840 |  |  |             }, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 841 |  |  |             "Profiles": { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 842 |  |  |                 "getClientUID": [uid, ""], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 843 |  |  |             }, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 844 |  |  |             "Specification": { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 845 |  |  |                 "getClientUID": [uid, ""], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 846 |  |  |             }, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 847 |  |  |             "Sample": { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 848 |  |  |                 "getClientUID": [uid], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 849 |  |  |             }, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 850 |  |  |             "Batch": { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 851 |  |  |                 "getClientUID": [uid, ""], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 852 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 853 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 854 |  |  |         info["filter_queries"] = filter_queries | 
            
                                                                                                            
                            
            
                                    
            
            
                | 855 |  |  |         return info | 
            
                                                                                                            
                            
            
                                    
            
            
                | 856 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 857 |  |  |     @cache(cache_key) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 858 |  |  |     def get_contact_info(self, obj): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 859 |  |  |         """Returns the client info of an object | 
            
                                                                                                            
                            
            
                                    
            
            
                | 860 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 861 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 862 |  |  |         info = self.get_base_info(obj) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 863 |  |  |         fullname = obj.getFullname() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 864 |  |  |         email = obj.getEmailAddress() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 865 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 866 |  |  |         # Note: It might get a circular dependency when calling: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 867 |  |  |         #       map(self.get_contact_info, obj.getCCContact()) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 868 |  |  |         cccontacts = [] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 869 |  |  |         for contact in obj.getCCContact(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 870 |  |  |             uid = api.get_uid(contact) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 871 |  |  |             fullname = contact.getFullname() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 872 |  |  |             email = contact.getEmailAddress() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 873 |  |  |             cccontacts.append({ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 874 |  |  |                 "uid": uid, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 875 |  |  |                 "title": fullname, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 876 |  |  |                 "fullname": fullname, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 877 |  |  |                 "email": email | 
            
                                                                                                            
                            
            
                                    
            
            
                | 878 |  |  |             }) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 879 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 880 |  |  |         info.update({ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 881 |  |  |             "fullname": fullname, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 882 |  |  |             "email": email, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 883 |  |  |             "field_values": { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 884 |  |  |                 "CCContact": cccontacts | 
            
                                                                                                            
                            
            
                                    
            
            
                | 885 |  |  |             }, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 886 |  |  |         }) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 887 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 888 |  |  |         return info | 
            
                                                                                                            
                            
            
                                    
            
            
                | 889 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 890 |  |  |     @cache(cache_key) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 891 |  |  |     def get_service_info(self, obj): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 892 |  |  |         """Returns the info for a Service | 
            
                                                                                                            
                            
            
                                    
            
            
                | 893 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 894 |  |  |         info = self.get_base_info(obj) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 895 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 896 |  |  |         info.update({ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 897 |  |  |             "short_title": obj.getShortTitle(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 898 |  |  |             "scientific_name": obj.getScientificName(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 899 |  |  |             "unit": obj.getUnit(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 900 |  |  |             "keyword": obj.getKeyword(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 901 |  |  |             "methods": map(self.get_method_info, obj.getMethods()), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 902 |  |  |             "calculation": self.get_calculation_info(obj.getCalculation()), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 903 |  |  |             "price": obj.getPrice(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 904 |  |  |             "currency_symbol": self.get_currency().symbol, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 905 |  |  |             "accredited": obj.getAccredited(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 906 |  |  |             "category": obj.getCategoryTitle(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 907 |  |  |             "poc": obj.getPointOfCapture(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 908 |  |  |             "conditions": self.get_conditions_info(obj), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 909 |  |  |         }) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 910 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 911 |  |  |         dependencies = get_calculation_dependencies_for(obj).values() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 912 |  |  |         info["dependencies"] = map(self.get_base_info, dependencies) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 913 |  |  |         return info | 
            
                                                                                                            
                            
            
                                    
            
            
                | 914 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 915 |  |  |     @cache(cache_key) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 916 |  |  |     def get_template_info(self, obj): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 917 |  |  |         """Returns the info for a Template | 
            
                                                                                                            
                            
            
                                    
            
            
                | 918 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 919 |  |  |         client = self.get_client() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 920 |  |  |         client_uid = api.get_uid(client) if client else "" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 921 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 922 |  |  |         profile = obj.getAnalysisProfile() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 923 |  |  |         profile_uid = api.get_uid(profile) if profile else "" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 924 |  |  |         profile_title = profile.Title() if profile else "" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 925 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 926 |  |  |         sample_type = obj.getSampleType() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 927 |  |  |         sample_type_uid = api.get_uid(sample_type) if sample_type else "" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 928 |  |  |         sample_type_title = sample_type.Title() if sample_type else "" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 929 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 930 |  |  |         sample_point = obj.getSamplePoint() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 931 |  |  |         sample_point_uid = api.get_uid(sample_point) if sample_point else "" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 932 |  |  |         sample_point_title = sample_point.Title() if sample_point else "" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 933 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 934 |  |  |         service_uids = [] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 935 |  |  |         analyses_partitions = {} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 936 |  |  |         analyses = obj.getAnalyses() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 937 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 938 |  |  |         for record in analyses: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 939 |  |  |             service_uid = record.get("service_uid") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 940 |  |  |             service_uids.append(service_uid) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 941 |  |  |             analyses_partitions[service_uid] = record.get("partition") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 942 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 943 |  |  |         info = self.get_base_info(obj) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 944 |  |  |         info.update({ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 945 |  |  |             "analyses_partitions": analyses_partitions, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 946 |  |  |             "analysis_profile_title": profile_title, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 947 |  |  |             "analysis_profile_uid": profile_uid, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 948 |  |  |             "client_uid": client_uid, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 949 |  |  |             "composite": obj.getComposite(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 950 |  |  |             "partitions": obj.getPartitions(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 951 |  |  |             "remarks": obj.getRemarks(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 952 |  |  |             "sample_point_title": sample_point_title, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 953 |  |  |             "sample_point_uid": sample_point_uid, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 954 |  |  |             "sample_type_title": sample_type_title, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 955 |  |  |             "sample_type_uid": sample_type_uid, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 956 |  |  |             "service_uids": service_uids, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 957 |  |  |         }) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 958 |  |  |         return info | 
            
                                                                                                            
                            
            
                                    
            
            
                | 959 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 960 |  |  |     @cache(cache_key) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 961 |  |  |     def get_profile_info(self, obj): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 962 |  |  |         """Returns the info for a Profile | 
            
                                                                                                            
                            
            
                                    
            
            
                | 963 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 964 |  |  |         info = self.get_base_info(obj) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 965 |  |  |         info.update({}) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 966 |  |  |         return info | 
            
                                                                                                            
                            
            
                                    
            
            
                | 967 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 968 |  |  |     @cache(cache_key) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 969 |  |  |     def get_method_info(self, obj): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 970 |  |  |         """Returns the info for a Method | 
            
                                                                                                            
                            
            
                                    
            
            
                | 971 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 972 |  |  |         info = self.get_base_info(obj) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 973 |  |  |         info.update({}) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 974 |  |  |         return info | 
            
                                                                                                            
                            
            
                                    
            
            
                | 975 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 976 |  |  |     @cache(cache_key) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 977 |  |  |     def get_calculation_info(self, obj): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 978 |  |  |         """Returns the info for a Calculation | 
            
                                                                                                            
                            
            
                                    
            
            
                | 979 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 980 |  |  |         info = self.get_base_info(obj) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 981 |  |  |         info.update({}) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 982 |  |  |         return info | 
            
                                                                                                            
                            
            
                                    
            
            
                | 983 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 984 |  |  |     @cache(cache_key) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 985 |  |  |     def get_sampletype_info(self, obj): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 986 |  |  |         """Returns the info for a Sample Type | 
            
                                                                                                            
                            
            
                                    
            
            
                | 987 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 988 |  |  |         info = self.get_base_info(obj) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 989 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 990 |  |  |         # client | 
            
                                                                                                            
                            
            
                                    
            
            
                | 991 |  |  |         client = self.get_client() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 992 |  |  |         client_uid = client and api.get_uid(client) or "" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 993 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 994 |  |  |         info.update({ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 995 |  |  |             "prefix": obj.getPrefix(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 996 |  |  |             "minimum_volume": obj.getMinimumVolume(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 997 |  |  |             "hazardous": obj.getHazardous(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 998 |  |  |             "retention_period": obj.getRetentionPeriod(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 999 |  |  |         }) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1000 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1001 |  |  |         # catalog queries for UI field filtering | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1002 |  |  |         sample_type_uid = api.get_uid(obj) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1003 |  |  |         filter_queries = { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1004 |  |  |             # Display Sample Points that have this sample type assigned plus | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1005 |  |  |             # those that do not have a sample type assigned | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1006 |  |  |             "SamplePoint": { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1007 |  |  |                 "sampletype_uid": [sample_type_uid, None], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1008 |  |  |                 "getClientUID": [client_uid, ""], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1009 |  |  |             }, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1010 |  |  |             # Display Specifications that have this sample type assigned only | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1011 |  |  |             "Specification": { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1012 |  |  |                 "sampletype_uid": sample_type_uid, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1013 |  |  |                 "getClientUID": [client_uid, ""], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1014 |  |  |             }, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1015 |  |  |             # Display AR Templates that have this sample type assigned plus | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1016 |  |  |             # those that do not have a sample type assigned | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1017 |  |  |             "Template": { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1018 |  |  |                 "sampletype_uid": [sample_type_uid, None], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1019 |  |  |                 "getClientUID": [client_uid, ""], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1020 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1021 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1022 |  |  |         info["filter_queries"] = filter_queries | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1023 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1024 |  |  |         return info | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1025 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1026 |  |  |     @cache(cache_key) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1027 |  |  |     def get_primaryanalysisrequest_info(self, obj): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1028 |  |  |         """Returns the info for a Primary Sample | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1029 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1030 |  |  |         info = self.get_base_info(obj) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1031 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1032 |  |  |         batch = obj.getBatch() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1033 |  |  |         client = obj.getClient() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1034 |  |  |         sample_type = obj.getSampleType() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1035 |  |  |         sample_condition = obj.getSampleCondition() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1036 |  |  |         storage_location = obj.getStorageLocation() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1037 |  |  |         sample_point = obj.getSamplePoint() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1038 |  |  |         container = obj.getContainer() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1039 |  |  |         deviation = obj.getSamplingDeviation() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1040 |  |  |         cccontacts = obj.getCCContact() or [] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1041 |  |  |         contact = obj.getContact() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1042 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1043 |  |  |         info.update({ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1044 |  |  |             "composite": obj.getComposite(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1045 |  |  |         }) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1046 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1047 |  |  |         # Set the fields for which we want the value to be set automatically | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1048 |  |  |         # when the primary sample is selected | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1049 |  |  |         info["field_values"].update({ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1050 |  |  |             "Client": self.to_field_value(client), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1051 |  |  |             "Contact": self.to_field_value(contact), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1052 |  |  |             "CCContact": map(self.to_field_value, cccontacts), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1053 |  |  |             "CCEmails": obj.getCCEmails(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1054 |  |  |             "Batch": self.to_field_value(batch), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1055 |  |  |             "DateSampled": {"value": self.to_iso_date(obj.getDateSampled())}, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1056 |  |  |             "SamplingDate": {"value": self.to_iso_date(obj.getSamplingDate())}, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1057 |  |  |             "SampleType": self.to_field_value(sample_type), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1058 |  |  |             "EnvironmentalConditions": {"value": obj.getEnvironmentalConditions()}, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1059 |  |  |             "ClientSampleID": {"value": obj.getClientSampleID()}, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1060 |  |  |             "ClientReference": {"value": obj.getClientReference()}, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1061 |  |  |             "ClientOrderNumber": {"value": obj.getClientOrderNumber()}, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1062 |  |  |             "SampleCondition": self.to_field_value(sample_condition), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1063 |  |  |             "SamplePoint": self.to_field_value(sample_point), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1064 |  |  |             "StorageLocation": self.to_field_value(storage_location), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1065 |  |  |             "Container": self.to_field_value(container), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1066 |  |  |             "SamplingDeviation": self.to_field_value(deviation), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1067 |  |  |             "Composite": {"value": obj.getComposite()} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1068 |  |  |         }) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1069 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1070 |  |  |         return info | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1071 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1072 |  |  |     @cache(cache_key) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1073 |  |  |     def get_conditions_info(self, obj): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1074 |  |  |         conditions = obj.getConditions() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1075 |  |  |         for condition in conditions: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1076 |  |  |             choices = condition.get("choices", "") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1077 |  |  |             options = filter(None, choices.split('|')) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1078 |  |  |             if options: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1079 |  |  |                 condition.update({"options": options}) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1080 |  |  |         return conditions | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1081 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1082 |  |  |     @cache(cache_key) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1083 |  |  |     def to_field_value(self, obj): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1084 |  |  |         return { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1085 |  |  |             "uid": obj and api.get_uid(obj) or "", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1086 |  |  |             "title": obj and api.get_title(obj) or "" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1087 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1088 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1089 |  |  |     def ajax_get_global_settings(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1090 |  |  |         """Returns the global Bika settings | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1091 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1092 |  |  |         setup = api.get_setup() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1093 |  |  |         settings = { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1094 |  |  |             "show_prices": setup.getShowPrices(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1095 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1096 |  |  |         return settings | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1097 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1098 |  |  |     def ajax_get_flush_settings(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1099 |  |  |         """Returns the settings for fields flush | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1100 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1101 |  |  |         flush_settings = { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1102 |  |  |             "Client": [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1103 |  |  |                 "Contact", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1104 |  |  |                 "CCContact", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1105 |  |  |                 "InvoiceContact", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1106 |  |  |                 "SamplePoint", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1107 |  |  |                 "Template", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1108 |  |  |                 "Profiles", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1109 |  |  |                 "PrimaryAnalysisRequest", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1110 |  |  |                 "Specification", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1111 |  |  |                 "Batch" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1112 |  |  |             ], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1113 |  |  |             "Contact": [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1114 |  |  |                 "CCContact" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1115 |  |  |             ], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1116 |  |  |             "SampleType": [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1117 |  |  |                 "SamplePoint", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1118 |  |  |                 "Specification", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1119 |  |  |                 "Template", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1120 |  |  |             ], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1121 |  |  |             "PrimarySample": [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1122 |  |  |                 "Batch" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1123 |  |  |                 "Client", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1124 |  |  |                 "Contact", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1125 |  |  |                 "CCContact", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1126 |  |  |                 "CCEmails", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1127 |  |  |                 "ClientOrderNumber", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1128 |  |  |                 "ClientReference", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1129 |  |  |                 "ClientSampleID", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1130 |  |  |                 "ContainerType", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1131 |  |  |                 "DateSampled", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1132 |  |  |                 "EnvironmentalConditions", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1133 |  |  |                 "InvoiceContact", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1134 |  |  |                 "Preservation", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1135 |  |  |                 "Profiles", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1136 |  |  |                 "SampleCondition", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1137 |  |  |                 "SamplePoint", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1138 |  |  |                 "SampleType", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1139 |  |  |                 "SamplingDate", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1140 |  |  |                 "SamplingDeviation", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1141 |  |  |                 "StorageLocation", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1142 |  |  |                 "Specification", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1143 |  |  |                 "Template", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1144 |  |  |             ] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1145 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1146 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1147 |  |  |         # Maybe other add-ons have additional fields that require flushing | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1148 |  |  |         for name, ad in getAdapters((self.context,), IAddSampleFieldsFlush): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1149 |  |  |             logger.info("Additional flush settings from {}".format(name)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1150 |  |  |             additional_settings = ad.get_flush_settings() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1151 |  |  |             for key, values in additional_settings.items(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1152 |  |  |                 new_values = flush_settings.get(key, []) + values | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1153 |  |  |                 flush_settings[key] = list(set(new_values)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1154 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1155 |  |  |         return flush_settings | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1156 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1157 |  |  |     def ajax_get_service(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1158 |  |  |         """Returns the services information | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1159 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1160 |  |  |         uid = self.request.form.get("uid", None) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1161 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1162 |  |  |         if uid is None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1163 |  |  |             return self.error("Invalid UID", status=400) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1164 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1165 |  |  |         service = self.get_object_by_uid(uid) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1166 |  |  |         if not service: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1167 |  |  |             return self.error("Service not found", status=404) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1168 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1169 |  |  |         info = self.get_service_info(service) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1170 |  |  |         return info | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1171 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1172 |  |  |     def ajax_recalculate_records(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1173 |  |  |         out = {} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1174 |  |  |         records = self.get_records() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1175 |  |  |         for num_sample, record in enumerate(records): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1176 |  |  |             # Get reference fields metadata | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1177 |  |  |             metadata = self.get_record_metadata(record) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1178 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1179 |  |  |             # service_to_templates, template_to_services | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1180 |  |  |             templates_additional = self.get_template_additional_info(metadata) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1181 |  |  |             metadata.update(templates_additional) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1182 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1183 |  |  |             # service_to_profiles, profiles_to_services | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1184 |  |  |             profiles_additional = self.get_profiles_additional_info(metadata) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1185 |  |  |             metadata.update(profiles_additional) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1186 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1187 |  |  |             # dependencies | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1188 |  |  |             dependencies = self.get_unmet_dependencies_info(metadata) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1189 |  |  |             metadata.update(dependencies) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1190 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1191 |  |  |             # Set the metadata for current sample number (column) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1192 |  |  |             out[num_sample] = metadata | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1193 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1194 |  |  |         return out | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1195 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1196 |  |  |     def get_record_metadata(self, record): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1197 |  |  |         """Returns the metadata for the record passed in | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1198 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1199 |  |  |         metadata = {} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1200 |  |  |         extra_fields = {} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1201 |  |  |         for key, value in record.items(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1202 |  |  |             if not key.endswith("_uid"): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1203 |  |  |                 continue | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1204 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1205 |  |  |             # This is a reference field (ends with _uid), so we add the | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1206 |  |  |             # metadata key, even if there is no way to handle objects this | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1207 |  |  |             # field refers to | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1208 |  |  |             metadata_key = key.replace("_uid", "") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1209 |  |  |             metadata_key = "{}_metadata".format(metadata_key.lower()) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1210 |  |  |             metadata[metadata_key] = {} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1211 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1212 |  |  |             if not value: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1213 |  |  |                 continue | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1214 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1215 |  |  |             # Get objects information (metadata) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1216 |  |  |             objs_info = self.get_objects_info(record, key) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1217 |  |  |             objs_uids = map(lambda obj: obj["uid"], objs_info) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1218 |  |  |             metadata[metadata_key] = dict(zip(objs_uids, objs_info)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1219 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1220 |  |  |             # Grab 'field_values' fields to be recalculated too | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1221 |  |  |             for obj_info in objs_info: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1222 |  |  |                 field_values = obj_info.get("field_values", {}) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1223 |  |  |                 for field_name, field_value in field_values.items(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1224 |  |  |                     if not isinstance(field_value, dict): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1225 |  |  |                         # this is probably a list, e.g. "Profiles" field | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1226 |  |  |                         continue | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1227 |  |  |                     uids = self.get_uids_from_record(field_value, "uid") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1228 |  |  |                     if len(uids) == 1: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1229 |  |  |                         extra_fields[field_name] = uids[0] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1230 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1231 |  |  |         # Populate metadata with object info from extra fields (hidden fields) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1232 |  |  |         for field_name, uid in extra_fields.items(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1233 |  |  |             key = "{}_metadata".format(field_name.lower()) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1234 |  |  |             if metadata.get(key): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1235 |  |  |                 # This object has been processed already, skip | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1236 |  |  |                 continue | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1237 |  |  |             obj = self.get_object_by_uid(uid) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1238 |  |  |             if not obj: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1239 |  |  |                 continue | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1240 |  |  |             obj_info = self.get_object_info(obj, field_name, record=extra_fields) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1241 |  |  |             if not obj_info or "uid" not in obj_info: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1242 |  |  |                 continue | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1243 |  |  |             metadata[key] = {obj_info["uid"]: obj_info} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1244 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1245 |  |  |         return metadata | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1246 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1247 |  |  |     def get_template_additional_info(self, metadata): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1248 |  |  |         template_to_services = {} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1249 |  |  |         service_to_templates = {} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1250 |  |  |         service_metadata = metadata.get("service_metadata", {}) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1251 |  |  |         profiles_metadata = metadata.get("profiles_metadata", {}) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1252 |  |  |         template = metadata.get("template_metadata", {}) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1253 |  |  |         # We don't expect more than one template, but who knows about future? | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1254 |  |  |         for uid, obj_info in template.items(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1255 |  |  |             obj = self.get_object_by_uid(uid) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1256 |  |  |             # profile from the template | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1257 |  |  |             profile = obj.getAnalysisProfile() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1258 |  |  |             # add the profile to the other profiles | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1259 |  |  |             if profile is not None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1260 |  |  |                 profile_uid = api.get_uid(profile) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1261 |  |  |                 if profile_uid not in profiles_metadata: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1262 |  |  |                     profile = self.get_object_by_uid(profile_uid) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1263 |  |  |                     profile_info = self.get_profile_info(profile) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1264 |  |  |                     profiles_metadata[profile_uid] = profile_info | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1265 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1266 |  |  |             # get the template analyses | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1267 |  |  |             # [{'partition': 'part-1', 'service_uid': '...'}, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1268 |  |  |             # {'partition': 'part-1', 'service_uid': '...'}] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1269 |  |  |             analyses = obj.getAnalyses() or [] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1270 |  |  |             # get all UIDs of the template records | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1271 |  |  |             service_uids = map(lambda rec: rec.get("service_uid"), analyses) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1272 |  |  |             # remember a mapping of template uid -> service | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1273 |  |  |             template_to_services[uid] = service_uids | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1274 |  |  |             # remember a mapping of service uid -> templates | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1275 |  |  |             for service_uid in service_uids: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1276 |  |  |                 # remember the template of all services | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1277 |  |  |                 if service_uid in service_to_templates: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1278 |  |  |                     service_to_templates[service_uid].append(uid) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1279 |  |  |                 else: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1280 |  |  |                     service_to_templates[service_uid] = [uid] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1281 |  |  |                 # remember the service metadata | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1282 |  |  |                 if service_uid not in service_metadata: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1283 |  |  |                     service = self.get_object_by_uid(service_uid) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1284 |  |  |                     service_info = self.get_service_info(service) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1285 |  |  |                     service_metadata[service_uid] = service_info | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1286 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1287 |  |  |         return { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1288 |  |  |             "service_to_templates": service_to_templates, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1289 |  |  |             "template_to_services": template_to_services, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1290 |  |  |             "service_metadata": service_metadata, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1291 |  |  |             "profiles_metadata": profiles_metadata, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1292 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1293 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1294 |  |  |     def get_profiles_additional_info(self, metadata): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1295 |  |  |         profile_to_services = {} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1296 |  |  |         service_to_profiles = metadata.get("service_to_profiles", {}) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1297 |  |  |         service_metadata = metadata.get("service_metadata", {}) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1298 |  |  |         profiles = metadata.get("profiles_metadata", {}) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1299 |  |  |         for uid, obj_info in profiles.items(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1300 |  |  |             obj = self.get_object_by_uid(uid) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1301 |  |  |             # get all services of this profile | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1302 |  |  |             services = obj.getService() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1303 |  |  |             # get all UIDs of the profile services | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1304 |  |  |             service_uids = map(api.get_uid, services) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1305 |  |  |             # remember all services of this profile | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1306 |  |  |             profile_to_services[uid] = service_uids | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1307 |  |  |             # remember a mapping of service uid -> profiles | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1308 |  |  |             for service in services: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1309 |  |  |                 # get the UID of this service | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1310 |  |  |                 service_uid = api.get_uid(service) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1311 |  |  |                 # remember the profiles of this service | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1312 |  |  |                 if service_uid in service_to_profiles: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1313 |  |  |                     service_to_profiles[service_uid].append(uid) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1314 |  |  |                 else: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1315 |  |  |                     service_to_profiles[service_uid] = [uid] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1316 |  |  |                 # remember the service metadata | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1317 |  |  |                 if service_uid not in service_metadata: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1318 |  |  |                     service_info = self.get_service_info(service) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1319 |  |  |                     service_metadata[service_uid] = service_info | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1320 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1321 |  |  |         return { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1322 |  |  |             "profile_to_services": profile_to_services, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1323 |  |  |             "service_to_profiles": service_to_profiles, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1324 |  |  |             "service_metadata": service_metadata, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1325 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1326 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1327 |  |  |     def get_unmet_dependencies_info(self, metadata): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1328 |  |  |         # mapping of service UID -> unmet service dependency UIDs | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1329 |  |  |         unmet_dependencies = {} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1330 |  |  |         services = metadata.get("service_metadata", {}).copy() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1331 |  |  |         for uid, obj_info in services.items(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1332 |  |  |             obj = self.get_object_by_uid(uid) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1333 |  |  |             # get the dependencies of this service | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1334 |  |  |             deps = get_service_dependencies_for(obj) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1335 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1336 |  |  |             # check for unmet dependencies | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1337 |  |  |             for dep in deps["dependencies"]: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1338 |  |  |                 # we use the UID to test for equality | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1339 |  |  |                 dep_uid = api.get_uid(dep) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1340 |  |  |                 if dep_uid not in services: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1341 |  |  |                     if uid in unmet_dependencies: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1342 |  |  |                         unmet_dependencies[uid].append(self.get_base_info(dep)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1343 |  |  |                     else: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1344 |  |  |                         unmet_dependencies[uid] = [self.get_base_info(dep)] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1345 |  |  |             # remember the dependencies in the service metadata | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1346 |  |  |             metadata["service_metadata"][uid].update({ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1347 |  |  |                 "dependencies": map( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1348 |  |  |                     self.get_base_info, deps["dependencies"]), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1349 |  |  |             }) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1350 |  |  |         return { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1351 |  |  |             "unmet_dependencies": unmet_dependencies | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1352 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1353 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1354 |  |  |     def get_objects_info(self, record, key): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1355 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1356 |  |  |         Returns a list with the metadata for the objects the field with | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1357 |  |  |         field_name passed in refers to. Returns empty list if the field is not | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1358 |  |  |         a reference field or the record for this key cannot be handled | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1359 |  |  |         :param record: a record for a single sample (column) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1360 |  |  |         :param key: The key of the field from the record (e.g. Client_uid) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1361 |  |  |         :return: list of info objects | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1362 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1363 |  |  |         # Get the objects from this record. Returns a list because the field | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1364 |  |  |         # can be multivalued | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1365 |  |  |         uids = self.get_uids_from_record(record, key) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1366 |  |  |         objects = map(self.get_object_by_uid, uids) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1367 |  |  |         objects = map(lambda obj: self.get_object_info( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1368 |  |  |             obj, key, record=record), objects) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1369 |  |  |         return filter(None, objects) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1370 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1371 |  |  |     def object_info_cache_key(method, self, obj, key, **kw): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1372 |  |  |         if obj is None or not key: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1373 |  |  |             raise DontCache | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1374 |  |  |         field_name = key.replace("_uid", "").lower() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1375 |  |  |         obj_key = api.get_cache_key(obj) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1376 |  |  |         return "-".join([field_name, obj_key] + kw.keys()) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1377 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1378 |  |  |     @cache(object_info_cache_key) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1379 |  |  |     def get_object_info(self, obj, key, record=None): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1380 |  |  |         """Returns the object info metadata for the passed in object and key | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1381 |  |  |         :param obj: the object from which extract the info from | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1382 |  |  |         :param key: The key of the field from the record (e.g. Client_uid) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1383 |  |  |         :return: dict that represents the object | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1384 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1385 |  |  |         # Check if there is a function to handle objects for this field | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1386 |  |  |         field_name = key.replace("_uid", "") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1387 |  |  |         func_name = "get_{}_info".format(field_name.lower()) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1388 |  |  |         func = getattr(self, func_name, None) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1389 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1390 |  |  |         # always ensure we have a record | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1391 |  |  |         if record is None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1392 |  |  |             record = {} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1393 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1394 |  |  |         # Get the info for each object | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1395 |  |  |         info = callable(func) and func(obj) or self.get_base_info(obj) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1396 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1397 |  |  |         # Check if there is any adapter to handle objects for this field | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1398 |  |  |         for name, adapter in getAdapters((obj, ), IAddSampleObjectInfo): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1399 |  |  |             logger.info("adapter for '{}': {}".format(field_name, name)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1400 |  |  |             ad_info = adapter.get_object_info_with_record(record) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1401 |  |  |             self.update_object_info(info, ad_info) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1402 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1403 |  |  |         return info | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1404 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1405 |  |  |     def update_object_info(self, base_info, additional_info): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1406 |  |  |         """Updates the dictionaries for keys 'field_values' and 'filter_queries' | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1407 |  |  |         from base_info with those defined in additional_info. If base_info is | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1408 |  |  |         empty or None, updates the whole base_info dict with additional_info | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1409 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1410 |  |  |         if not base_info: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1411 |  |  |             base_info.update(additional_info) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1412 |  |  |             return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1413 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1414 |  |  |         # Merge field_values info | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1415 |  |  |         field_values = base_info.get("field_values", {}) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1416 |  |  |         field_values.update(additional_info.get("field_values", {})) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1417 |  |  |         base_info["field_values"] = field_values | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1418 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1419 |  |  |         # Merge filter_queries info | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1420 |  |  |         filter_queries = base_info.get("filter_queries", {}) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1421 |  |  |         filter_queries.update(additional_info.get("filter_queries", {})) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1422 |  |  |         base_info["filter_queries"] = filter_queries | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1423 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1424 |  |  |     def show_recalculate_prices(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1425 |  |  |         setup = api.get_setup() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1426 |  |  |         return setup.getShowPrices() | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 1427 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 1428 |  |  |     def ajax_recalculate_prices(self): | 
            
                                                                        
                            
            
                                    
            
            
                | 1429 |  |  |         """Recalculate prices for all ARs | 
            
                                                                        
                            
            
                                    
            
            
                | 1430 |  |  |         """ | 
            
                                                                        
                            
            
                                    
            
            
                | 1431 |  |  |         # When the option "Include and display pricing information" in | 
            
                                                                        
                            
            
                                    
            
            
                | 1432 |  |  |         # Bika Setup Accounting tab is not selected | 
            
                                                                        
                            
            
                                    
            
            
                | 1433 |  |  |         if not self.show_recalculate_prices(): | 
            
                                                                        
                            
            
                                    
            
            
                | 1434 |  |  |             return {} | 
            
                                                                        
                            
            
                                    
            
            
                | 1435 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 1436 |  |  |         # The sorted records from the request | 
            
                                                                        
                            
            
                                    
            
            
                | 1437 |  |  |         records = self.get_records() | 
            
                                                                        
                            
            
                                    
            
            
                | 1438 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 1439 |  |  |         client = self.get_client() | 
            
                                                                        
                            
            
                                    
            
            
                | 1440 |  |  |         setup = api.get_setup() | 
            
                                                                        
                            
            
                                    
            
            
                | 1441 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 1442 |  |  |         member_discount = float(setup.getMemberDiscount()) | 
            
                                                                        
                            
            
                                    
            
            
                | 1443 |  |  |         member_discount_applies = False | 
            
                                                                        
                            
            
                                    
            
            
                | 1444 |  |  |         if client: | 
            
                                                                        
                            
            
                                    
            
            
                | 1445 |  |  |             member_discount_applies = client.getMemberDiscountApplies() | 
            
                                                                        
                            
            
                                    
            
            
                | 1446 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 1447 |  |  |         prices = {} | 
            
                                                                        
                            
            
                                    
            
            
                | 1448 |  |  |         for n, record in enumerate(records): | 
            
                                                                        
                            
            
                                    
            
            
                | 1449 |  |  |             ardiscount_amount = 0.00 | 
            
                                                                        
                            
            
                                    
            
            
                | 1450 |  |  |             arservices_price = 0.00 | 
            
                                                                        
                            
            
                                    
            
            
                | 1451 |  |  |             arprofiles_price = 0.00 | 
            
                                                                        
                            
            
                                    
            
            
                | 1452 |  |  |             arprofiles_vat_amount = 0.00 | 
            
                                                                        
                            
            
                                    
            
            
                | 1453 |  |  |             arservice_vat_amount = 0.00 | 
            
                                                                        
                            
            
                                    
            
            
                | 1454 |  |  |             services_from_priced_profile = [] | 
            
                                                                        
                            
            
                                    
            
            
                | 1455 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 1456 |  |  |             profile_uids = record.get("Profiles_uid", "").split(",") | 
            
                                                                        
                            
            
                                    
            
            
                | 1457 |  |  |             profile_uids = filter(lambda x: x, profile_uids) | 
            
                                                                        
                            
            
                                    
            
            
                | 1458 |  |  |             profiles = map(self.get_object_by_uid, profile_uids) | 
            
                                                                        
                            
            
                                    
            
            
                | 1459 |  |  |             services = map(self.get_object_by_uid, record.get("Analyses", [])) | 
            
                                                                        
                            
            
                                    
            
            
                | 1460 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 1461 |  |  |             # ANALYSIS PROFILES PRICE | 
            
                                                                        
                            
            
                                    
            
            
                | 1462 |  |  |             for profile in profiles: | 
            
                                                                        
                            
            
                                    
            
            
                | 1463 |  |  |                 use_profile_price = profile.getUseAnalysisProfilePrice() | 
            
                                                                        
                            
            
                                    
            
            
                | 1464 |  |  |                 if not use_profile_price: | 
            
                                                                        
                            
            
                                    
            
            
                | 1465 |  |  |                     continue | 
            
                                                                        
                            
            
                                    
            
            
                | 1466 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 1467 |  |  |                 profile_price = float(profile.getAnalysisProfilePrice()) | 
            
                                                                        
                            
            
                                    
            
            
                | 1468 |  |  |                 arprofiles_price += profile_price | 
            
                                                                        
                            
            
                                    
            
            
                | 1469 |  |  |                 arprofiles_vat_amount += profile.getVATAmount() | 
            
                                                                        
                            
            
                                    
            
            
                | 1470 |  |  |                 profile_services = profile.getService() | 
            
                                                                        
                            
            
                                    
            
            
                | 1471 |  |  |                 services_from_priced_profile.extend(profile_services) | 
            
                                                                        
                            
            
                                    
            
            
                | 1472 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 1473 |  |  |             # ANALYSIS SERVICES PRICE | 
            
                                                                        
                            
            
                                    
            
            
                | 1474 |  |  |             for service in services: | 
            
                                                                        
                            
            
                                    
            
            
                | 1475 |  |  |                 if service in services_from_priced_profile: | 
            
                                                                        
                            
            
                                    
            
            
                | 1476 |  |  |                     continue | 
            
                                                                        
                            
            
                                    
            
            
                | 1477 |  |  |                 service_price = float(service.getPrice()) | 
            
                                                                        
                            
            
                                    
            
            
                | 1478 |  |  |                 # service_vat = float(service.getVAT()) | 
            
                                                                        
                            
            
                                    
            
            
                | 1479 |  |  |                 service_vat_amount = float(service.getVATAmount()) | 
            
                                                                        
                            
            
                                    
            
            
                | 1480 |  |  |                 arservice_vat_amount += service_vat_amount | 
            
                                                                        
                            
            
                                    
            
            
                | 1481 |  |  |                 arservices_price += service_price | 
            
                                                                        
                            
            
                                    
            
            
                | 1482 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 1483 |  |  |             base_price = arservices_price + arprofiles_price | 
            
                                                                        
                            
            
                                    
            
            
                | 1484 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 1485 |  |  |             # Calculate the member discount if it applies | 
            
                                                                        
                            
            
                                    
            
            
                | 1486 |  |  |             if member_discount and member_discount_applies: | 
            
                                                                        
                            
            
                                    
            
            
                | 1487 |  |  |                 logger.info("Member discount applies with {}%".format( | 
            
                                                                        
                            
            
                                    
            
            
                | 1488 |  |  |                     member_discount)) | 
            
                                                                        
                            
            
                                    
            
            
                | 1489 |  |  |                 ardiscount_amount = base_price * member_discount / 100 | 
            
                                                                        
                            
            
                                    
            
            
                | 1490 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 1491 |  |  |             subtotal = base_price - ardiscount_amount | 
            
                                                                        
                            
            
                                    
            
            
                | 1492 |  |  |             vat_amount = arprofiles_vat_amount + arservice_vat_amount | 
            
                                                                        
                            
            
                                    
            
            
                | 1493 |  |  |             total = subtotal + vat_amount | 
            
                                                                        
                            
            
                                    
            
            
                | 1494 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 1495 |  |  |             prices[n] = { | 
            
                                                                        
                            
            
                                    
            
            
                | 1496 |  |  |                 "discount": "{0:.2f}".format(ardiscount_amount), | 
            
                                                                        
                            
            
                                    
            
            
                | 1497 |  |  |                 "subtotal": "{0:.2f}".format(subtotal), | 
            
                                                                        
                            
            
                                    
            
            
                | 1498 |  |  |                 "vat": "{0:.2f}".format(vat_amount), | 
            
                                                                        
                            
            
                                    
            
            
                | 1499 |  |  |                 "total": "{0:.2f}".format(total), | 
            
                                                                        
                            
            
                                    
            
            
                | 1500 |  |  |             } | 
            
                                                                        
                            
            
                                    
            
            
                | 1501 |  |  |             logger.info("Prices for AR {}: Discount={discount} " | 
            
                                                                        
                            
            
                                    
            
            
                | 1502 |  |  |                         "VAT={vat} Subtotal={subtotal} total={total}" | 
            
                                                                        
                            
            
                                    
            
            
                | 1503 |  |  |                         .format(n, **prices[n])) | 
            
                                                                        
                            
            
                                    
            
            
                | 1504 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 1505 |  |  |         return prices | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1506 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1507 |  |  |     def check_confirmation(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1508 |  |  |         """Returns a dict when user confirmation is required for the creation of | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1509 |  |  |         samples. Returns None otherwise | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1510 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1511 |  |  |         if self.request.form.get("confirmed") == "1": | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1512 |  |  |             # User pressed the "yes" button in the confirmation pane already | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1513 |  |  |             return None | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1514 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1515 |  |  |         # Find out if there is a confirmation adapter available | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1516 |  |  |         adapter = queryAdapter(self.request, IAddSampleConfirmation) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1517 |  |  |         if not adapter: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1518 |  |  |             return None | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1519 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1520 |  |  |         # Extract records from the request and call the adapter | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1521 |  |  |         records = self.get_records() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1522 |  |  |         return adapter.check_confirmation(records) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1523 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1524 |  |  |     def ajax_cancel(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1525 |  |  |         """Cancel and redirect to configured actions | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1526 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1527 |  |  |         message = _("Sample creation cancelled") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1528 |  |  |         self.context.plone_utils.addPortalMessage(message, "info") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1529 |  |  |         return self.handle_redirect([], message) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1530 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1531 |  |  |     def ajax_submit(self): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1532 |  |  |         """Create samples and redirect to configured actions | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1533 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1534 |  |  |         # Check if there is the need to display a confirmation pane | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1535 |  |  |         confirmation = self.check_confirmation() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1536 |  |  |         if confirmation: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1537 |  |  |             return {"confirmation": confirmation} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1538 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1539 |  |  |         # Get AR required fields (including extended fields) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1540 |  |  |         fields = self.get_ar_fields() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1541 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1542 |  |  |         # extract records from request | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1543 |  |  |         records = self.get_records() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1544 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1545 |  |  |         fielderrors = {} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1546 |  |  |         errors = {"message": "", "fielderrors": {}} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1547 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1548 |  |  |         attachments = {} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1549 |  |  |         valid_records = [] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1550 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1551 |  |  |         # Validate required fields | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1552 |  |  |         for n, record in enumerate(records): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1553 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1554 |  |  |             # Process UID fields first and set their values to the linked field | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1555 |  |  |             uid_fields = filter(lambda f: f.endswith("_uid"), record) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1556 |  |  |             for field in uid_fields: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1557 |  |  |                 name = field.replace("_uid", "") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1558 |  |  |                 value = record.get(field) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1559 |  |  |                 if "," in value: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1560 |  |  |                     value = value.split(",") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1561 |  |  |                 record[name] = value | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1562 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1563 |  |  |             # Extract file uploads (fields ending with _file) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1564 |  |  |             # These files will be added later as attachments | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1565 |  |  |             file_fields = filter(lambda f: f.endswith("_file"), record) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1566 |  |  |             attachments[n] = map(lambda f: record.pop(f), file_fields) | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1567 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1568 |  |  |             # Required fields and their values | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1569 |  |  |             required_keys = [field.getName() for field in fields | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1570 |  |  |                              if field.required] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1571 |  |  |             required_values = [record.get(key) for key in required_keys] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1572 |  |  |             required_fields = dict(zip(required_keys, required_values)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1573 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1574 |  |  |             # Client field is required but hidden in the AR Add form. We remove | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1575 |  |  |             # it therefore from the list of required fields to let empty | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1576 |  |  |             # columns pass the required check below. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1577 |  |  |             if record.get("Client", False): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1578 |  |  |                 required_fields.pop('Client', None) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1579 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1580 |  |  |             # Check if analyses are required for sample registration | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1581 |  |  |             if not self.analyses_required(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1582 |  |  |                 required_fields.pop("Analyses", None) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1583 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1584 |  |  |             # Contacts get pre-filled out if only one contact exists. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1585 |  |  |             # We won't force those columns with only the Contact filled out to | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1586 |  |  |             # be required. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1587 |  |  |             contact = required_fields.pop("Contact", None) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1588 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1589 |  |  |             # None of the required fields are filled, skip this record | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1590 |  |  |             if not any(required_fields.values()): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1591 |  |  |                 continue | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1592 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1593 |  |  |             # Re-add the Contact | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1594 |  |  |             required_fields["Contact"] = contact | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1595 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1596 |  |  |             # Check if the contact belongs to the selected client | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1597 |  |  |             contact_obj = api.get_object(contact, None) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1598 |  |  |             if not contact_obj: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1599 |  |  |                 fielderrors["Contact"] = _("No valid contact") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1600 |  |  |             else: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1601 |  |  |                 parent_uid = api.get_uid(api.get_parent(contact_obj)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1602 |  |  |                 if parent_uid != record.get("Client"): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1603 |  |  |                     msg = _("Contact does not belong to the selected client") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1604 |  |  |                     fielderrors["Contact"] = msg | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1605 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1606 |  |  |             # Missing required fields | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1607 |  |  |             missing = [f for f in required_fields if not record.get(f, None)] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1608 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1609 |  |  |             # Handle required fields from Service conditions | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1610 |  |  |             for condition in record.get("ServiceConditions", []): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1611 |  |  |                 if condition.get("required") == "on": | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1612 |  |  |                     if not condition.get("value"): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1613 |  |  |                         title = condition.get("title") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1614 |  |  |                         if title not in missing: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1615 |  |  |                             missing.append(title) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1616 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1617 |  |  |             # If there are required fields missing, flag an error | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1618 |  |  |             for field in missing: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1619 |  |  |                 fieldname = "{}-{}".format(field, n) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1620 |  |  |                 msg = _("Field '{}' is required".format(field)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1621 |  |  |                 fielderrors[fieldname] = msg | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1622 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1623 |  |  |             # Process valid record | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1624 |  |  |             valid_record = dict() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1625 |  |  |             for fieldname, fieldvalue in six.iteritems(record): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1626 |  |  |                 # clean empty | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1627 |  |  |                 if fieldvalue in ['', None]: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1628 |  |  |                     continue | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1629 |  |  |                 valid_record[fieldname] = fieldvalue | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1630 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1631 |  |  |             # append the valid record to the list of valid records | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1632 |  |  |             valid_records.append(valid_record) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1633 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1634 |  |  |         # return immediately with an error response if some field checks failed | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1635 |  |  |         if fielderrors: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1636 |  |  |             errors["fielderrors"] = fielderrors | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1637 |  |  |             return {'errors': errors} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1638 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1639 |  |  |         # do a custom validation of records. For instance, we may want to rise | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1640 |  |  |         # an error if a value set to a given field is not consistent with a | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1641 |  |  |         # value set to another field | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1642 |  |  |         validators = getAdapters((self.request, ), IAddSampleRecordsValidator) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1643 |  |  |         for name, validator in validators: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1644 |  |  |             validation_err = validator.validate(valid_records) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1645 |  |  |             if validation_err: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1646 |  |  |                 # Not valid, return immediately with an error response | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1647 |  |  |                 return {"errors": validation_err} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1648 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1649 |  |  |         # Process Form | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1650 |  |  |         actions = ActionHandlerPool.get_instance() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1651 |  |  |         actions.queue_pool() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1652 |  |  |         ARs = OrderedDict() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1653 |  |  |         for n, record in enumerate(valid_records): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1654 |  |  |             client_uid = record.get("Client") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1655 |  |  |             client = self.get_object_by_uid(client_uid) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1656 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1657 |  |  |             if not client: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1658 |  |  |                 actions.resume() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1659 |  |  |                 raise RuntimeError("No client found") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1660 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1661 |  |  |             # Create the Analysis Request | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1662 |  |  |             try: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1663 |  |  |                 ar = crar( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1664 |  |  |                     client, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1665 |  |  |                     self.request, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1666 |  |  |                     record, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1667 |  |  |                 ) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1668 |  |  |             except Exception as e: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1669 |  |  |                 actions.resume() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1670 |  |  |                 errors["message"] = str(e) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1671 |  |  |                 return {"errors": errors} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1672 |  |  |             # We keep the title to check if AR is newly created | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1673 |  |  |             # and UID to print stickers | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1674 |  |  |             ARs[ar.Title()] = ar.UID() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1675 |  |  |             for attachment in attachments.get(n, []): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1676 |  |  |                 if not attachment.filename: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1677 |  |  |                     continue | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1678 |  |  |                 att = _createObjectByType("Attachment", client, tmpID()) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1679 |  |  |                 att.setAttachmentFile(attachment) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1680 |  |  |                 att.processForm() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1681 |  |  |                 ar.addAttachment(att) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1682 |  |  |         actions.resume() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1683 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1684 |  |  |         level = "info" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1685 |  |  |         if len(ARs) == 0: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1686 |  |  |             message = _('No Samples could be created.') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1687 |  |  |             level = "error" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1688 |  |  |         elif len(ARs) > 1: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1689 |  |  |             message = _('Samples ${ARs} were successfully created.', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1690 |  |  |                         mapping={'ARs': safe_unicode(', '.join(ARs.keys()))}) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1691 |  |  |         else: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1692 |  |  |             message = _('Sample ${AR} was successfully created.', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1693 |  |  |                         mapping={'AR': safe_unicode(ARs.keys()[0])}) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1694 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1695 |  |  |         # Display a portal message | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1696 |  |  |         self.context.plone_utils.addPortalMessage(message, level) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1697 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1698 |  |  |         return self.handle_redirect(ARs.values(), message) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1699 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1700 |  |  |     def handle_redirect(self, uids, message): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1701 |  |  |         """Handle redirect after sample creation or cancel | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1702 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1703 |  |  |         # Automatic label printing | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1704 |  |  |         setup = api.get_setup() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1705 |  |  |         auto_print = setup.getAutoPrintStickers() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1706 |  |  |         immediate_results_entry = setup.getImmediateResultsEntry() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1707 |  |  |         redirect_to = self.context.absolute_url() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1708 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1709 |  |  |         # UIDs of the new created samples | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1710 |  |  |         sample_uids = ",".join(uids) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1711 |  |  |         # UIDs of previous created samples when save© was selected | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1712 |  |  |         prev_sample_uids = self.request.get("sample_uids") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1713 |  |  |         if prev_sample_uids: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1714 |  |  |             sample_uids = ",".join([prev_sample_uids, sample_uids]) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1715 |  |  |         # Get the submit action (either "Save" or "Save and Copy") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1716 |  |  |         submit_action = self.request.form.get("submit_action", "save") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1717 |  |  |         if submit_action == "save_and_copy": | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1718 |  |  |             # redirect to the sample add form, but keep track of | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1719 |  |  |             # previous created sample UIDs | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1720 |  |  |             redirect_to = "{}/ar_add?copy_from={}&ar_count={}&sample_uids={}" \ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1721 |  |  |                 .format(self.context.absolute_url(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1722 |  |  |                         ",".join(uids),  # copy_from | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1723 |  |  |                         len(uids),  # ar_count | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1724 |  |  |                         sample_uids)  # sample_uids | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1725 |  |  |         elif "register" in auto_print and sample_uids: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1726 |  |  |             redirect_to = "{}/sticker?autoprint=1&template={}&items={}".format( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1727 |  |  |                 self.context.absolute_url(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1728 |  |  |                 setup.getAutoStickerTemplate(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1729 |  |  |                 sample_uids) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1730 |  |  |         elif immediate_results_entry and sample_uids: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1731 |  |  |             redirect_to = "{}/multi_results?uids={}".format( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1732 |  |  |                 self.context.absolute_url(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1733 |  |  |                 sample_uids) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1734 |  |  |         return { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1735 |  |  |             "success": message, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1736 |  |  |             "redirect_to": redirect_to, | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 1737 |  |  |         } | 
            
                                                        
            
                                    
            
            
                | 1738 |  |  |  |