def __call__(self, result=None, specification=None, **kwargs):
        searchTerm = _c(self.request.get('searchTerm', '')).lower()
        force_all = self.request.get('force_all', 'true')
        searchFields = 'search_fields' in self.request \
            and json.loads(_u(self.request.get('search_fields', '[]'))) \
            or ('Title',)
        # lookup objects from ZODB
        catalog_name = _c(self.request.get('catalog_name', 'portal_catalog'))
        catalog = getToolByName(self.context, catalog_name)
        base_query = json.loads(_c(self.request['base_query']))
        search_query = json.loads(_c(self.request.get('search_query', "{}")))

        # first with all queries
        contentFilter = dict(
            (k, self.to_utf8(v)) for k, v in base_query.items())
        contentFilter.update(
            dict((k, self.to_utf8(v)) for k, v in search_query.items()))
        try:
            brains = catalog(contentFilter)
        except:
            from bika.lims import logger
            logger.info(contentFilter)
            raise
        if brains and searchTerm:
            _brains = []
            if len(searchFields) == 0 \
                    or (len(searchFields) == 1 and searchFields[0] == 'Title'):
                _brains = [
                    p for p in brains if p.Title.lower().find(searchTerm) > -1
                ]
            else:
                for p in brains:
                    for fieldname in searchFields:
                        value = getattr(p, fieldname, None)
                        if not value:
                            instance = p.getObject()
                            schema = instance.Schema()
                            if fieldname in schema:
                                value = schema[fieldname].get(instance)
                        if callable(value):
                            value = value()
                        if value and value.lower().find(searchTerm) > -1:
                            _brains.append(p)
                            break

            brains = _brains
        # Then just base_query alone ("show all if no match")
        if not brains and force_all.lower() == 'true':
            if search_query:
                brains = catalog(base_query)
                if brains and searchTerm:
                    _brains = [
                        p for p in brains
                        if p.Title.lower().find(searchTerm) > -1
                    ]
                    if _brains:
                        brains = _brains
        return brains
    def __call__(self, result=None, specification=None, **kwargs):
        searchTerm = _c(self.request.get('searchTerm', '')).lower()
        force_all = self.request.get('force_all', 'true')
        searchFields = 'search_fields' in self.request \
            and json.loads(_u(self.request.get('search_fields', '[]'))) \
            or ('Title',)
        # lookup objects from ZODB
        catalog_name = _c(self.request.get('catalog_name', 'portal_catalog'))
        catalog = getToolByName(self.context, catalog_name)
        base_query = json.loads(_c(self.request['base_query']))
        search_query = json.loads(_c(self.request.get('search_query', "{}")))

        # first with all queries
        contentFilter = dict((k, self.to_utf8(v)) for k, v in base_query.items())
        contentFilter.update(dict((k, self.to_utf8(v)) for k, v in search_query.items()))
        try:
            brains = catalog(contentFilter)
        except:
            from bika.lims import logger
            logger.info(contentFilter)
            raise
        if brains and searchTerm:
            _brains = []
            if len(searchFields) == 0 \
                    or (len(searchFields) == 1 and searchFields[0] == 'Title'):
                _brains = [p for p in brains
                           if p.Title.lower().find(searchTerm) > -1]
            else:
                for p in brains:
                    for fieldname in searchFields:
                        value = getattr(p, fieldname, None)
                        if not value:
                            instance = p.getObject()
                            schema = instance.Schema()
                            if fieldname in schema:
                                value = schema[fieldname].get(instance)
                        if callable(value):
                            value = value()
                        if value and value.lower().find(searchTerm) > -1:
                            _brains.append(p)
                            break

            brains = _brains
        # Then just base_query alone ("show all if no match")
        if not brains and force_all.lower() == 'true':
            if search_query:
                brains = catalog(base_query)
                if brains and searchTerm:
                    _brains = [p for p in brains
                               if p.Title.lower().find(searchTerm) > -1]
                    if _brains:
                        brains = _brains
        return brains
Beispiel #3
0
    def isItemAllowed(self, obj):
        """
        Only show "my" worksheets
        this cannot be setup in contentFilter,
        because AuthenticatedMember is not available in __init__
        It also checks if the worksheet can be added to the list depending
        on the department filter. It checks the department of each analysis
        service from each analysis belonguing to the given worksheet.
        If department filtering is disabled in bika_setup, will return True.
        :param obj: An object that represents a Worksheet
        :type obj: CatalogBrain
        :returns: True if the worksheet object meets with the criteria for
            being displayed
        :rtype: bool
        """
        if (self.selected_state == 'mine' or self.restrict_results) \
            and obj.getAnalyst != _c(self.member.getId()):
            # Check if the current WS is assigned to the current user
            return False

        if not self.allowed_department_filtering:
            # Filtering by department is disabled. Return True
            return True

        # Department filtering is enabled. Check if at least one of the
        # analyses associated to this worksheet belongs to at least one
        # of the departments currently selected.
        cdepuids = self.request.get('filter_by_department_info', '')
        cdepuids = cdepuids.split(',') if cdepuids else []
        deps = obj.getDepartmentUIDs
        allowed = [d for d in obj.getDepartmentUIDs if d in cdepuids]
        return len(allowed) > 0
Beispiel #4
0
 def isItemAllowed(self, obj):
     """
     Only show "my" worksheets
     this cannot be setup in contentFilter,
     because AuthenticatedMember is not available in __init__
     It also checks if the worksheet can be added to the list depending
     on the department filter. It checks the department of each analysis
     service from each analysis belonguing to the given worksheet.
     If department filtering is disabled in bika_setup, will return True.
     @Obj: it is a worksheet object.
     @return: boolean
     """
     if self.selected_state == 'mine' or self.restrict_results == True:
         analyst = obj.getAnalyst().strip()
         if analyst != _c(self.member.getId()):
             return False
     if not self.context.bika_setup.getAllowDepartmentFiltering():
         return True
     # Gettin the department from worksheet
     deps = [an.getDepartment().UID() for
             an in obj.getWorksheetServices() if
             an.getDepartment()]
     result = True
     if deps:
         # Getting the cookie value
         cookie_dep_uid = self.request.get('filter_by_department_info', '')
         # Comparing departments' UIDs
         deps_uids = set(deps)
         filter_uids = set(
             cookie_dep_uid.split(','))
         matches = deps_uids & filter_uids
         result = len(matches) > 0
     return result
