Beispiel #1
0
    def before_render(self):
        # Additional columns
        self.add_columns()
        # Remove unnecessary columns
        self.hide_columns()

        # Apply client filter, if necessary
        client = api.get_current_client()
        if client:
            query = dict(getClientUID=api.get_uid(client))
            self.listing.contentFilter.update(query)
            for rv in self.listing.review_states:
                if "contentFilter" not in rv:
                    rv["contentFilter"] = {}
                rv["contentFilter"].update(query)

        # Render the Add button
        self.listing.context_actions = {}
        batches = api.get_portal().batches
        if security.check_permission(AddBatch, batches):
            url = api.get_url(batches)
            self.listing.context_actions = {
                _("Add"): {
                    "url": "{}/createObject?type_name=Batch".format(url),
                    "icon": "++resource++bika.lims.images/add.png"
                }
            }
Beispiel #2
0
    def before_render(self):
        # Additional columns
        self.add_columns()
        # Remove unnecessary columns
        self.hide_columns()

        # Apply client filter, if necessary
        client = api.get_current_client()
        if client:
            query = dict(getClientUID=api.get_uid(client))
            self.listing.contentFilter.update(query)
            for rv in self.listing.review_states:
                if "contentFilter" not in rv:
                    rv["contentFilter"] = {}
                rv["contentFilter"].update(query)

        # Render the Add button
        self.listing.context_actions = {}
        batches = api.get_portal().batches
        if security.check_permission(AddBatch, batches):
            url = api.get_url(batches)
            self.listing.context_actions = {
                _("Add"): {
                    "url": "{}/createObject?type_name=Batch".format(url),
                    "icon": "++resource++bika.lims.images/add.png"}
            }
Beispiel #3
0
    def update(self):
        """Called before the listings renders
        """
        super(PatientsView, self).update()

        # Render the Add button. We need to do this here because patients live
        # inside site.patients folder
        self.context_actions = {}
        patients = api.get_portal().patients
        if security.check_permission(AddPatient, patients):
            self.context_actions = {
                _("Add"): {
                    "url": "createObject?type_name=Patient",
                    "icon": "++resource++bika.lims.images/add.png"
                }
            }

        # If the current user is a client contact, display those patients that
        # belong to same client or that do not belong to any client
        client = api.get_current_client()
        if client:
            query = dict(client_uid=[api.get_uid(client), "-1"])
            # We add UID "-1" to also include Patients w/o Client assigned
            self.contentFilter.update(query)
            for rv in self.review_states:
                rv["contentFilter"].update(query)

        # If the current context is a Client, remove the title column
        if IClient.providedBy(self.context):
            self.remove_column('getPrimaryReferrerTitle')
Beispiel #4
0
    def update(self):
        """Before template render hook
        """
        super(BatchFolderContentsView, self).update()

        if self.context.portal_type == "BatchFolder":
            self.request.set("disable_border", 1)

        # By default, only users with AddBatch permissions for the current
        # context can add batches.
        self.context_actions = {
            _("Add"): {
                "url": "createObject?type_name=Batch",
                "permission": AddBatch,
                "icon": "++resource++bika.lims.images/add.png"
            }
        }

        # If current user is a client contact and current context is not a
        # Client, then modify the url for Add action so the Batch gets created
        # inside the Client object to which the current user belongs. The
        # reason is that Client contacts do not have privileges to create
        # Batches inside portal/batches
        if not IClient.providedBy(self.context):
            # Get the client the current user belongs to
            client = api.get_current_client()
            if client and check_permission(AddBatch, client):
                add_url = self.context_actions[_("Add")]["url"]
                add_url = "{}/{}".format(api.get_url(client), add_url)
                self.context_actions[_("Add")]["url"] = add_url
                del (self.context_actions[_("Add")]["permission"])
Beispiel #5
0
    def update(self):
        """Called before the listings renders
        """
        super(PatientsView, self).update()

        # Render the Add button. We need to do this here because patients live
        # inside site.patients folder
        self.context_actions = {}
        patients = api.get_portal().patients
        if security.check_permission(AddPatient, patients):
            self.context_actions = {
                _("Add"): {
                    "url": "createObject?type_name=Patient",
                    "icon": "++resource++bika.lims.images/add.png"}
            }

        # If the current user is a client contact, display those patients that
        # belong to same client or that do not belong to any client
        client = api.get_current_client()
        if client:
            query = dict(client_uid=[api.get_uid(client), "-1"])
            # We add UID "-1" to also include Patients w/o Client assigned
            self.contentFilter.update(query)
            for rv in self.review_states:
                rv["contentFilter"].update(query)

        # If the current context is a Client, remove the title column
        if IClient.providedBy(self.context):
            self.remove_column('getPrimaryReferrerTitle')
