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" } }
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"} }
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')
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"])
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')
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')
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)
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)
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": "" }
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
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')
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)
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
def is_edit_allowed(self): """Check permission 'ModifyPortalContent' on the context """ return check_permission(ModifyPortalContent, self.context)
def can_view_logs_of(self, obj): """Checks if the current user is allowed to see the logs """ return check_permission(ViewLogTab, obj)
def is_edit_allowed(self): """Check if edit is allowed """ return check_permission(FieldEditSpecification, self.context)
def is_edit_allowed(self): """Check if edit is allowed """ return check_permission(FieldEditProfiles, self.context)
def can_add_batches(self): """Checks if the current user is allowed to add batches """ return check_permission(AddBatch, self.context)