Beispiel #5
0
    def isItemAllowed(self, obj):
        """
        Only show "my" worksheets
        this cannot be setup in contentFilter,
        because AuthenticatedMember is not available in __init__
        It also checks if the worksheet can be added to the list depending
        on the department filter. It checks the department of each analysis
        service from each analysis belonguing to the given worksheet.
        If department filtering is disabled in bika_setup, will return True.
        :param obj: An object that represents a Worksheet
        :type obj: CatalogBrain
        :returns: True if the worksheet object meets with the criteria for
            being displayed
        :rtype: bool
        """
        if (self.selected_state == 'mine' or self.restrict_results) \
            and obj.getAnalyst != _c(self.member.getId()):
            # Check if the current WS is assigned to the current user
            return False

        if not self.allowed_department_filtering:
            # Filtering by department is disabled. Return True
            return True

        # Department filtering is enabled. Check if at least one of the
        # analyses associated to this worksheet belongs to at least one
        # of the departments currently selected.
        cdepuids = self.request.get('filter_by_department_info', '')
        cdepuids = cdepuids.split(',') if cdepuids else []
        deps = obj.getDepartmentUIDs
        allowed = [d for d in obj.getDepartmentUIDs if d in cdepuids]
        return len(allowed) > 0
Beispiel #6
0
 def isItemAllowed(self, obj):
     """
     Only show "my" worksheets
     this cannot be setup in contentFilter,
     because AuthenticatedMember is not available in __init__
     It also checks if the worksheet can be added to the list depending
     on the department filter. It checks the department of each analysis
     service from each analysis belonguing to the given worksheet.
     If department filtering is disabled in bika_setup, will return True.
     @Obj: it is a worksheet object.
     @return: boolean
     """
     if self.selected_state == 'mine' or self.restrict_results == True:
         analyst = obj.getAnalyst().strip()
         if analyst != _c(self.member.getId()):
             return False
     if not self.context.bika_setup.getAllowDepartmentFiltering():
         return True
     # Gettin the department from worksheet
     deps = [
         an.getDepartment().UID() for an in obj.getWorksheetServices()
         if an.getDepartment()
     ]
     result = True
     if deps:
         # Getting the cookie value
         cookie_dep_uid = self.request.get('filter_by_department_info', '')
         # Comparing departments' UIDs
         deps_uids = set(deps)
         filter_uids = set(cookie_dep_uid.split(','))
         matches = deps_uids & filter_uids
         result = len(matches) > 0
     return result
Beispiel #7
0
 def isItemAllowed(self, obj):
     # Only show "my" worksheets
     # this cannot be setup in contentFilter,
     # because AuthenticatedMember is not available in __init__
     if self.selected_state == 'mine' or self.restrict_results == True:
         analyst = obj.getAnalyst().strip()
         if analyst != _c(self.member.getId()):
             return False
     return BikaListingView.isItemAllowed(self, obj)
Beispiel #8
0
 def isItemAllowed(self, obj):
     # Only show "my" worksheets
     # this cannot be setup in contentFilter,
     # because AuthenticatedMember is not available in __init__
     if self.selected_state == 'mine' or self.restrict_results == True:
         analyst = obj.getAnalyst().strip()
         if analyst != _c(self.member.getId()):
             return False
     return BikaListingView.isItemAllowed(self, obj)
Beispiel #9
0
    def checkUserAccess(self):
        """ Checks if the current user has granted access to this worksheet.
            Returns False if the user has no access, otherwise returns True
        """
        # Deny access to foreign analysts
        allowed = True
        pm = getToolByName(self, "portal_membership")
        member = pm.getAuthenticatedMember()

        analyst = self.getAnalyst().strip()
        if analyst != _c(member.getId()):
            roles = member.getRoles()
            restrict = 'Manager' not in roles \
                    and 'LabManager' not in roles \
                    and 'LabClerk' not in roles \
                    and 'RegulatoryInspector' not in roles \
                    and self.bika_setup.getRestrictWorksheetUsersAccess()
            allowed = not restrict

        return allowed
Beispiel #10
0
    def checkUserAccess(self):
        """ Checks if the current user has granted access to this worksheet.
            Returns False if the user has no access, otherwise returns True
        """
        # Deny access to foreign analysts
        allowed = True
        pm = getToolByName(self, "portal_membership")
        member = pm.getAuthenticatedMember()

        analyst = self.getAnalyst().strip()
        if analyst != _c(member.getId()):
            roles = member.getRoles()
            restrict = 'Manager' not in roles \
                    and 'LabManager' not in roles \
                    and 'LabClerk' not in roles \
                    and 'RegulatoryInspector' not in roles \
                    and self.bika_setup.getRestrictWorksheetUsersAccess()
            allowed = not restrict

        return allowed
Beispiel #11
0
    def checkUserManage(self):
        """ Checks if the current user has granted access to this worksheet
            and if has also privileges for managing it.
        """
        granted = False
        can_access = self.checkUserAccess()

        if can_access == True:
            pm = getToolByName(self, 'portal_membership')
            edit_allowed = pm.checkPermission(EditWorksheet, self)
            if edit_allowed:
                # Check if the current user is the WS's current analyst
                member = pm.getAuthenticatedMember()
                analyst = self.getAnalyst().strip()
                if analyst != _c(member.getId()):
                    # Has management privileges?
                    if pm.checkPermission(ManageWorksheets, self):
                        granted = True
                else:
                    granted = True

        return granted