Beispiel #6
0
    def update(self):
        """Before template render hook
        """
        super(DoctorsView, self).update()

        if IDoctors.providedBy(self.context):
            # Top-level doctors listing
            self.request.set("disable_border", 1)

        elif "disable_border" in self.request:
            del (self.request["disable_border"])

        # By default, only users with AddDoctor permissions for the current
        # context can add doctors.
        self.context_actions = {
            _("Add"): {
                "url": "createObject?type_name=Doctor",
                "permission": AddDoctor,
                "icon": "++resource++bika.lims.images/add.png"
            }
        }

        # If current user is a client contact and current context is not a
        # Client, then modify the url for Add action so the Doctor gets created
        # inside the Client object the current user belongs to
        client = self.get_user_client()
        if client and check_permission(AddDoctor, client):
            add_url = self.context_actions[_("Add")]["url"]
            add_url = "{}/{}".format(api.get_url(client), add_url)
            self.context_actions[_("Add")]["url"] = add_url
            del (self.context_actions[_("Add")]["permission"])

        if self.get_client():
            # The current context is a Client, remove the client column
            self.remove_column('getPrimaryReferrer')
Beispiel #7
0
 def before_render(self):
     """Before template render hook
     """
     super(PricelistsView, self).before_render()
     # Render the Add button if the user has the AddPricelist permission
     if check_permission(AddPricelist, self.context):
         self.context_actions[_("Add")] = {
             "url": "createObject?type_name=Pricelist",
             "icon": "++resource++bika.lims.images/add.png"
         }
     # Don't allow any context actions on the Methods folder
     self.request.set("disable_border", 1)
Beispiel #8
0
 def get_breadcrumbs(self):
     """Generates the breadcrumbs. Items for which current user does not
     have the View permission granted are omitted
     """
     hierarchy = []
     current = self.context
     while not api.is_portal(current):
         if api.is_object(current):
             if check_permission(View, current):
                 hierarchy.append(current)
         else:
             # Some objects (e.g. portal_registry) are not supported
             hierarchy.append(current)
         current = current.aq_parent
     hierarchy = reversed(hierarchy)
     return map(self.to_breadcrumb, hierarchy)
Beispiel #9
0
    def get_reference_field_data(self, field):
        """Get reference field view data for the template
        """
        targets = None
        fieldname = field.getName()

        accessor = getattr(self.context, "get%s" % fieldname, None)
        if accessor and callable(accessor):
            targets = accessor()
        else:
            targets = field.get(self.context)

        if targets:
            if not isinstance(targets, list):
                targets = [targets, ]

            if all([check_permission(view, target) for target in targets]):
                elements = [
                    "<div id='{id}' class='field reference'>"
                    "  <a class='link' uid='{uid}' href='{url}'>"
                    "    {title}"
                    "  </a>"
                    "</div>"
                    .format(id=target.getId(),
                            uid=target.UID(),
                            url=target.absolute_url(),
                            title=target.Title())
                    for target in targets]

                return {
                    "fieldName": fieldname,
                    "mode": "structure",
                    "html": "".join(elements),
                }
            else:
                return {
                    "fieldName": fieldname,
                    "mode": "structure",
                    "html": ", ".join([ta.Title() for ta in targets]),
                }

        return {
            "fieldName": fieldname,
            "mode": "structure",
            "html": ""
        }
Beispiel #10
0
    def purge_nav_tree(self, data):
        """Purges the items of the nav tree for which the current user does not
        have "View" permission granted
        """
        item = data.get("item", "")
        if item:
            # Check if current user has "View" permission granted
            try:
                if not check_permission(View, item):
                    return None
            except Unauthorized:
                return None

        if "children" in data:
            children = map(self.purge_nav_tree, data["children"])
            children = filter(None, children)
            data["children"] = children

        return data
