def isItemAllowed(self, obj): # TODO: Performance tip. We need the full object to filter by Insurance uid = api.get_uid(self.context) full_obj = api.get_object(obj) insurance_company = full_obj.getInsuranceCompany() if not insurance_company: return False return api.get_uid(insurance_company) == uid
def current_user_can_edit(self): """Returns true if the current user can edit this Doctor. """ user_client = api.get_current_client() if user_client: # The current user is a client contact. This user can only edit # this doctor if it has the same client assigned client_uid = api.get_uid(user_client) doctor_client = self.getPrimaryReferrer() return doctor_client and api.get_uid(doctor_client) == client_uid return True
def get_clients_vocabulary(self): client = api.get_current_client() if client: # Current user is a client contact. Load only this client return DisplayList([(api.get_uid(client), api.get_title(client))]) # Current user is not a client contact. Load all active clients query = dict(portal_type="Client", is_active=True) clients = api.search(query, "portal_catalog") clients = map(lambda cl: [api.get_uid(cl), api.get_title(cl)], clients) clients.sort(lambda x, y: cmp(x[1].lower(), y[1].lower())) # Lab personnel can set a Patient to be visible for all Clients clients.insert(0, ['', '']) return DisplayList(clients)
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 getTemplateInstruments(self): """ Distionary of instruments per template Used in bika_listing.pt """ items = dict() templates = self._get_worksheet_templates_brains() for template in templates: template_obj = api.get_object(template) uid_template = api.get_uid(template_obj) instrument = template_obj.getInstrument() uid_instrument = '' if instrument: uid_instrument = api.get_uid(instrument) items[uid_template] = uid_instrument return json.dumps(items)
def get_user_client_uid(self, default=None): """Returns the id of the client the current user belongs to """ client = api.get_current_client() if client: return api.get_uid(client) return default
def Vocabulary(self, content_instance=None): """Create a vocabulary from analysis services """ vocab = [] for service in self._get_services(): vocab.append((api.get_uid(service), api.get_title(service))) return vocab
def client_uid(instance): """Returns the uid of the Client assigned to the Patient, if any. Otherwise returns "-1". """ client = instance.getClient() if client: return api.get_uid(client) return "-1"
def getSamples(self, **kwargs): """Return samples taken from this Patient """ catalog = api.get_tool(CATALOG_ANALYSIS_REQUEST_LISTING, context=self) query = dict([(k, v) for k, v in kwargs.items() if k in catalog.indexes()]) query["getPatientUID"] = api.get_uid(self) brains = api.search(query, CATALOG_ANALYSIS_REQUEST_LISTING) if not kwargs.get("full_objects", False): return brains return map(api.get_object, brains)
def get_clients_vocabulary(self): """ Vocabulary list with clients :return: A DisplayList object """ if self.getBatches() or self.getAnalysisRequests(): # Allow to change the client if there are no ARs associated client = self.getPrimaryReferrer() if not client: # Maybe all Batches and ARs assigned to this Doctor belong to # the same Client.. If so, just assign this client by default client_uids = map(lambda ar: ar.getClientUID, self.getAnalysisRequests()) client_uids = list(set(client_uids)) if len(client_uids) > 1: # More than one client assigned! return DisplayList([('', '')]) clients = map(lambda batch: batch.getClient(), self.getBatches(full_objects=True)) client_uids += map(lambda client: api.get_uid(client), clients) client_uids = list(set(client_uids)) if len(client_uids) > 1: # More than one client assigned! return DisplayList([('', '')]) client = api.get_object_by_uid(client_uids[0]) return DisplayList([(api.get_uid(client), client.Title())]) # If the current user is a client contact, do not display other clients client = api.get_current_client() if client: return DisplayList([(api.get_uid(client), client.Title())]) # Search for clients query = dict(portal_type='Client', is_active=True, sort_order='ascending', sort_on='title') brains = api.search(query, 'portal_catalog') clients = map(lambda brain: [api.get_uid(brain), brain.Title], brains) clients.insert(0, ['', '']) return DisplayList(clients)
def __call__(self, value, *args, **kwargs): # avoid the catalog query if the option is not selected if not api.get_bika_setup().ClientPatientIDUnique: return True query = dict(getClientPatientID=value) patients = api.search(query, CATALOG_PATIENTS) instance = kwargs.get('instance') # If there are no patients with this Client Patient ID # then it is valid if not patients: return True # If there is only one patient with this Client Patient ID # and it is the patient being edited then it also valid if len(patients) == 1 and api.get_uid(patients[0]) == api.get_uid(instance): return True trans = getToolByName(instance, 'translation_service').translate msg = _( "Validation failed: '${value}' is not unique", mapping={ 'value': safe_unicode(value) }) return to_utf8(trans(msg))
def purge_owners_for(batch): """Remove role "Owner" from all those client contacts that do not belong to the same Client the batch is assigned to and assigns the role "Owner" to the client contacts assigned to the batch """ # Add role "Owner" for this batch to all contacts from this Client assign_owners_for(batch) # Unassign role "Owner" from contacts that belong to another Client batch_client = batch.getClient() batch_client_uid = batch_client and api.get_uid(batch_client) or None for client in api.search(dict(portal_type="Client"), "portal_catalog"): if api.get_uid(client) == batch_client_uid: continue client = api.get_object(client) contacts = client.objectValues("Contact") users = map(lambda contact: contact.getUser(), contacts) users = filter(None, users) for user in users: security.revoke_local_roles_for(batch, ["Owner"], user=user) batch.reindexObjectSecurity()
def __call__(self, context): query = { "portal_type": "Microorganism", "is_active": True, "sort_on": "sortable_title", "sort_order": "ascending", } brains = api.search(query, SETUP_CATALOG) items = [ SimpleTerm(api.get_uid(brain), title=api.get_title(brain)) for brain in brains ] return SimpleVocabulary(items)
def getCalculationDependencies(self, flat=False, deps=None): """ Recursively calculates all dependencies of this calculation. The return value is dictionary of dictionaries (of dictionaries...) {service_UID1: {service_UID2: {service_UID3: {}, service_UID4: {}, }, }, } set flat=True to get a simple list of AnalysisService objects """ if deps is None: deps = [] if flat is True else {} def get_fetched(deps): if isinstance(deps, list): return map(api.get_uid, deps) if isinstance(deps, dict): fetched = deps.keys() for value in deps.values(): fetched.extend(get_fetched(value)) return fetched return [] # List of service uids that have been grabbed already. This is used to # prevent an infinite recursion error when the formula includes the # Keyword of the Service that includes the Calculation fetched = get_fetched(deps) for service in self.getDependentServices(): if api.get_uid(service) in fetched: # Processed already. Omit to prevent recursion continue if flat: deps.append(service) else: deps[service.UID()] = {} calc = service.getCalculation() if calc: calc.getCalculationDependencies(flat, deps) if flat: # Remove duplicates deps = list(set(deps)) return deps
def process(context, request, task_uid=None): # noqa """Processes the task passed-in """ # disable CSRF req.disable_csrf_protection() # Maybe the task uid has been sent via POST task_uid = task_uid or req.get_json().get("task_uid") # Get the task task = get_task(task_uid) if task.username != capi.get_current_user().id: # 403 Authenticated, but user does not have access to the resource _fail(403) # Process t0 = time.time() task_context = task.get_context() if not task_context: _fail(500, "Task's context is not available") # Get the adapter able to process this specific type of task adapter = queryAdapter(task_context, IQueuedTaskAdapter, name=task.name) if not adapter: _fail(501, "No adapter found for {}".format(task.name)) logger.info("Processing task {}: '{}' for '{}' ({}) ...".format( task.task_short_uid, task.name, capi.get_id(task_context), task.context_uid)) # Inject the queue_consumer marker to the request so guards skip checks # against the queue request = capi.get_request() request.set("queue_tuid", task_uid) # If the task refers to a worksheet, inject (ws_id) in params to make # sure guards (assign, un-assign) return True if IWorksheet.providedBy(task_context): request.set("ws_uid", capi.get_uid(task_context)) # Process the task adapter.process(task) # Sleep a bit for minimum effect against userland threads # Better to have a transaction conflict here than in userland min_seconds = task.get("min_seconds", 3) while time.time() - t0 < min_seconds: time.sleep(0.5) msg = "Processed: {}".format(task.task_short_uid) return get_message_summary(msg, "consumer.process")
def unlink_version(self, source, target): """Unlink the current version of the target from the source """ if not hasattr(source, REFERENCE_VERSIONS): return target_uid = api.get_uid(target) if target_uid in source.reference_versions[target_uid]: # delete the version del source.reference_versions[target_uid] # persist changes that occured referenced versions source._p_changed = 1 else: logger.warn("No version link found on '{}' -> '{}'".format( repr(source), repr(target)))
def add_reference(self, source, target, **kwargs): """Add a new reference """ # Tweak keyword arguments for addReference addRef_kw = kwargs.copy() addRef_kw.setdefault("referenceClass", self.referenceClass) if "schema" in addRef_kw: del addRef_kw["schema"] uid = api.get_uid(target) rc = api.get_tool("reference_catalog") # throws IndexError if uid is invalid rc.addReference(source, uid, self.relationship, **addRef_kw) # link the version of the reference self.link_version(source, target)
def get_antibiotic_info(self, uid_brain_object): uid = api.get_uid(uid_brain_object) obj = api.get_object(uid_brain_object) href = api.get_url(obj) title = api.get_title(obj) abbreviation = obj.abbreviation or title return { "uid": uid, "link": get_link(href=href, value=abbreviation, title=title), "abbreviation": abbreviation, "title": title, }
def link_reference(self, source, target): """Link the target to the source """ target_uid = api.get_uid(target) # get the annotation storage key key = self.get_relationship_key(target) # get all backreferences from the source # N.B. only like this we get the persistent mapping! backrefs = get_backreferences(source, relationship=None) if key not in backrefs: backrefs[key] = PersistentList() if target_uid not in backrefs[key]: backrefs[key].append(target_uid) return True
def process_form(self, instance, field, form, empty_marker=None, emptyReturnsMarker=False): """Return a list of dictionaries fit for ARTemplate/Analyses field consumption. """ value = [] # selected services service_uids = form.get("uids", []) # defined partitions partitions = form.get("Partition", []) partitions = partitions and partitions[0] or {} # hidden services hidden_services = form.get("Hidden", {}) # get the service objects services = map(api.get_object_by_uid, service_uids) # get dependencies dependencies = map(lambda s: s.getServiceDependencies(), services) dependencies = list(itertools.chain.from_iterable(dependencies)) # Merge dependencies and services services = set(services + dependencies) # get the profile profile_uid = form.get("AnalysisProfile_uid") if profile_uid: profile = api.get_object_by_uid(profile_uid) # update the services with those from the profile services.update(profile.getService()) as_settings = [] for service in services: service_uid = api.get_uid(service) value.append({ "service_uid": service_uid, "partition": partitions.get(service_uid, "part-1") }) hidden = hidden_services.get(service_uid, "") == "on" as_settings.append({"uid": service_uid, "hidden": hidden}) # set the analysis services settings instance.setAnalysisServicesSettings(as_settings) # This returns the value for the Analyses Schema Field return value, {}
def folderitem(self, obj, item, index): """Applies new properties to item (StorageContainer) that is currently being rendered as a row in the list """ item = super(ContainersView, self).folderitem(obj, item, index) # Containers/Positions usage # Samples containers cannot have containers inside! if not IStorageSamplesContainer.providedBy(obj): capacity = obj.get_capacity() taken = len(obj.get_non_available_positions()) percentage = capacity and taken*100/capacity or 0 item["replace"]["ContainersUsage"] = get_progress_bar_html(percentage) item["replace"]["Containers"] = "{:01d} / {:01d} ({:01d}%)"\ .format(taken, capacity, percentage) # append the UID of the primary AR as parent parent = api.get_uid(api.get_parent(obj)) item["parent"] = parent != api.get_uid(self.context) and parent or "" # append partition UIDs of this AR as children containers = obj.get_layout_containers() item["children"] = map(lambda cont: api.get_uid(cont), containers) return item
def get_attachment_info(self, attachment): """Returns a dictionary of attachment information """ attachment_uid = api.get_uid(attachment) attachment_file = attachment.getAttachmentFile() attachment_type = attachment.getAttachmentType() attachment_icon = attachment_file.icon if callable(attachment_icon): attachment_icon = attachment_icon() return { 'keywords': attachment.getAttachmentKeys(), 'size': self.get_attachment_size(attachment), 'name': attachment_file.filename, 'Icon': attachment_icon, 'type': api.get_uid(attachment_type) if attachment_type else '', 'absolute_url': attachment.absolute_url(), 'UID': attachment_uid, 'report_option': attachment.getReportOption(), 'analysis': '', }
def isItemAllowed(self, obj): """Returns true if the current analysis to be rendered has a slot assigned for the current layout. :param obj: analysis to be rendered as a row in the list :type obj: ATContentType/DexterityContentType :return: True if the obj has an slot assigned. Otherwise, False. :rtype: bool """ uid = api.get_uid(obj) if not self.get_item_slot(uid): logger.warning("Slot not assigned to item %s" % uid) return False return BaseView.isItemAllowed(self, obj)
def get_samples_data(self): """Returns a list of AR data """ for obj in self.get_objects_from_request(): obj = api.get_object(obj) yield { "obj": obj, "id": api.get_id(obj), "uid": api.get_uid(obj), "title": api.get_title(obj), "path": api.get_path(obj), "url": api.get_url(obj), "sample_type": api.get_title(obj.getSampleType()) }
def add_filter_by_client(self, query, out_params): """Applies the filter by client to the search query """ current_client = logged_in_client(self.context) if current_client: query['getClientUID'] = api.get_uid(current_client) elif self.request.form.get("ClientUID", ""): query['getClientUID'] = self.request.form['ClientUID'] client = api.get_object_by_uid(query['getClientUID']) out_params.append({ 'title': _('Client'), 'value': client.Title(), 'type': 'text' })
def _getMethodsVoc(self): """Return the registered methods as DisplayList """ methods = api.search( { "portal_type": "Method", "inactive_state": "active" }, "bika_setup_catalog") items = map(lambda m: (api.get_uid(m), api.get_title(m)), methods) items.sort(lambda x, y: cmp(x[1], y[1])) items.insert(0, ("", _("Not specified"))) return DisplayList(list(items))
def folderitem(self, obj, item, index): """Service triggered each time an item is iterated in folderitems. The use of this service prevents the extra-loops in child objects. :obj: the instance of the class to be foldered :item: dict containing the properties of the object to be used by the template :index: current index of the item """ # ensure we have an object and not a brain obj = api.get_object(obj) uid = api.get_uid(obj) url = api.get_url(obj) title = api.get_title(obj) # get the category if self.show_categories_enabled(): category = obj.getCategoryTitle() if category not in self.categories: self.categories.append(category) item["category"] = category rr = self.referenceresults.get(uid, {}) item["Title"] = title item["replace"]["Title"] = get_link(url, value=title) item["allow_edit"] = self.get_editable_columns() item["required"] = self.get_required_columns() item["selected"] = rr and True or False item["result"] = rr.get("result", "") item["min"] = rr.get("min", "") item["max"] = rr.get("max", "") item["error"] = rr.get("error", "") # Icons after_icons = "" if obj.getAccredited(): after_icons += get_image( "accredited.png", title=_("Accredited")) if obj.getAttachmentOption() == "r": after_icons += get_image( "attach_reqd.png", title=_("Attachment required")) if obj.getAttachmentOption() == "n": after_icons += get_image( "attach_no.png", title=_("Attachment not permitted")) if after_icons: item["after"]["Title"] = after_icons return item
def get_base_info(self, obj): """Extract the base info from the given object """ review_state = api.get_workflow_status_of(obj) state_title = review_state.capitalize().replace("_", " ") return { "obj": obj, "id": api.get_id(obj), "uid": api.get_uid(obj), "title": api.get_title(obj), "path": api.get_path(obj), "url": api.get_url(obj), "review_state": review_state, "state_title": state_title, }
def _transition_cache_key(fun, obj, action): """Cache key generator for the request cache This function generates cache keys like this: >>> from bika.lims import api >>> from zope.annotation.interfaces import IAnnotations >>> request = api.get_request() >>> IAnnotations(request) # noqa: E501 {'bika.lims.workflow.analysis.guards.check_analysis_allows_transition:3ff02762c70f4a56b1b30c1b74d32bf6-retract': True, 'bika.lims.workflow.analysis.guards.check_analysis_allows_transition:0390c16ddec14a04b87ff8408e2aa229-retract': True, ... } """ return "%s-%s" % (api.get_uid(obj), action)
def get_samples_data(self): """Returns a list of Samples data (dictionary) """ for obj in self.get_samples_from_request(): yield { "obj": obj, "id": api.get_id(obj), "uid": api.get_uid(obj), "title": api.get_title(obj), "path": api.get_path(obj), "url": api.get_url(obj), "sample_type": obj.getSampleTypeTitle(), "client_title": obj.getClientTitle(), "date": ulocalized_time(obj.created(), long_format=True), }
def __call__(self): plone.protect.CheckAuthenticator(self.request) searchTerm = 'searchTerm' in self.request and self.request[ 'searchTerm'].lower() or '' page = self.request['page'] nr_rows = self.request['rows'] sord = self.request['sord'] sidx = self.request['sidx'] rows = [] query = dict(portal_type="Doctor", inactive_state="active") client = self.get_current_client() if client: # Search those Doctors that are assigned to the same client or # that do not have any client assigned query["getPrimaryReferrerUID"] = [api.get_uid(client), None] doctors = api.search(query, 'portal_catalog') for doctor in doctors: doctor_id = doctor.id doctor_title = doctor.Title search_val = ('{} {}'.format(doctor_id, doctor_title)).lower() if searchTerm not in search_val: continue rows.append({ 'Title': doctor.Title() or '', 'DoctorID': doctor.getDoctorID(), 'DoctorSysID': doctor.id, 'DoctorUID': doctor.UID() }) rows = sorted(rows, cmp=lambda x, y: cmp(x.lower(), 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 ret = { 'pages': page, 'total': pages, 'records': len(rows), 'rows': rows[(int(page) - 1) * int(nr_rows):int(page) * int(nr_rows)] } return json.dumps(ret)
def workflow_action_create_partitions(self): """Redirects the user to the partition magic view """ uids = list() if IAnalysisRequest.providedBy(self.context): uids = [api.get_uid(self.context)] else: uids = self.get_selected_uids() if not uids: message = "No items selected".format(repr(type(self.context))) self.redirect(message=message, level="error") # Redirect to the partitioning magic view url = "{}/partition_magic?uids={}".format(self.back_url, ",".join(uids)) self.redirect(redirect_url=url)
def getResultRange(self, values, uid_keyword_service): if not uid_keyword_service: return None if api.is_object(uid_keyword_service): uid_keyword_service = api.get_uid(uid_keyword_service) key = "keyword" if api.is_uid(uid_keyword_service) and uid_keyword_service != "0": # We always assume a uid of "0" refers to portal key = "uid" # Find out the item for the given uid/keyword from bika.lims.content.analysisspec import ResultsRangeDict value = filter(lambda v: v.get(key) == uid_keyword_service, values) return value and ResultsRangeDict(dict(value[0].items())) or None
def handle_submit(self): """Handle form submission """ wst_uid = self.request.form.get("getWorksheetTemplate") if not wst_uid: return False layout = self.context.getLayout() wst = api.get_object_by_uid(wst_uid) self.request["context_uid"] = api.get_uid(self.context) self.context.applyWorksheetTemplate(wst) if len(self.context.getLayout()) == len(layout): return False return True
def get_item_info(self, brain_or_object): """Return the data of this brain or object """ portal_type = api.get_portal_type(brain_or_object) state = api.get_workflow_status_of(brain_or_object) return { "obj": brain_or_object, "uid": api.get_uid(brain_or_object), "url": api.get_url(brain_or_object), "id": api.get_id(brain_or_object), "title": api.get_title(brain_or_object), "portal_type": api.get_portal_type(brain_or_object), "review_state": state, "state_title": self.translate_review_state(state, portal_type), "state_class": "state-{}".format(state), }
def create_report(self, parent, pdf, html, uids, metadata, csv_text=None): """Create a new report object NOTE: We limit the creation of reports to 1 to avoid conflict errors on simultaneous publication. :param parent: parent object where to create the report inside :returns: ARReport """ parent_id = api.get_id(parent) logger.info("Create Report for {} ...".format(parent_id)) # Manually update the view on the database to avoid conflict errors parent._p_jar.sync() query = { 'portal_type': 'ARReport', 'path': { 'query': api.get_path(parent), 'depth': 1 } } brains = api.search(query, 'portal_catalog') coa_num = '{}-COA-{}'.format(parent_id, len(brains) + 1) # Create the report object report = api.create(parent, "ARReport", AnalysisRequest=api.get_uid(parent), Pdf=pdf, Html=html, CSV=csv_text, ContainedAnalysisRequests=uids, Metadata=metadata) fld = report.getField('Pdf') fld.get(report).setFilename(coa_num + ".pdf") fld.get(report).setContentType('application/pdf') fld = report.getField('CSV') fld.get(report).setFilename(coa_num + ".csv") fld.get(report).setContentType('text/csv') # Commit the changes transaction.commit() logger.info("Create Report for {} [DONE]".format(parent_id)) return report
def __init__(self, name, request, context, *arg, **kw): super(QueueTask, self).__init__(*arg, **kw) if api.is_uid(context): context_uid = context context_path = kw.get("context_path") if not context_path: raise ValueError("context_path is missing") elif api.is_object(context): context_uid = api.get_uid(context) context_path = api.get_path(context) else: raise TypeError("No valid context object") # Set defaults kw = kw or {} task_uid = str(kw.get("task_uid", tmpID())) uids = map(str, kw.get("uids", [])) created = api.to_float(kw.get("created"), default=time.time()) status = kw.get("status", None) min_sec = api.to_int(kw.get("min_seconds"), default=get_min_seconds()) max_sec = api.to_int(kw.get("max_seconds"), default=get_max_seconds()) priority = api.to_int(kw.get("priority"), default=10) retries = api.to_int(kw.get("retries"), default=get_max_retries()) unique = self._is_true(kw.get("unique", False)) chunks = api.to_int(kw.get("chunk_size"), default=get_chunk_size(name)) username = kw.get("username", self._get_authenticated_user(request)) err_message = kw.get("error_message", None) self.update({ "task_uid": task_uid, "name": name, "context_uid": context_uid, "context_path": context_path, "uids": uids, "created": created, "status": status and str(status) or None, "error_message": err_message and str(err_message) or None, "min_seconds": min_sec, "max_seconds": max_sec, "priority": priority, "retries": retries, "unique": unique, "chunk_size": chunks, "username": str(username), })
def __call__(self, context): """Returns a SimpleVocabulary of antibiotic classes """ query = { "portal_type": "AntibioticClass", "is_active": True, "sort_on": "sortable_title", "sort_order": "ascending", } items = [] brains = api.search(query, SETUP_CATALOG) for brain in brains: uid = api.get_uid(brain) title = api.get_title(brain) items.append(SimpleTerm(uid, uid, title)) return SimpleVocabulary(items)
def link_version(self, source, target): """Link the current version of the target on the source """ if not hasattr(target, VERSION_ID): # no initial version of this object! logger.warn("No iniatial version found for '{}'".format( repr(target))) return if not hasattr(source, REFERENCE_VERSIONS): source.reference_versions = {} target_uid = api.get_uid(target) # store the current version of the target on the source source.reference_versions[target_uid] = target.version_id # persist changes that occured referenced versions source._p_changed = 1
def _folder_item_fieldicons(self, analysis_brain): """Resolves if field-specific icons must be displayed for the object passed in. :param analysis_brain: Brain that represents an analysis """ full_obj = self.get_object(analysis_brain) uid = api.get_uid(full_obj) for name, adapter in getAdapters((full_obj, ), IFieldIcons): alerts = adapter() if not alerts or uid not in alerts: continue alerts = alerts[uid] if uid not in self.field_icons: self.field_icons[uid] = alerts continue self.field_icons[uid].extend(alerts)
def add_analysis(self, instance, service, **kwargs): service_uid = api.get_uid(service) # Ensure we have suitable parameters specs = kwargs.get("specs") or {} # Get the hidden status for the service hidden = kwargs.get("hidden") or [] hidden = filter(lambda d: d.get("uid") == service_uid, hidden) hidden = hidden and hidden[0].get("hidden") or service.getHidden() # Get the price for the service prices = kwargs.get("prices") or {} price = prices.get(service_uid) or service.getPrice() # Gets the analysis or creates the analysis for this service # Note this returns a list, because is possible to have multiple # partitions with same analysis analyses = self.resolve_analyses(instance, service) if not analyses: # Create the analysis keyword = service.getKeyword() logger.info("Creating new analysis '{}'".format(keyword)) analysis = create_analysis(instance, service) analyses.append(analysis) skip = ["cancelled", "retracted", "rejected"] for analysis in analyses: # Skip analyses to better not modify if api.get_review_status(analysis) in skip: continue # Set the hidden status analysis.setHidden(hidden) # Set the price of the Analysis analysis.setPrice(price) # Set the internal use status parent_sample = analysis.getRequest() analysis.setInternalUse(parent_sample.getInternalUse()) # Set the result range to the analysis analysis_rr = specs.get(service_uid) or analysis.getResultsRange() analysis.setResultsRange(analysis_rr) analysis.reindexObject()
def after_retract(analysis): """Function triggered after a 'retract' transition for the analysis passed in is performed. The analysis transitions to "retracted" state and a new copy of the analysis is created. The copy initial state is "unassigned", unless the the retracted analysis was assigned to a worksheet. In such case, the copy is transitioned to 'assigned' state too """ # Retract our dependents (analyses that depend on this analysis) cascade_to_dependents(analysis, "retract") # Retract our dependencies (analyses this analysis depends on) promote_to_dependencies(analysis, "retract") # Rename the analysis to make way for it's successor. # Support multiple retractions by renaming to *-0, *-1, etc parent = analysis.aq_parent keyword = analysis.getKeyword() # Get only those that are analyses and with same keyword as the original analyses = parent.getAnalyses(full_objects=True) analyses = filter(lambda an: an.getKeyword() == keyword, analyses) # TODO This needs to get managed by Id server in a nearly future! new_id = '{}-{}'.format(keyword, len(analyses)) # Create a copy of the retracted analysis an_uid = api.get_uid(analysis) new_analysis = create_analysis(parent, analysis, id=new_id, RetestOf=an_uid) new_analysis.setResult("") new_analysis.setResultCaptureDate(None) new_analysis.reindexObject() logger.info("Retest for {} ({}) created: {}".format( keyword, api.get_id(analysis), api.get_id(new_analysis))) # Assign the new analysis to this same worksheet, if any. worksheet = analysis.getWorksheet() if worksheet: worksheet.addAnalysis(new_analysis) # Try to rollback the Analysis Request if IRequestAnalysis.providedBy(analysis): doActionFor(analysis.getRequest(), "rollback_to_receive") reindex_request(analysis)
def before_render(self): """Called before the listing renders """ super(PatientBatchListingViewAdapter, self).before_render() # Hide patient columns self.listing.columns['getPatientID']['toggle'] = False self.listing.columns['getClientPatientID']['toggle'] = False self.listing.columns['Patient']['toggle'] = False # Filter by patient query = dict(getPatientUID=api.get_uid(self.context)) self.listing.contentFilter.update(query) for rv in self.listing.review_states: if "contentFilter" not in rv: rv["contentFilter"] = {} rv["contentFilter"].update(query)
def searchable_text(instance): """ Retrieves all the values of metadata columns in the catalog for wildcard searches :return: all metadata values joined in a string """ entries = [] catalog = api.get_tool(CATALOG_PATIENTS) columns = catalog.schema() brains = catalog({"UID": api.get_uid(instance)}) brain = brains[0] if brains else None for column in columns: brain_value = api.safe_getattr(brain, column, None) instance_value = api.safe_getattr(instance, column, None) parsed = api.to_searchable_text_metadata(brain_value or instance_value) entries.append(parsed) # Concatenate all strings to one text blob return " ".join(entries)
def getResultsRange(self): """Return the AR Specs sorted by Service UID, so that the JS can work easily with the values. """ rr_dict_by_service_uid = {} rr = self.context.getResultsRange() for r in rr: uid = r.get("uid", None) if not uid: # get the AS by keyword keyword = r.get("keyword") service = self.get_service_by_keyword(keyword, None) if service is not None: uid = api.get_uid(service) if uid: rr_dict_by_service_uid[uid] = r return json.dumps(rr_dict_by_service_uid)
def __call__(self): plone.protect.CheckAuthenticator(self.request) searchTerm = 'searchTerm' in self.request and self.request['searchTerm'].lower() or '' page = self.request['page'] nr_rows = self.request['rows'] sord = self.request['sord'] sidx = self.request['sidx'] rows = [] query = dict(portal_type="Doctor", is_active=True) client = self.get_current_client() if client: # Search those Doctors that are assigned to the same client or # that do not have any client assigned query["getPrimaryReferrerUID"] = [api.get_uid(client), None] doctors = api.search(query, 'portal_catalog') for doctor in doctors: doctor_id = doctor.id doctor_title = doctor.Title search_val = ('{} {}'.format(doctor_id, doctor_title)).lower() if searchTerm not in search_val: continue rows.append({'Title': doctor.Title() or '', 'DoctorID': doctor.getDoctorID(), 'DoctorSysID': doctor.id, 'DoctorUID': doctor.UID()}) rows = sorted(rows, cmp=lambda x, y: cmp(x.lower(), 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 ret = {'pages': page, 'total': pages, 'records': len(rows), 'rows': rows[(int(page) - 1) * int(nr_rows): int(page) * int(nr_rows)]} return json.dumps(ret)
def __call__(self): mtool = getToolByName(self.context, 'portal_membership') can_add_doctors = mtool.checkPermission(AddDoctor, self.context) if can_add_doctors: add_doctors_url = '{}/doctors/createObject?type_name=Doctor' \ .format(self.portal_url) self.context_actions[_('Add')] = { 'url': add_doctors_url, 'icon': '++resource++bika.lims.images/add.png' } if mtool.checkPermission(ManageDoctors, self.context): self.review_states[0]['transitions'].append({'id':'deactivate'}) self.review_states.append( {'id':'inactive', 'title': _('Dormant'), 'contentFilter': {'is_active': False}, 'transitions': [{'id':'activate'}, ], 'columns': self.columns.keys()}) self.review_states.append( {'id':'all', 'title': _('All'), 'contentFilter':{}, 'transitions':[{'id':'empty'}], 'columns': self.columns.keys()}) stat = self.request.get("%s_review_state"%self.form_id, 'default') self.show_select_column = stat != 'all' # If the current context is a Client, filter Doctors by Client UID if IClient.providedBy(self.context): client_uid = api.get_uid(self.context) self.contentFilter['getPrimaryReferrerUID'] = client_uid # If the current user is a client contact, do not display the doctors # assigned to other clients elif self.get_user_client_uid(): client_uid = self.get_user_client_uid() self.contentFilter['getPrimaryReferrerUID'] = [client_uid, None] return super(DoctorsView, self).__call__()
def __call__(self, value, *args, **kwargs): context = kwargs['instance'] uid = api.get_uid(context) field = kwargs['field'] fieldname = field.getName() translate = getToolByName(context, 'translation_service').translate # return directly if nothing changed if value == field.get(context): return True # Fetch the parent object candidates by catalog or by objectValues # # N.B. We want to use the catalog to speed things up, because using # `parent.objectValues` is very expensive if the parent object contains # many items and causes the UI to block too long catalog_query = self.make_catalog_query(context, field, value) parent_objects = self.query_parent_objects( context, query=catalog_query) for item in parent_objects: if hasattr(item, 'UID') and item.UID() != uid and \ fieldname in item.Schema() and \ str(item.Schema()[fieldname].get(item)) == str(value).strip(): # We have to compare them as strings because # even if a number (as an id) is saved inside # a string widget and string field, it will be # returned as an int. I don't know if it is # caused because is called with # <item.Schema()[fieldname].get(item)>, # but it happens... msg = _( "Validation failed: '${value}' is not unique", mapping={ 'value': safe_unicode(value) }) return to_utf8(translate(msg)) return True
def remove_service(self, service): """Removes the service passed in from the services offered by the current Template. If the Analysis Service passed in is not assigned to this Analysis Template, returns False. :param service: the service to be removed from this AR Template :type service: AnalysisService :return: True if the AnalysisService has been removed successfully """ uid = api.get_uid(service) # Remove the service from the referenced services services = self.getAnalyses() num_services = len(services) services = [item for item in services if item.get('service_uid', '') != uid] removed = len(services) < num_services self.setAnalyses(services) # Remove the service from the settings map settings = self.getAnalysisServicesSettings() settings = [item for item in settings if item.get('uid', '') != uid] self.setAnalysisServicesSettings(settings) return removed
def get_uid(brain_or_object): """Proxy to bika.lims.api.get_uid """ return api.get_uid(brain_or_object)