Beispiel #12
0
    def checkUserManage(self):
        """ Checks if the current user has granted access to this worksheet
            and if has also privileges for managing it.
        """
        granted = False
        can_access = self.checkUserAccess()

        if can_access == True:
            pm = getToolByName(self, "portal_membership")
            edit_allowed = pm.checkPermission(EditWorksheet, self)
            if edit_allowed:
                # Check if the current user is the WS's current analyst
                member = pm.getAuthenticatedMember()
                analyst = self.getAnalyst().strip()
                if analyst != _c(member.getId()):
                    # Has management privileges?
                    if pm.checkPermission(ManageWorksheets, self):
                        granted = True
                else:
                    granted = True

        return granted
Beispiel #13
0
    def __call__(self):
        """Create and render selected report
        """

        # if there's an error, we return productivity.pt which requires these.
        self.selection_macros = SelectionMacrosView(self.context, self.request)

        report_id = self.request.get('report_id', '')
        if not report_id:
            message = "No report specified in request"
            self.logger.error(message)
            self.context.plone_utils.addPortalMessage(message, 'error')
            return self.template()

        self.date = DateTime()
        username = self.context.portal_membership.getAuthenticatedMember(
        ).getUserName()
        self.reporter = self.user_fullname(username)
        self.reporter_email = self.user_email(username)

        # signature image
        self.reporter_signature = ""
        c = [
            x for x in self.bika_setup_catalog(portal_type='LabContact')
            if x.getObject().getUsername() == username
        ]
        if c:
            sf = c[0].getObject().getSignature()
            if sf:
                self.reporter_signature = sf.absolute_url() + "/Signature"

        lab = self.context.bika_setup.laboratory
        self.laboratory = lab
        self.lab_title = lab.getName()
        self.lab_address = lab.getPrintAddress()
        self.lab_email = lab.getEmailAddress()
        self.lab_url = lab.getLabURL()

        client = logged_in_client(self.context)
        if client:
            clientuid = client.UID()
            self.client_title = client.Title()
            self.client_address = client.getPrintAddress()
        else:
            clientuid = None
            self.client_title = None
            self.client_address = None

        ## Render form output

        # the report can add file names to this list; they will be deleted
        # once the PDF has been generated.  temporary plot image files, etc.
        self.request['to_remove'] = []

        try:
            exec("from bika.lims.browser.reports.%s import Report" % report_id)
        except ImportError:
            message = "Report %s not found (shouldn't happen)" % report_id
            self.logger.error(message)
            self.context.plone_utils.addPortalMessage(message, 'error')
            return self.template()

        # Report must return dict with:
        # - report_title - title string for pdf/history listing
        # - report_data - rendered report
        output = Report(self.context, self.request)()

        if type(output) in (str, unicode, bytes):
            # remove temporary files
            for f in self.request['to_remove']:
                os.remove(f)
            return output

        ## The report output gets pulled through report_frame.pt
        self.reportout = output['report_data']
        framed_output = self.frame_template()

        # this is the good part
        pisa.showLogging()
        ramdisk = StringIO()
        pdf = pisa.CreatePDF(framed_output, ramdisk)
        result = ramdisk.getvalue()
        ramdisk.close()

        ## Create new report object
        reportid = self.aq_parent.generateUniqueId('Report')
        self.aq_parent.invokeFactory(id=reportid, type_name="Report")
        report = self.aq_parent._getOb(reportid)
        report.edit(Client=clientuid)
        report.processForm()

        ## write pdf to report object
        report.edit(title=output['report_title'], ReportFile=result)
        report.reindexObject()

        fn = "%s - %s" % (self.date.strftime(
            self.date_format_short), _u(output['report_title']))

        # remove temporary files
        for f in self.request['to_remove']:
            os.remove(f)

        if not pdf.err:
            setheader = self.request.RESPONSE.setHeader
            setheader('Content-Type', 'application/pdf')
            setheader("Content-Disposition",
                      "attachment;filename=\"%s\"" % _c(fn))
            self.request.RESPONSE.write(result)

        return
Beispiel #14
0
    def __call__(self, result=None, specification=None, **kwargs):
        searchTerm = _c(self.request.get('searchTerm', '')).lower()
        force_all = self.request.get('force_all', 'false')
        searchFields = 'search_fields' in self.request \
            and json.loads(_u(self.request.get('search_fields', '[]'))) \
            or ('Title',)
        # lookup objects from ZODB
        catalog_name = _c(self.request.get('catalog_name', 'portal_catalog'))
        catalog = getToolByName(self.context, catalog_name)

        # json.loads does unicode conversion, which will fail in the catalog
        # search for some cases. So we need to convert the strings to utf8
        # see: https://github.com/senaite/bika.lims/issues/443
        base_query = json.loads(self.request['base_query'])
        search_query = json.loads(self.request.get('search_query', "{}"))
        base_query = self.to_utf8(base_query)
        search_query = self.to_utf8(search_query)

        # first with all queries
        contentFilter = dict((k, v) for k, v in base_query.items())
        contentFilter.update(search_query)

        # Sorted by? (by default, Title)
        sort_on = self.request.get('sidx', 'Title')
        if sort_on == 'Title':
            sort_on = 'sortable_title'
        if sort_on:
            # Check if is an index and if is sortable. Otherwise, assume the
            # sorting must be done manually
            index = catalog.Indexes.get(sort_on, None)
            if index and index.meta_type in ['FieldIndex', 'DateIndex']:
                contentFilter['sort_on'] = sort_on
                # Sort order?
                sort_order = self.request.get('sord', 'asc')
                if (sort_order in ['desc', 'reverse', 'rev', 'descending']):
                    contentFilter['sort_order'] = 'descending'
                else:
                    contentFilter['sort_order'] = 'ascending'

        # Can do a search for indexes?
        criterias = []
        fields_wo_index = []
        if searchTerm:
            for field_name in searchFields:
                index = catalog.Indexes.get(field_name, None)
                if not index:
                    fields_wo_index.append(field_name)
                    continue
                if index.meta_type in ('ZCTextIndex'):
                    if searchTerm.isspace():
                        # earchTerm != ' ' added because of
                        # https://github.com/plone/Products.CMFPlone/issues
                        # /1537
                        searchTerm = ''
                        continue
                    else:
                        temp_st = searchTerm + '*'
                        criterias.append(MatchRegexp(field_name, temp_st))
                elif index.meta_type in ('FieldIndex'):
                    criterias.append(MatchRegexp(field_name, searchTerm))
                elif index.meta_type == 'DateIndex':
                    msg = "Unhandled DateIndex search on '%s'" % field_name
                    from bika.lims import logger
                    logger.warn(msg)
                else:
                    criterias.append(Generic(field_name, searchTerm))

        if criterias:
            # Advanced search
            advanced_query = catalog.makeAdvancedQuery(contentFilter)
            aq_or = Or()
            for criteria in criterias:
                aq_or.addSubquery(criteria)
            advanced_query &= aq_or
            brains = catalog.evalAdvancedQuery(advanced_query)
        else:
            brains = catalog(contentFilter)

        if brains and searchTerm and fields_wo_index:
            _brains = []
            for brain in brains:
                for field_name in fields_wo_index:
                    value = getattr(brain, field_name, None)
                    if not value:
                        instance = brain.getObject()
                        schema = instance.Schema()
                        if field_name in schema:
                            value = schema[field_name].get(instance)
                    if callable(value):
                        value = value()
                    if value and value.lower().find(searchTerm) > -1:
                        _brains.append(brain)
                        break
            brains = _brains

        # Then just base_query alone ("show all if no match")
        if not brains and force_all.lower() == 'true':
            if search_query:
                brains = catalog(base_query)
                if brains and searchTerm:
                    _brains = [
                        p for p in brains
                        if p.Title.lower().find(searchTerm) > -1
                    ]
                    if _brains:
                        brains = _brains

        return brains