Beispiel #11
0
    def update(self):
        """Before template render hook
        """
        super(PatientsView, self).update()

        if IPatients.providedBy(self.context):
            # Top-level patients listing
            self.request.set("disable_border", 1)

        elif "disable_border" in self.request:
            del (self.request["disable_border"])

        # By default, only users with AddPatient permissions for the current
        # context can add patients.
        self.context_actions = {
            _("Add"): {
                "url": "createObject?type_name=Patient",
                "permission": AddPatient,
                "icon": "++resource++bika.lims.images/add.png"
            }
        }

        # If current user is a client contact, then modify the url for Add
        # action so the Patient gets created, inside the Client object to which
        # the current user belongs. The reason is that the permission
        # "AddPatient" for client contacts in base folders is not granted
        client = self.get_user_client()
        if client and check_permission(AddPatient, client):
            add_url = self.context_actions[_("Add")]["url"]
            add_url = "{}/{}".format(api.get_url(client), add_url)
            self.context_actions[_("Add")]["url"] = add_url
            del (self.context_actions[_("Add")]["permission"])

        if self.get_client():
            # The current context belongs to a Client, remove the title column
            self.remove_column('getPrimaryReferrerTitle')
Beispiel #12
0
 def is_specification_editable(self):
     """Returns whether the Specification field is editable or not
     """
     return check_permission(FieldEditSpecification, self.context)
    def set(self, instance, items, prices=None, specs=None, hidden=None, **kw):
        """Set/Assign Analyses to this AR

        :param items: List of Analysis objects/brains, AnalysisService
                      objects/brains and/or Analysis Service uids
        :type items: list
        :param prices: Mapping of AnalysisService UID -> price
        :type prices: dict
        :param specs: List of AnalysisService UID -> Result Range mappings
        :type specs: list
        :param hidden: List of AnalysisService UID -> Hidden mappings
        :type hidden: list
        :returns: list of new assigned Analyses
        """
        if items is None:
            items = []

        # Bail out if the items is not a list type
        if not isinstance(items, (list, tuple)):
            raise TypeError(
                "Items parameter must be a tuple or list, got '{}'".format(
                    type(items)))

        # Bail out if the AR is inactive
        if not api.is_active(instance):
            raise Unauthorized(
                "Inactive ARs can not be modified".format(AddAnalysis))

        # Bail out if the user has not the right permission
        if not check_permission(AddAnalysis, instance):
            raise Unauthorized(
                "You do not have the '{}' permission".format(AddAnalysis))

        # Convert the items to a valid list of AnalysisServices
        services = filter(None, map(self._to_service, items))

        # Calculate dependencies
        dependencies = map(lambda s: s.getServiceDependencies(), services)
        dependencies = list(itertools.chain.from_iterable(dependencies))

        # Merge dependencies and services
        services = set(services + dependencies)

        # Modify existing AR specs with new form values of selected analyses
        specs = self.resolve_specs(instance, specs)

        # Add analyses
        params = dict(prices=prices, hidden=hidden, specs=specs)
        map(lambda serv: self.add_analysis(instance, serv, **params), services)

        # Get all analyses (those from descendants included)
        analyses = instance.objectValues("Analysis")
        analyses.extend(self.get_analyses_from_descendants(instance))

        # Bail out those not in services list or submitted
        uids = map(api.get_uid, services)
        to_remove = filter(lambda an: an.getServiceUID() not in uids, analyses)
        to_remove = filter(lambda an: not ISubmitted.providedBy(an), to_remove)

        # Remove analyses
        map(self.remove_analysis, to_remove)
