示例#1
0
 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
示例#2
0
 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
示例#3
0
    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)
示例#4
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"}
            }
示例#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')
示例#6
0
文件: folder.py 项目: xispa/bika.lims
    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)
示例#7
0
 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
示例#8
0
 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
示例#9
0
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"
示例#10
0
 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)
示例#11
0
    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)
示例#12
0
 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))
示例#13
0
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()
示例#14
0
 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)
示例#15
0
    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
示例#16
0
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")
示例#17
0
 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)))
示例#18
0
 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)
示例#19
0
    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,
        }
示例#20
0
 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, {}
示例#22
0
    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
示例#23
0
    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': '',
        }
示例#24
0
    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)
示例#25
0
 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())
         }
示例#26
0
 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'
         })
示例#27
0
    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))
示例#28
0
    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
示例#29
0
 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,
     }
示例#30
0
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)
示例#31
0
 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),
         }
示例#32
0
    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)
示例#33
0
    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)
示例#34
0
    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
示例#35
0
    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
示例#36
0
 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),
     }
示例#37
0
    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
示例#38
0
    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),
        })
示例#39
0
    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)
示例#40
0
    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
示例#41
0
    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)
示例#42
0
    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()
示例#43
0
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)
示例#44
0
    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)
示例#45
0
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)
示例#46
0
    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)
示例#47
0
    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)
示例#48
0
    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__()
示例#49
0
    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
示例#50
0
    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
示例#51
0
def get_uid(brain_or_object):
    """Proxy to bika.lims.api.get_uid
    """
    return api.get_uid(brain_or_object)