Beispiel #15
0
    def __call__(self):
        """Create and render selected report
        """

        # if there's an error, we return productivity.pt which requires these.
        self.selection_macros = SelectionMacrosView(self.context, self.request)
        self.additional_reports = []
        adapters = getAdapters((self.context, ), IProductivityReport)
        for name, adapter in adapters:
            report_dict = adapter(self.context, self.request)
            report_dict['id'] = name
            self.additional_reports.append(report_dict)

        report_id = self.request.get('report_id', '')
        if not report_id:
            message = _("No report specified in request")
            self.logger.error(message)
            self.context.plone_utils.addPortalMessage(message, 'error')
            return self.template()

        self.date = DateTime()
        username = self.context.portal_membership.getAuthenticatedMember(
        ).getUserName()
        self.reporter = self.user_fullname(username)
        self.reporter_email = self.user_email(username)

        # signature image
        self.reporter_signature = ""
        c = [
            x for x in self.bika_setup_catalog(portal_type='LabContact')
            if x.getObject().getUsername() == username
        ]
        if c:
            sf = c[0].getObject().getSignature()
            if sf:
                self.reporter_signature = sf.absolute_url() + "/Signature"

        lab = self.context.bika_setup.laboratory
        self.laboratory = lab
        self.lab_title = lab.getName()
        self.lab_address = lab.getPrintAddress()
        self.lab_email = lab.getEmailAddress()
        self.lab_url = lab.getLabURL()

        client = logged_in_client(self.context)
        if client:
            clientuid = client.UID()
            self.client_title = client.Title()
            self.client_address = client.getPrintAddress()
        else:
            clientuid = None
            self.client_title = None
            self.client_address = None

        # Render form output

        # the report can add file names to this list; they will be deleted
        # once the PDF has been generated.  temporary plot image files, etc.
        self.request['to_remove'] = []

        if "report_module" in self.request:
            module = self.request["report_module"]
        else:
            module = "bika.lims.browser.reports.%s" % report_id
        try:
            exec("from %s import Report" % module)
            # required during error redirect: the report must have a copy of
            # additional_reports, because it is used as a surrogate view.
            Report.additional_reports = self.additional_reports
        except ImportError:
            message = "Report %s.Report not found (shouldn't happen)" % module
            self.logger.error(message)
            self.context.plone_utils.addPortalMessage(message, 'error')
            return self.template()

        # Report must return dict with:
        # - report_title - title string for pdf/history listing
        # - report_data - rendered report
        output = Report(self.context, self.request)()

        # if CSV output is chosen, report returns None
        if not output:
            return

        if type(output) in (str, unicode, bytes):
            # remove temporary files
            for f in self.request['to_remove']:
                os.remove(f)
            return output

        # The report output gets pulled through report_frame.pt
        self.reportout = output['report_data']
        framed_output = self.frame_template()

        # this is the good part
        result = createPdf(framed_output, False)

        # remove temporary files
        for f in self.request['to_remove']:
            os.remove(f)

        if result:
            # Create new report object
            reportid = self.aq_parent.generateUniqueId('Report')
            report = _createObjectByType("Report", self.aq_parent, reportid)
            report.edit(Client=clientuid)
            report.processForm()

            # write pdf to report object
            report.edit(title=output['report_title'], ReportFile=result)
            report.reindexObject()

            fn = "%s - %s" % (self.date.strftime(
                self.date_format_short), _u(output['report_title']))

            setheader = self.request.RESPONSE.setHeader
            setheader('Content-Type', 'application/pdf')
            setheader("Content-Disposition",
                      "attachment;filename=\"%s\"" % _c(fn))
            self.request.RESPONSE.write(result)

        return