Beispiel #14
0
    def set(self, instance, items, prices=None, specs=None, hidden=None, **kw):
        """Set/Assign Analyses to this AR

        :param items: List of Analysis objects/brains, AnalysisService
                      objects/brains and/or Analysis Service uids
        :type items: list
        :param prices: Mapping of AnalysisService UID -> price
        :type prices: dict
        :param specs: List of AnalysisService UID -> Result Range mappings
        :type specs: list
        :param hidden: List of AnalysisService UID -> Hidden mappings
        :type hidden: list
        :returns: list of new assigned Analyses
        """
        # This setter returns a list of new set Analyses
        new_analyses = []

        # Current assigned analyses
        analyses = instance.objectValues("Analysis")

        # Analyses which are in a non-open state must be retained, except those
        # that are in a registered state (the sample has not been received)
        non_open_analyses = filter(lambda an: not an.isOpen(), analyses)
        non_open_analyses = filter(
            lambda an: api.get_workflow_status_of(an) != "registered",
            non_open_analyses)

        # Prevent removing all analyses
        #
        # N.B.: Non-open analyses are rendered disabled in the HTML form.
        #       Therefore, their UIDs are not included in the submitted UIDs.
        if not items and not non_open_analyses:
            logger.warn("Not allowed to remove all Analyses from AR.")
            return new_analyses

        # Bail out if the items is not a list type
        if not isinstance(items, (list, tuple)):
            raise TypeError(
                "Items parameter must be a tuple or list, got '{}'".format(
                    type(items)))

        # Bail out if the AR is inactive
        if not api.is_active(instance):
            raise Unauthorized(
                "Inactive ARs can not be modified".format(AddAnalysis))

        # Bail out if the user has not the right permission
        if not check_permission(AddAnalysis, instance):
            raise Unauthorized(
                "You do not have the '{}' permission".format(AddAnalysis))

        # Convert the items to a valid list of AnalysisServices
        services = filter(None, map(self._to_service, items))

        # Calculate dependencies
        # FIXME Infinite recursion error possible here, if the formula includes
        #       the Keyword of the Service that includes the Calculation
        dependencies = map(lambda s: s.getServiceDependencies(), services)
        dependencies = list(itertools.chain.from_iterable(dependencies))

        # Merge dependencies and services
        services = set(services + dependencies)

        # Modify existing AR specs with new form values of selected analyses.
        self._update_specs(instance, specs)

        # Create a mapping of Service UID -> Hidden status
        if hidden is None:
            hidden = []
        hidden = dict(map(lambda d: (d.get("uid"), d.get("hidden")), hidden))

        # Ensure we have a prices dictionary
        if prices is None:
            prices = dict()

        # CREATE/MODIFY ANALYSES

        for service in services:
            service_uid = api.get_uid(service)
            keyword = service.getKeyword()

            # Create the Analysis if it doesn't exist
            if shasattr(instance, keyword):
                analysis = instance._getOb(keyword)
            else:
                analysis = create_analysis(instance, service)
                new_analyses.append(analysis)

            # set the hidden status
            analysis.setHidden(hidden.get(service_uid, False))

            # Set the price of the Analysis
            analysis.setPrice(prices.get(service_uid, service.getPrice()))

        # DELETE ANALYSES

        # Service UIDs
        service_uids = map(api.get_uid, services)

        # Analyses IDs to delete
        delete_ids = []

        # Assigned Attachments
        assigned_attachments = []

        for analysis in analyses:
            service_uid = analysis.getServiceUID()

            # Skip if the Service is selected
            if service_uid in service_uids:
                continue

            # Skip non-open Analyses
            if analysis in non_open_analyses:
                continue

            # Remember assigned attachments
            # https://github.com/senaite/senaite.core/issues/1025
            assigned_attachments.extend(analysis.getAttachment())
            analysis.setAttachment([])

            # If it is assigned to a worksheet, unassign it before deletion.
            worksheet = analysis.getWorksheet()
            if worksheet:
                worksheet.removeAnalysis(analysis)

            # Unset the partition reference
            # TODO Remove in >v1.3.0 - This is kept for backwards-compatibility
            part = analysis.getSamplePartition()
            if part:
                # From this partition, remove the reference to the current
                # analysis that is going to be removed to prevent inconsistent
                # states (Sample Partitions referencing to Analyses that do not
                # exist anymore
                an_uid = api.get_uid(analysis)
                part_ans = part.getAnalyses() or []
                part_ans = filter(lambda an: api.get_uid(an) != an_uid,
                                  part_ans)
                part.setAnalyses(part_ans)
            # Unset the Analysis-to-Partition reference
            analysis.setSamplePartition(None)
            delete_ids.append(analysis.getId())

        if delete_ids:
            # Note: subscriber might promote the AR
            instance.manage_delObjects(ids=delete_ids)

        # Remove orphaned attachments
        for attachment in assigned_attachments:
            # only delete attachments which are no further linked
            if not attachment.getLinkedAnalyses():
                logger.info("Deleting attachment: {}".format(
                    attachment.getId()))
                attachment_id = api.get_id(attachment)
                api.get_parent(attachment).manage_delObjects(attachment_id)

        return new_analyses
Beispiel #15
0
 def is_edit_allowed(self):
     """Check permission 'ModifyPortalContent' on the context
     """
     return check_permission(ModifyPortalContent, self.context)
Beispiel #16
0
 def can_view_logs_of(self, obj):
     """Checks if the current user is allowed to see the logs
     """
     return check_permission(ViewLogTab, obj)
Beispiel #17
0
 def is_edit_allowed(self):
     """Check if edit is allowed
     """
     return check_permission(FieldEditSpecification, self.context)
Beispiel #18
0
 def is_edit_allowed(self):
     """Check if edit is allowed
     """
     return check_permission(FieldEditProfiles, self.context)
Beispiel #19
0
 def can_add_batches(self):
     """Checks if the current user is allowed to add batches
     """
     return check_permission(AddBatch, self.context)