Beispiel #16
0
def getContainers(instance,
                  minvol=None,
                  allow_blank=True,
                  show_container_types=True,
                  show_containers=True):
    """ Containers vocabulary

    This is a separate class so that it can be called from ajax to filter
    the container list, as well as being used as the AT field vocabulary.

    Returns a tuple of tuples: ((object_uid, object_title), ())

    If the partition is flagged 'Separate', only containers are displayed.
    If the Separate flag is false, displays container types.

    XXX bsc = self.portal.bika_setup_catalog
    XXX obj = bsc(getKeyword='Moist')[0].getObject()
    XXX u'Container Type: Canvas bag' in obj.getContainers().values()
    XXX True

    """

    bsc = getToolByName(instance, 'bika_setup_catalog')

    items = allow_blank and [['', _('Any')]] or []

    containers = []
    for container in bsc(portal_type='Container', sort_on='sortable_title'):
        container = container.getObject()

        # verify container capacity is large enough for required sample volume.
        if minvol is not None:
            capacity = container.getCapacity()
            try:
                capacity = capacity.split(' ', 1)
                capacity = mg(float(capacity[0]), capacity[1])
                if capacity < minvol:
                    continue
            except:
                # if there's a unit conversion error, allow the container
                # to be displayed.
                pass

        containers.append(container)

    if show_containers:
        # containers with no containertype first
        for container in containers:
            if not container.getContainerType():
                items.append((container.UID(), container.Title()))

    ts = getToolByName(instance, 'translation_service').translate
    cat_str = _c(ts(_('Container Type')))
    containertypes = [c.getContainerType() for c in containers]
    containertypes = dict([(ct.UID(), ct.Title())
                           for ct in containertypes if ct])
    for ctype_uid, ctype_title in containertypes.items():
        ctype_title = _c(ctype_title)
        if show_container_types:
            items.append((ctype_uid, "%s: %s" % (cat_str, ctype_title)))
        if show_containers:
            for container in containers:
                ctype = container.getContainerType()
                if ctype and ctype.UID() == ctype_uid:
                    items.append((container.UID(), container.Title()))

    items = tuple(items)
    return items
    def __call__(self, result=None, specification=None, **kwargs):
        searchTerm = _c(self.request.get('searchTerm', '')).lower()
        force_all = self.request.get('force_all', 'false')
        searchFields = 'search_fields' in self.request \
            and json.loads(_u(self.request.get('search_fields', '[]'))) \
            or ('Title',)
        # lookup objects from ZODB
        catalog_name = _c(self.request.get('catalog_name', 'portal_catalog'))
        catalog = getToolByName(self.context, catalog_name)

        # N.B. We don't use json.loads to avoid unicode conversion, which will
        #      fail in the catalog search for some cases
        # see: https://github.com/senaite/bika.lims/issues/443
        base_query = ast.literal_eval(self.request['base_query'])
        search_query = ast.literal_eval(self.request.get('search_query', "{}"))

        # first with all queries
        contentFilter = dict((k, v) for k, v in base_query.items())
        contentFilter.update(search_query)

        # Sorted by? (by default, Title)
        sort_on = self.request.get('sidx', 'Title')
        if sort_on == 'Title':
            sort_on = 'sortable_title'
        if sort_on:
            # Check if is an index and if is sortable. Otherwise, assume the
            # sorting must be done manually
            index = catalog.Indexes.get(sort_on, None)
            if index and index.meta_type in ['FieldIndex', 'DateIndex']:
                contentFilter['sort_on'] = sort_on
                # Sort order?
                sort_order = self.request.get('sord', 'asc')
                if (sort_order in ['desc', 'reverse', 'rev', 'descending']):
                    contentFilter['sort_order'] = 'descending'
                else:
                    contentFilter['sort_order'] = 'ascending'

        # Can do a search for indexes?
        criterias = []
        fields_wo_index = []
        if searchTerm:
            for field_name in searchFields:
                index = catalog.Indexes.get(field_name, None)
                if not index:
                    fields_wo_index.append(field_name)
                    continue
                if index.meta_type in ('ZCTextIndex'):
                    if searchTerm.isspace():
                        # earchTerm != ' ' added because of
                        # https://github.com/plone/Products.CMFPlone/issues
                        # /1537
                        searchTerm = ''
                        continue
                    else:
                        temp_st = searchTerm + '*'
                        criterias.append(MatchRegexp(field_name, temp_st))
                elif index.meta_type in ('FieldIndex'):
                    criterias.append(MatchRegexp(field_name, searchTerm))
                elif index.meta_type == 'DateIndex':
                    msg = "Unhandled DateIndex search on '%s'" % field_name
                    from bika.lims import logger
                    logger.warn(msg)
                else:
                    criterias.append(Generic(field_name, searchTerm))

        if criterias:
            # Advanced search
            advanced_query = catalog.makeAdvancedQuery(contentFilter)
            aq_or = Or()
            for criteria in criterias:
                aq_or.addSubquery(criteria)
            advanced_query &= aq_or
            brains = catalog.evalAdvancedQuery(advanced_query)
        else:
            brains = catalog(contentFilter)

        if brains and searchTerm and fields_wo_index:
            _brains = []
            for brain in brains:
                for field_name in fields_wo_index:
                    value = getattr(brain, field_name, None)
                    if not value:
                        instance = brain.getObject()
                        schema = instance.Schema()
                        if field_name in schema:
                            value = schema[field_name].get(instance)
                    if callable(value):
                        value = value()
                    if value and value.lower().find(searchTerm) > -1:
                        _brains.append(brain)
                        break
            brains = _brains

        # Then just base_query alone ("show all if no match")
        if not brains and force_all.lower() == 'true':
            if search_query:
                brains = catalog(base_query)
                if brains and searchTerm:
                    _brains = [p for p in brains
                               if p.Title.lower().find(searchTerm) > -1]
                    if _brains:
                        brains = _brains

        return brains
Beispiel #18
0
def getContainers(instance,
                  minvol=None,
                  allow_blank=True,
                  show_container_types=True,
                  show_containers=True):
    """ Containers vocabulary

    This is a separate class so that it can be called from ajax to filter
    the container list, as well as being used as the AT field vocabulary.

    Returns a tuple of tuples: ((object_uid, object_title), ())

    If the partition is flagged 'Separate', only containers are displayed.
    If the Separate flag is false, displays container types.

    XXX bsc = self.portal.bika_setup_catalog
    XXX obj = bsc(getKeyword='Moist')[0].getObject()
    XXX u'Container Type: Canvas bag' in obj.getContainers().values()
    XXX True

    """

    bsc = getToolByName(instance, 'bika_setup_catalog')

    items = allow_blank and [['', _('Any')]] or []

    containers = []
    for container in bsc(portal_type='Container', sort_on='sortable_title'):
        container = container.getObject()

        # verify container capacity is large enough for required sample volume.
        if minvol is not None:
            capacity = container.getCapacity()
            try:
                capacity = capacity.split(' ', 1)
                capacity = mg(float(capacity[0]), capacity[1])
                if capacity < minvol:
                    continue
            except:
                # if there's a unit conversion error, allow the container
                # to be displayed.
                pass

        containers.append(container)

    if show_containers:
        # containers with no containertype first
        for container in containers:
            if not container.getContainerType():
                items.append((container.UID(), container.Title()))

    ts = getToolByName(instance, 'translation_service').translate
    cat_str = _c(ts(_('Container Type')))
    containertypes = [c.getContainerType() for c in containers]
    containertypes = dict([(ct.UID(), ct.Title())
                           for ct in containertypes if ct])
    for ctype_uid, ctype_title in containertypes.items():
        ctype_title = _c(ctype_title)
        if show_container_types:
            items.append((ctype_uid, "%s: %s" % (cat_str, ctype_title)))
        if show_containers:
            for container in containers:
                ctype = container.getContainerType()
                if ctype and ctype.UID() == ctype_uid:
                    items.append((container.UID(), container.Title()))

    items = tuple(items)
    return items
 def Title(self):
     return _c(self.title)
Beispiel #20
0
 def search_term(self):
     """Returns the search term
     """
     search_term = _c(self.request.get("searchTerm", ""))
     return search_term.lower().strip()
Beispiel #21
0
    def __call__(self):
        plone.protect.CheckAuthenticator(self.request)
        uc = getToolByName(self.context, 'uid_catalog')
        ar_uid = _c(self.request.get('ar_uid', ''))
        column = _c(self.request.get('column', '0'))

        if not ar_uid:
            return {}

        ar = uc(UID=ar_uid)
        if not ar:
            return {}
        ar = ar[0].getObject()

        categories = []
        services = {}

        for analysis in ar.getAnalyses(full_objects=True):
            service = analysis.getService()
            category = service.getCategory()
            cat_uid = category.UID()
            if cat_uid not in categories:
                categories.append(cat_uid)
            if cat_uid not in services:
                services[cat_uid] = []
            services[cat_uid].append(service.UID())

        batch = ar.getBatch()
        client = ar.getClient()
        contact = ar.getContact()
        # cccontacts = ar.getCCContact()
        ccemails = ar.getCCEmails()
        sampletype = ar.getSampleType()
        samplepoint = ar.getSamplePoint()
        subgroup = ar.Schema()['SubGroup'].get(ar)
        template = ar.getTemplate()
        profile = ar.getProfile()

        ret = {
            'column': column,  # js callback needs to know where the data goes
            'Batch': batch.Title() if batch else '',
            'Batch_uid': batch.UID() if batch else '',
            'Client': client.Title() if client else '',
            'Client_uid': client.UID() if client else '',
            'Contact': contact.getFullname() if contact else '',
            'Contact_uid': contact.UID() if contact else '',
            # 'CCContact': ", ".join([cc.getFullname() for cc in cccontact]) if cccontact else '',
            # 'CCContact_uid': ", ".join([cc.UID() for cc in cccontact]) if cccontact else '',
            'CCEmails': ccemails,
            'SampleType': sampletype.Title() if sampletype else '',
            'SampleType_uid': sampletype.UID() if sampletype else '',
            'SamplePoint': samplepoint.Title() if samplepoint else '',
            'SamplePoint_uid': samplepoint.UID() if samplepoint else '',
            'SubGroup': subgroup.Title() if subgroup else '',
            'SubGroup_uid': subgroup.UID() if subgroup else '',
            'Template': template.Title() if template else '',
            'Template_uid': template.UID() if template else '',
            'Profile': profile.Title() if profile else '',
            'Profile_uid': profile.UID() if profile else '',
            'ClientOrderNumber': ar.getClientOrderNumber(),
            'ClientReference': ar.getSample().getClientReference(),
            'ClientSampleID': ar.getSample().getClientSampleID(),
            'categories': categories,
            'services': services,
        }

        return json.dumps(ret)
    def __init__(self, context, request):
        super(AccreditationView, self).__init__(context, request)
        self.contentFilter = {'portal_type': 'AnalysisService',
                              'sort_on': 'sortable_title',
                              'getAccredited': True,
                              'inactive_state': 'active'}
        self.context_actions = {}
        self.icon = self.portal_url + "/++resource++bika.lims.images/accredited_big.png"
        self.title = _("Accreditation")

        lab = context.bika_setup.laboratory
        accredited = lab.getLaboratoryAccredited()
        self.mapping = {'accredited': accredited,
                        'labname': lab.getName(),
                        'labcountry': lab.getPhysicalAddress().get('country', ''),
                        'confidence': lab.getConfidence(),
                        'abbr': lab.getAccreditationBody(),
                        'body': lab.getAccreditationBodyLong(),
                        'url': lab.getAccreditationBodyURL(),
                        'accr': lab.getAccreditation(),
                        'ref': lab.getAccreditationReference()
                        }
        if accredited:
            translate = self.context.translate
            msg = translate(_("${labname} has been accredited as ${accr} " +
                    "conformant by ${abbr}, (${body}). ${abbr} is " +
                    "recognised by government as a national " +
                    "accreditation body in ${labcountry}. ",
                    mapping=self.mapping))

        else:
            msg = _("The lab is not accredited, or accreditation has not "
                    "been configured. ")
        self.description = context.translate(_c(msg))
        msg = _("All Accredited analysis services are listed here.")
        self.description = "%s<p><br/>%s</p>" % (self.description,
                                               context.translate(_c(msg)))

        self.show_select_column = False
        request.set('disable_border', 1)

        self.columns = {
            'Title': {'title': _('Service'), 'sortable': False},
            'Keyword': {'title': _('Keyword'), 'sortable': False},
            'Category': {'title': _('Category'), 'sortable': False},
            'Department': {'title': _('Department'), 'sortable': False},
            'Instrument': {'title': _('Instrument'), 'sortable': False},
            'Unit': {'title': _('Unit'), 'sortable': False},
            'Price': {'title': _('Price'), 'sortable': False},
            'MaxTimeAllowed': {'title': _('Max Time'), 'sortable': False},
            'DuplicateVariation': {'title': _('Dup Var'), 'sortable': False},
            'Calculation': {'title': _('Calculation'), 'sortable': False},
        }

        self.review_states = [
            {'id': 'default',
             'title': _('All'),
             'contentFilter': {},
             'transitions': [{'id': 'empty'}, ],  # none
             'columns': ['Title',
                         'Keyword',
                         'Category',
                         'Price',
                         'MaxTimeAllowed',
                         'DuplicateVariation',
                         ],
             },
        ]
    def __init__(self, context, request):
        super(AccreditationView, self).__init__(context, request)
        self.contentFilter = {'portal_type': 'AnalysisService',
                              'sort_on': 'sortable_title',
                              'getAccredited':True,
                              'inactive_state':'active'}
        self.context_actions = {}
        self.icon = self.portal_url + "/++resource++bika.lims.images/accredited_big.png"
        self.title = _("Accreditation")

        lab = context.bika_setup.laboratory
        accredited = lab.getLaboratoryAccredited()
        self.mapping = {'accredited':accredited,
                        'labname': lab.getName(),
                        'labcountry': lab.getPhysicalAddress().get('country', ''),
                        'confidence': lab.getConfidence(),
                        'abbr': lab.getAccreditationBody(),
                        'body': lab.getAccreditationBodyLong(),
                        'url': lab.getAccreditationBodyURL(),
                        'accr': lab.getAccreditation(),
                        'ref': lab.getAccreditationReference()
                        }
        if accredited:
            msg = _("${labname} has been accredited as ${accr} " + \
                    "conformant by ${abbr}, (${body}). ${abbr} is " + \
                    "recognised by government as a national " + \
                    "accreditation body in ${labcountry}. ",
                    mapping = self.mapping)
        else:
            msg = _("The lab is not accredited, or accreditation has not "
                    "been configured. ")
        self.description = context.translate(_c(msg))
        msg = _("All Accredited analysis services are listed here.")
        self.description = "%s<p><br/>%s</p>"%(self.description,
                                               context.translate(_c(msg)))

        self.show_select_column = False
        request.set('disable_border', 1)

        self.columns = {
            'Title': {'title': _('Service'), 'sortable':False},
            'Keyword': {'title': _('Keyword'), 'sortable':False},
            'Category': {'title': _('Category'), 'sortable':False},
            'Department': {'title': _('Department'), 'sortable':False},
            'Instrument': {'title': _('Instrument'), 'sortable':False},
            'Unit': {'title': _('Unit'), 'sortable':False},
            'Price': {'title': _('Price'), 'sortable':False},
            'MaxTimeAllowed': {'title': _('Max Time'), 'sortable':False},
            'DuplicateVariation': {'title': _('Dup Var'), 'sortable':False},
            'Calculation': {'title': _('Calculation'), 'sortable':False},
        }

        self.review_states = [
            {'id':'default',
             'title': _('All'),
             'contentFilter':{},
             'transitions': [{'id':'empty'}, ], # none
             'columns': ['Title',
                         'Keyword',
                         'Category',
                         'Price',
                         'MaxTimeAllowed',
                         'DuplicateVariation',
                         ],
             },
        ]
Beispiel #24
0
    def __call__(self):
        plone.protect.CheckAuthenticator(self.request)
        uc = getToolByName(self.context, 'uid_catalog')
        ar_uid = _c(self.request.get('ar_uid', ''))
        column = _c(self.request.get('column', '0'))

        if not ar_uid:
            return {}

        ar = uc(UID=ar_uid)
        if not ar:
            return {}
        ar = ar[0].getObject()

        categories = []
        services = {}

        for analysis in ar.getAnalyses(full_objects=True):
            service = analysis.getService()
            category = service.getCategory()
            cat_uid = category.UID()
            if cat_uid not in categories:
                categories.append(cat_uid)
            if cat_uid not in services:
                services[cat_uid] = []
            services[cat_uid].append(service.UID())

        batch = ar.getBatch()
        client = ar.getClient()
        contact = ar.getContact()
        # cccontacts = ar.getCCContact()
        ccemails = ar.getCCEmails()
        sampletype = ar.getSampleType()
        samplepoint = ar.getSamplePoint()
        subgroup = ar.Schema()['SubGroup'].get(ar)
        template = ar.getTemplate()
        profile = ar.getProfile()

        ret = {
            'column': column,  # js callback needs to know where the data goes
            'Batch': batch.Title() if batch else '',
            'Batch_uid': batch.UID() if batch else '',
            'Client': client.Title() if client else '',
            'Client_uid': client.UID() if client else '',
            'Contact': contact.getFullname() if contact else '',
            'Contact_uid': contact.UID() if contact else '',
            # 'CCContact': ", ".join([cc.getFullname() for cc in cccontact]) if cccontact else '',
            # 'CCContact_uid': ", ".join([cc.UID() for cc in cccontact]) if cccontact else '',
            'CCEmails': ccemails,
            'SampleType': sampletype.Title() if sampletype else '',
            'SampleType_uid': sampletype.UID() if sampletype else '',
            'SamplePoint': samplepoint.Title() if samplepoint else '',
            'SamplePoint_uid': samplepoint.UID() if samplepoint else '',
            'SubGroup': subgroup.Title() if subgroup else '',
            'SubGroup_uid': subgroup.UID() if subgroup else '',
            'Template': template.Title() if template else '',
            'Template_uid': template.UID() if template else '',
            'Profile': profile.Title() if profile else '',
            'Profile_uid': profile.UID() if profile else '',
            'ClientOrderNumber': ar.getClientOrderNumber(),
            'ClientReference': ar.getSample().getClientReference(),
            'ClientSampleID': ar.getSample().getClientSampleID(),

            'categories': categories,
            'services': services,
        }

        return json.dumps(ret)
 def to_utf8(self, s):
     if not isinstance(s, basestring):
         return s
     return _c(s)
Beispiel #26
0
 def Title(self):
     return _c(self.title)
 def to_utf8(self, s):
     if not isinstance(s, basestring):
         return s
     return _c(s)
Beispiel #28
0
    def __call__(self):
        plone.protect.CheckAuthenticator(self.request)
        page = self.request['page']
        nr_rows = self.request['rows']
        sord = self.request['sord']
        sidx = self.request['sidx']
        colModel = json.loads(_u(self.request.get('colModel', '[]')))
        discard_empty = json.loads(_c(self.request.get('discard_empty', "[]")))
        rows = []

        brains = []
        for name, adapter in getAdapters((self.context, self.request), IReferenceWidgetVocabulary):
            brains.extend(adapter())

        for p in brains:
            row = {'UID': getattr(p, 'UID'),
                   'Title': getattr(p, 'Title')}
            other_fields = [x for x in colModel
                            if x['columnName'] not in row.keys()]
            instance = schema = None
            discard = False
            # This will be faster if the columnNames are catalog indexes
            for field in other_fields:
                fieldname = field['columnName']
                # Prioritize method retrieval over field retrieval from schema
                obj = p.getObject()
                value = getattr(obj, fieldname, None)
                if not value or hasattr(value, 'im_self'):
                    value = getattr(p, fieldname, None)
                if not value:
                    if instance is None:
                        instance = p.getObject()
                        schema = instance.Schema()
                    if fieldname in schema:
                        value = schema[fieldname].get(instance)
                    elif hasattr(instance, fieldname):
                        value = getattr(instance, fieldname)
                        if callable(value):
                            value = value()

                if fieldname in discard_empty and not value:
                    discard = True
                    break

                # '&nbsp;' instead of '' because empty div fields don't render
                # correctly in combo results table
                row[fieldname] = value and value or '&nbsp;'

            if discard is False:
                rows.append(row)

        rows = sorted(rows, cmp=lambda x, y: cmp(
            str(x).lower(), str(y).lower()),
            key=itemgetter(sidx and sidx or 'Title'))
        if sord == 'desc':
            rows.reverse()
        pages = len(rows) / int(nr_rows)
        pages += divmod(len(rows), int(nr_rows))[1] and 1 or 0
        start = (int(page) - 1) * int(nr_rows)
        end = int(page) * int(nr_rows)
        ret = {'page': page,
               'total': pages,
               'records': len(rows),
               'rows': rows[start:end]}

        return json.dumps(ret)
Beispiel #29
0
    def __call__(self):
        """Create and render selected report
        """

        # if there's an error, we return productivity.pt which requires these.
        self.selection_macros = SelectionMacrosView(self.context, self.request)
        self.additional_reports = []
        adapters = getAdapters((self.context, ), IProductivityReport)
        for name, adapter in adapters:
            report_dict = adapter(self.context, self.request)
            report_dict['id'] = name
            self.additional_reports.append(report_dict)

        report_id = self.request.get('report_id', '')
        if not report_id:
            message = "No report specified in request"
            self.logger.error(message)
            self.context.plone_utils.addPortalMessage(message, 'error')
            return self.template()

        self.date = DateTime()
        username = self.context.portal_membership.getAuthenticatedMember().getUserName()
        self.reporter = self.user_fullname(username)
        self.reporter_email = self.user_email(username)

        # signature image
        self.reporter_signature = ""
        c = [x for x in self.bika_setup_catalog(portal_type='LabContact')
             if x.getObject().getUsername() == username]
        if c:
            sf = c[0].getObject().getSignature()
            if sf:
                self.reporter_signature = sf.absolute_url() + "/Signature"

        lab = self.context.bika_setup.laboratory
        self.laboratory = lab
        self.lab_title = lab.getName()
        self.lab_address = lab.getPrintAddress()
        self.lab_email = lab.getEmailAddress()
        self.lab_url = lab.getLabURL()

        client = logged_in_client(self.context)
        if client:
            clientuid = client.UID()
            self.client_title = client.Title()
            self.client_address = client.getPrintAddress()
        else:
            clientuid = None
            self.client_title = None
            self.client_address = None

        # Render form output

        # the report can add file names to this list; they will be deleted
        # once the PDF has been generated.  temporary plot image files, etc.
        self.request['to_remove'] = []

        if "report_module" in self.request:
            module = self.request["report_module"]
        else:
            module = "bika.lims.browser.reports.%s" % report_id
        try:
            exec("from %s import Report" % module)
            # required during error redirect: the report must have a copy of
            # additional_reports, because it is used as a surrogate view.
            Report.additional_reports = self.additional_reports
        except ImportError:
            message = "Report %s.Report not found (shouldn't happen)" % module
            self.logger.error(message)
            self.context.plone_utils.addPortalMessage(message, 'error')
            return self.template()

        # Report must return dict with:
        # - report_title - title string for pdf/history listing
        # - report_data - rendered report
        output = Report(self.context, self.request)()

        # if CSV output is chosen, report returns None
        if not output:
            return

        if type(output) in (str, unicode, bytes):
            # remove temporary files
            for f in self.request['to_remove']:
                os.remove(f)
            return output

        # The report output gets pulled through report_frame.pt
        self.reportout = output['report_data']
        framed_output = self.frame_template()

        # this is the good part
        result = createPdf(framed_output)

        # remove temporary files
        for f in self.request['to_remove']:
            os.remove(f)

        if result:
            # Create new report object
            reportid = self.aq_parent.generateUniqueId('Report')
            self.aq_parent.invokeFactory(id=reportid, type_name="Report")
            report = self.aq_parent._getOb(reportid)
            report.edit(Client=clientuid)
            report.processForm()

            # write pdf to report object
            report.edit(title=output['report_title'], ReportFile=result)
            report.reindexObject()

            fn = "%s - %s" % (self.date.strftime(self.date_format_short),
                              _u(output['report_title']))

            setheader = self.request.RESPONSE.setHeader
            setheader('Content-Type', 'application/pdf')
            setheader("Content-Disposition", "attachment;filename=\"%s\"" % _c(fn))
            self.request.RESPONSE.write(result)

        return