Exemple #1
0
def search_analysis_container(container_ids):
    """Searches an analysis container (Sample or Worksheet) for the id. The
     priority for searches is as follows: Sample ID, Worksheet ID, Client
     Sample ID
    """
    # Try by Sample ID (only received samples can be submitted)
    query = dict(portal_type="AnalysisRequest",
                 getId=container_ids,
                 review_state="sample_received")
    sample = api.search(query, CATALOG_ANALYSIS_REQUEST_LISTING)
    if sample:
        return api.get_object(sample[0])

    # Try by Worksheet ID (only open worksheets)
    query = dict(portal_type="Worksheet",
                 review_state="open",
                 getId=container_ids)
    worksheet = api.search(query, CATALOG_WORKSHEET_LISTING)
    if worksheet:
        return api.get_object(worksheet[0])

    # Try by Client Sample ID
    query = dict(portal_type="AnalysisRequest",
                 getClientSampleID=container_ids,
                 review_state="sample_received")
    sample = api.search(query, CATALOG_ANALYSIS_REQUEST_LISTING)
    if sample:
        return api.get_object(sample[0])

    return None
def to_service_uid(uid_brain_obj_str):
    """Resolves the passed in element to a valid uid. Returns None if the value
    cannot be resolved to a valid uid
    """
    if api.is_uid(uid_brain_obj_str) and uid_brain_obj_str != "0":
        return uid_brain_obj_str

    if api.is_object(uid_brain_obj_str):
        obj = api.get_object(uid_brain_obj_str)

        if IAnalysisService.providedBy(obj):
            return api.get_uid(obj)

        elif IRoutineAnalysis.providedBy(obj):
            return obj.getServiceUID()

        else:
            logger.error("Type not supported: {}".format(obj.portal_type))
            return None

    if isinstance(uid_brain_obj_str, six.string_types):
        # Maybe is a keyword?
        query = dict(portal_type="AnalysisService",
                     getKeyword=uid_brain_obj_str)
        brains = api.search(query, SETUP_CATALOG)
        if len(brains) == 1:
            return api.get_uid(brains[0])

        # Or maybe a title
        query = dict(portal_type="AnalysisService", title=uid_brain_obj_str)
        brains = api.search(query, SETUP_CATALOG)
        if len(brains) == 1:
            return api.get_uid(brains[0])

    return None
Exemple #3
0
 def search(self, query):
     """search the catalog
     """
     logger.info("Catalog query={}".format(query))
     # Support to set the catalog as a request parameter
     catalogs = _.to_list(req.get("catalog", None))
     if catalogs:
         return senaiteapi.search(query, catalog=catalogs)
     # Delegate to the search API of Bika LIMS
     return senaiteapi.search(query)
Exemple #4
0
def update_rejection_permissions(portal):
    """Adds the permission 'Reject Analysis Request' and update the permission
     mappings accordingly """
    updated = update_rejection_permissions_for(portal, "bika_ar_workflow",
                                               "Reject Analysis Request")
    if updated:
        brains = api.search(dict(portal_type="AnalysisRequest"),
                            CATALOG_ANALYSIS_REQUEST_LISTING)
        update_rolemappings_for(brains, "bika_ar_workflow")

    updated = update_rejection_permissions_for(portal, "bika_sample_workflow",
                                               "Reject Sample")
    if updated:
        brains = api.search(dict(portal_type="Sample"), "bika_catalog")
        update_rolemappings_for(brains, "bika_sample_workflow")
    def returnBills(self):
        """Create's user for patient to login
        """

        aRequest_query_results = api.search({"portal_type": "AnalysisRequest","Complete":True})
        logger.info("Results: {0}".format(len(aRequest_query_results)))

        response = {'status': 'processed'}
        results = []

        if len(aRequest_query_results) > 0:

            for sample_r in aRequest_query_results:
                sample = api.get_object(sample_r)
                sample_object  = {}

                try:
                    sample_object['title'] = sample.Title()
                    sample_object['subtotal'] = sample.getSubtotal()
                    # logger.info('{0}: {1}'.format(sample.Title(),sample.getSubtotal()))
                except Exception as e:
                    logger.info("Failed to get sample object properties {0}".format(e))

                results.append(sample_object)
        
        if len(results) > 0:
            response.update({'status': 'success'})
        
        response.update({'results':results})

        return response
    def __call__(self):
        parms = []

        # Base query
        query = dict(portal_type="Analysis", sort_on='getClientTitle')

        # Filter by client
        self.add_filter_by_client(query, parms)

        # Filter by date
        self.add_filter_by_date(query, parms)

        # Filter analyses by review_state
        self.add_filter_by_review_state(query, parms)

        # Filter analyses by cancellation state
        self.add_filter_by_cancellation_state(query, parms)

        # Fetch and fill data
        data = OrderedDict()
        analyses = api.search(query, CATALOG_ANALYSIS_LISTING)
        total_num_analyses = len(analyses)
        total_num_ars = 0
        for analysis in analyses:
            client = analysis.getClientTitle
            data_client = data.get(client, {})
            request = analysis.getRequestID
            requests = data_client.get("requests", [])
            if request not in requests:
                requests += [request]
                data_client["requests"] = requests
                total_num_ars += 1
            data_client["analyses"] = data_client.get("analyses", 0) + 1
            data[client] = data_client

        # Generate datalines
        data_lines = list()
        for client, data in data.items():
            ars_count = len(data.get('requests', []))
            ans_count = data.get('analyses', 0)
            data_lines.append([{"value": client},
                               {"value": ars_count},
                               {"value": ans_count}])

        if self.request.get('output_format', '') == 'CSV':
            return self.generate_csv(data_lines)

        self.report_content = {
            'headings': self.headings,
            'parms': parms,
            'formats': self.formats,
            'datalines': data_lines,
            'footings': [
                [{'value': _('Total'), 'class': 'total_label'},
                 {'value': total_num_ars},
                 {'value': total_num_analyses},],]
        }

        return {'report_title': t(self.headings['header']),
                'report_data': self.template()}
Exemple #7
0
    def resume(self):
        """Resumes the pool and reindex all objects processed
        """
        self.num_calls -= 1
        if self.num_calls > 0:
            return
        logger.info("Resume actions for {} objects".format(len(self)))

        # Fetch the objects from the pool
        processed = list()
        for brain in api.search(dict(UID=self.objects.keys()), UID_CATALOG):
            uid = api.get_uid(brain)
            if uid in processed:
                # This object has been processed already, do nothing
                continue

            # Reindex the object
            obj = api.get_object(brain)
            idxs = self.get_indexes(uid)
            idxs_str = idxs and ', '.join(idxs) or "-- All indexes --"
            logger.info("Reindexing {}: {}".format(obj.getId(), idxs_str))
            obj.reindexObject(idxs=idxs)
            processed.append(uid)

        # Cleanup the pool
        logger.info("Objects processed: {}".format(len(processed)))
        self.objects = collections.OrderedDict()
Exemple #8
0
def reindex_client_fields(portal):
    logger.info("Reindexing client fields ...")
    fields_to_reindex = [
        "getClientUID",
        "getClientID",
        "getClientTitle",
        "getClientURL"
    ]

    # We only need to reindex those that might be associated to a Client object.
    # There is no need to reindex objects that already belong to a Client.
    # Batches were correctly indexed in previous upgrade step
    portal_types = [
        "AnalysisProfile",
        "AnalysisSpec",
        "ARTemplate",
        "SamplePoint"
    ]

    query = dict(portal_type=portal_types)
    brains = api.search(query, UID_CATALOG)
    total = len(brains)
    for num, brain in enumerate(brains):
        if num and num % 100 == 0:
            logger.info("Reindexing client fields: {}/{}".format(num, total))

        obj = api.get_object(brain)
        obj.reindexObject(idxs=fields_to_reindex)

    logger.info("Reindexing client fields ... [DONE]")
Exemple #9
0
def reindex_supplier_manufacturers_titles(portal):
    logger.info("Reindexing title indexes for Suppliers and Manufacturers ...")
    query = dict(portal_type="Supplier")
    for brain in api.search(query, SETUP_CATALOG):
        obj = api.get_object(brain)
        obj.reindexObject(idxs=["title", "sortable_title"])
    logger.info("Reindexing title indexes for Suppliers and Manufacturers ... [DONE]")
Exemple #10
0
    def get_methods_vocabulary(self, analysis_brain):
        """Returns a vocabulary with all the methods available for the passed in
        analysis, either those assigned to an instrument that are capable to
        perform the test (option "Allow Entry of Results") and those assigned
        manually in the associated Analysis Service.

        The vocabulary is a list of dictionaries. Each dictionary has the
        following structure:

            {'ResultValue': <method_UID>,
             'ResultText': <method_Title>}

        :param analysis_brain: A single Analysis brain
        :type analysis_brain: CatalogBrain
        :returns: A list of dicts
        """
        uids = analysis_brain.getAllowedMethodUIDs
        query = {
            'portal_type': 'Method',
            'inactive_state': 'active',
            'UID': uids
        }
        brains = api.search(query, 'bika_setup_catalog')
        if not brains:
            return [{'ResultValue': '', 'ResultText': _('None')}]
        return map(
            lambda brain: {
                'ResultValue': brain.UID,
                'ResultText': brain.Title
            }, brains)
Exemple #11
0
    def getInstruments(self):
        """Get the allowed instruments
        """
        query = {"portal_type": "Instrument", "inactive_state": "active"}

        if self.getRestrictToMethod():
            query.update({
                "getMethodUIDs": {
                    "query": api.get_uid(self.getRestrictToMethod()),
                    "operator": "or",
                }
            })

        instruments = api.search(query, "bika_setup_catalog")
        items = map(lambda i: (i.UID, i.Title), instruments)

        instrument = self.getInstrument()
        if instrument:
            instrument_uids = map(api.get_uid, instruments)
            if api.get_uid(instrument) not in instrument_uids:
                items.append(
                    (api.get_uid(instrument), api.get_title(instrument)))

        items.sort(lambda x, y: cmp(x[1], y[1]))
        items.insert(0, ("", _("No instrument")))

        return DisplayList(list(items))
Exemple #12
0
    def reset_samples_usage(self, recursive=True):
        """Resets the sample usage values (capacity and utilization) for this
        container. It looks through all children to reset the values.
        If recursive is set to True, the function reset the samples usage for
        contained containers too.
        """
        items = filter(self.is_taken, self.getPositionsLayout())
        items = map(lambda item: item.get["uid"], items)
        uids = filter(api.is_uid, items)
        if not uids:
            return

        query = dict(UID=uids)
        uids_usage = {}
        for brain in api.search(query, "uid_catalog"):
            obj = api.get_object(brain)
            if not IStorageLayoutContainer.providedBy(obj):
                continue
            if recursive:
                obj.reset_samples_usage(recursive=recursive)
            uids_usage[api.get_uid(obj)] = {
                "samples_utilization": obj.get_samples_utilization(),
                "samples_capacity": obj.get_samples_capacity()
            }

        new_items = list()
        for layout_item in self.getPositionsLayout():
            item = layout_item.copy()
            usage = uids_usage.get(item.get("uid"), None)
            if usage:
                item.update(usage)
            new_items.append(item)
        self.setPositionsLayout(new_items)
Exemple #13
0
def search_analysis_from(container, keywords):
    """Searches an analysis with the specified keyword within the container
    """
    # Base query
    query = dict(getKeyword=keywords,
                 portal_type="Analysis",
                 review_state=["unassigned", "assigned"])

    # Build the query
    container = api.get_object(container)
    container_uid = api.get_uid(container)
    if IAnalysisRequest.providedBy(container):
        query.update({"getAncestorsUIDs": container_uid})

    elif IWorksheet.providedBy(container):
        query.update({"getWorksheetUID": container_uid})

    else:
        path = api.get_path(container)
        raise ValueError("Could not get analyses from {}".format(path))

    # Search for a unique result
    analyses = api.search(query, CATALOG_ANALYSIS_LISTING)
    if len(analyses) == 1:
        return api.get_object(analyses[0])

    return None
    def get_sample_container_info(self):
        """Returns the storage container this Sample is stored in
        """
        # Search the container the sample is stored in
        query = {
            "portal_type": "StorageSamplesContainer",
            "get_samples_uids": api.get_uid(self.context)
        }
        brains = api.search(query, SENAITE_STORAGE_CATALOG)
        if not brains:
            return None

        # Get the data info from the container
        container = api.get_object(brains[0])
        position = container.get_object_position(self.context)
        position = container.position_to_alpha(position[0], position[1])
        return {
            "uid": api.get_uid(container),
            "id": api.get_id(container),
            "title": api.get_title(container),
            "url": api.get_url(container),
            "position": position,
            "full_title": container.get_full_title(),
            "when": wf.getTransitionDate(self.context, "store"),
        }
Exemple #15
0
def decouple_analyses_from_sample_workflow(portal):
    logger.info("Decoupling analyses from sample workflow ...")
    add_index(portal,
              catalog_id=CATALOG_ANALYSIS_LISTING,
              index_name="isSampleReceived",
              index_attribute="isSampleReceived",
              index_metatype="BooleanIndex")

    wf_id = "bika_analysis_workflow"
    affected_rs = [
        "sample_registered", "to_be_sampled", "sampled", "sample_due",
        "sample_received", "to_be_preserved", "not_requested", "registered"
    ]
    wf_tool = api.get_tool("portal_workflow")
    workflow = wf_tool.getWorkflowById(wf_id)
    query = dict(portal_type=["Analysis", "DuplicateAnalysis"],
                 review_state=affected_rs)
    brains = api.search(query, CATALOG_ANALYSIS_LISTING)
    total = len(brains)
    for num, brain in enumerate(brains):
        # Set state
        analysis = api.get_object(brain)
        target_state = analysis.getWorksheet() and "assigned" or "unassigned"

        if num % 100 == 0:
            logger.info("Restoring state to '{}': {}/{}".format(
                target_state, num, total))

        changeWorkflowState(analysis, wf_id, target_state)

        # Update role mappings
        workflow.updateRoleMappingsFor(analysis)

        # Reindex
        analysis.reindexObject()
Exemple #16
0
 def get_sample_uids(self):
     """Returns the sample UIDs for which the current Doctor has at least
     one Analysis Request assigned."""
     query = dict(getDoctorUID=api.get_uid(self.context))
     ars = api.search(query, CATALOG_ANALYSIS_REQUEST_LISTING)
     uids = map(lambda brain: brain.getSampleUID, ars) or list()
     return list(set(uids))
Exemple #17
0
def remove_orphan_reference_analyses(portal):
    logger.info("Removing orphan reference analyses ...")
    wf_id = "bika_referenceanalysis_workflow"
    wf_tool = api.get_tool("portal_workflow")
    workflow = wf_tool.getWorkflowById(wf_id)
    query = dict(portal_type="ReferenceAnalysis", review_state="unassigned")
    brains = api.search(query, CATALOG_ANALYSIS_LISTING)
    total = len(brains)
    for num, brain in enumerate(brains):
        orphan = api.get_object(brain)
        worksheet = orphan.getWorksheet()
        if worksheet:
            logger.info("Reassigning orphan reference: {}/{}".format(
                num, total))
            # This one has a worksheet! reindex and do nothing
            changeWorkflowState(orphan, wf_id, "assigned")
            # Update role mappings
            workflow.updateRoleMappingsFor(orphan)
            # Reindex
            orphan.reindexObject()
            continue
        elif orphan.getInstrument():
            # This is a calibration test, do nothing!
            if not brain.getInstrumentUID:
                orphan.reindexObject()
            total -= 1
            continue

        if num % 100 == 0:
            logger.info("Removing orphan reference analysis: {}/{}".format(
                num, total))
        # Remove the duplicate
        orphan.aq_parent.manage_delObjects([orphan.getId()])
Exemple #18
0
 def get_ar(sample_id):
     query = dict(portal_type='AnalysisRequest', getId=sample_id)
     brains = api.search(query, CATALOG_ANALYSIS_REQUEST_LISTING)
     try:
         return api.get_object(brains[0])
     except IndexError:
         pass
Exemple #19
0
def _children_are_ready(obj, transition_id, dettached_states=None):
    """Returns true if the children of the object passed in (worksheet) have
    been all transitioned in accordance with the 'transition_id' passed in. If
    detached_states is provided, children with those states are dismissed, so
    they will not be taken into account in the evaluation. Nevertheless, at
    least one child with for which the transition_id performed is required for
    this function to return true (if all children are in detached states, it
    always return False).
    """
    query = dict(getWorksheetUID=api.get_uid(obj))
    brains = api.search(query, CATALOG_ANALYSIS_LISTING)
    if not brains:
        return False
    detached_count = 0

    for brain in brains:
        if dettached_states and brain.review_state in dettached_states:
            detached_count += 1
            # dismiss the brain and skip the rest of the checks
            continue
        if not api.is_active(brain):
            return False
        analysis = api.get_object(brain)
        if not wasTransitionPerformed(analysis, transition_id):
            return False

    if detached_count == len(brains):
        # If all brains are in a detached state, it means that the
        # condition of at least having one child for which the
        # transition is performed is not satisfied so return False
        return False
    return True
Exemple #20
0
    def _get_instruments_brains(self):
        """Returns all active Instruments

        :returns: list of brains
        """
        query = {"portal_type": "Instrument", "is_active": True}
        return api.search(query, "bika_setup_catalog")
Exemple #21
0
    def __call__(self):
        # Get the id of the action to be performed
        action = self.get_action()
        if not action:
            return self.redirect(message=_("No action defined."),
                                 level="error")

        # Get the UIDs of the objects the action needs to be done against
        uids = self.get_uids()
        if not uids:
            return self.redirect(message=_("No items selected."),
                                 level="warning")

        # Find out if there is an adapter registered for the current context
        # able to handle the requested action
        adapter_name = "workflow_action_{}".format(action)
        adapter = queryMultiAdapter((self.context, self.request),
                                    interface=IWorkflowActionAdapter,
                                    name=adapter_name)
        if not adapter:
            # No adapter found, use the generic one
            adapter = WorkflowActionGenericAdapter(self.context, self.request)
        else:
            adapter_module = adapter.__module__
            adapter_class = adapter.__class__.__name__
            logger.info("Action '{}' managed by {}.{}".format(
                action, adapter_module, adapter_class))

        # Handle the action
        if IWorkflowActionUIDsAdapter.providedBy(adapter):
            return adapter(action, uids)

        objects = api.search(dict(UID=uids), UID_CATALOG)
        objects = map(api.get_object, objects)
        return adapter(action, objects)
Exemple #22
0
def update_partitions_role_mappings(portal):
    """Updates the rolemappings for existing partitions that are in a suitable
     state, so they can be detached from the primary sample they belong to
    """
    logger.info("Updating role mappings of partitions ...")
    wf_tool = api.get_tool("portal_workflow")
    workflow = wf_tool.getWorkflowById("bika_ar_workflow")

    # States that allow detach transition as defined in workflow definition in
    # order to query and update role mappings of objects that matter
    allowed_states = [
        "to_be_preserved", "sample_due", "sample_received", "to_be_verified",
        "verified"
    ]
    query = dict(portal_type="AnalysisRequest",
                 isRootAncestor=False,
                 review_state=allowed_states)

    brains = api.search(query, CATALOG_ANALYSIS_REQUEST_LISTING)
    total = len(brains)
    for num, brain in enumerate(brains):
        if num and num % 100 == 0:
            logger.info("Updating role mappings of partitions: {}/{}".format(
                num, total))
        partition = api.get_object(brain)
        workflow.updateRoleMappingsFor(partition)
        partition.reindexObjectSecurity()

    logger.info("Updating role mappings of partitions [DONE]")
Exemple #23
0
def reindex_labcontact_sortable_title(portal):
    logger.info("Reindexing sortable_title for LabContacts ...")
    query = dict(portal_type="LabContact")
    for brain in api.search(query, SETUP_CATALOG):
        obj = api.get_object(brain)
        obj.reindexObject(idxs=["sortable_title"])
    logger.info("Reindexing sortable_title for LabContacts ... [DONE]")
Exemple #24
0
    def isQCValid(self):
        """ Returns True if the results of the last batch of QC Analyses
        performed against this instrument was within the valid range.

        For a given Reference Sample, more than one Reference Analyses assigned
        to this same instrument can be performed and the Results Capture Date
        might slightly differ amongst them. Thus, this function gets the latest
        QC Analysis performed, looks for siblings (through RefAnalysisGroupID)
        and if the results for all them are valid, then returns True. If there
        is one single Reference Analysis from the group with an out-of-range
        result, the function returns False
        """
        query = {
            "portal_type": "ReferenceAnalysis",
            "getInstrumentUID": self.UID(),
            "sort_on": "getResultCaptureDate",
            "sort_order": "reverse",
            "sort_limit": 1,
        }
        brains = api.search(query, CATALOG_ANALYSIS_LISTING)
        if len(brains) == 0:
            # There are no Reference Analyses assigned to this instrument yet
            return True

        # Look for siblings. These are the QC Analyses that were created
        # together with this last ReferenceAnalysis and for the same Reference
        # Sample. If they were added through "Add Reference Analyses" in a
        # Worksheet, they typically appear in the same slot.
        group_id = brains[0].getReferenceAnalysesGroupID
        query = {
            "portal_type": "ReferenceAnalysis",
            "getInstrumentUID": self.UID(),
            "getReferenceAnalysesGroupID": group_id,
        }
        brains = api.search(query, CATALOG_ANALYSIS_LISTING)
        for brain in brains:
            analysis = api.get_object(brain)
            results_range = analysis.getResultsRange()
            if not results_range:
                continue
            # Is out of range?
            out_of_range = is_out_of_range(analysis)[0]
            if out_of_range:
                return False

        # By default, in range
        return True
def setup_catalogs(portal):
    """Setup Plone catalogs
    """
    logger.info("*** Setup Catalogs ***")

    # Setup catalogs by type
    for type_name, catalogs in CATALOGS_BY_TYPE:
        at = api.get_tool("archetype_tool")
        # get the current registered catalogs
        current_catalogs = at.getCatalogsByType(type_name)
        # get the desired catalogs this type should be in
        desired_catalogs = map(api.get_tool, catalogs)
        # check if the catalogs changed for this portal_type
        if set(current_catalogs).difference(desired_catalogs):
            # fetch the brains to reindex
            brains = api.search({"portal_type": type_name})
            # updated the catalogs
            at.setCatalogsByType(type_name, catalogs)
            logger.info("*** Assign '%s' type to Catalogs %s" %
                        (type_name, catalogs))
            for brain in brains:
                obj = api.get_object(brain)
                logger.info("*** Reindexing '%s'" % repr(obj))
                obj.reindexObject()

    # Setup catalog indexes
    to_index = []
    for catalog, name, attribute, meta_type in INDEXES:
        c = api.get_tool(catalog)
        indexes = c.indexes()
        if name in indexes:
            logger.info("*** Index '%s' already in Catalog [SKIP]" % name)
            continue

        logger.info("*** Adding Index '%s' for field '%s' to catalog ..."
                    % (meta_type, name))
        c.addIndex(name, meta_type)
        to_index.append((c, name))
        logger.info("*** Added Index '%s' for field '%s' to catalog [DONE]"
                    % (meta_type, name))

    for catalog, name in to_index:
        logger.info("*** Indexing new index '%s' ..." % name)
        catalog.manage_reindexIndex(name)
        logger.info("*** Indexing new index '%s' [DONE]" % name)

    # Setup catalog metadata columns
    for catalog, name in COLUMNS:
        c = api.get_tool(catalog)
        if name not in c.schema():
            logger.info("*** Adding Column '%s' to catalog '%s' ..."
                        % (name, catalog))
            c.addColumn(name)
            logger.info("*** Added Column '%s' to catalog '%s' [DONE]"
                        % (name, catalog))
        else:
            logger.info("*** Column '%s' already in catalog '%s'  [SKIP]"
                        % (name, catalog))
            continue
Exemple #26
0
 def get_brain(self, uid, catalog):
     if not api.is_uid(uid):
         return None
     query = dict(UID=uid)
     brains = api.search(query, catalog)
     if brains and len(brains) == 1:
         return brains[0]
     return None
Exemple #27
0
 def getMethodsDisplayList(self):
     """Returns a display list with the active methods
     """
     query = dict(portal_type="Method", inactive_state="active")
     items = api.search(query, "bika_setup_catalog")
     items = map(lambda brain: (brain.UID, brain.Title), items)
     items.sort(lambda x, y: cmp(x[1], y[1]))
     return DisplayList(list(items))
Exemple #28
0
 def getBatches(self, full_objects=False):
     """Returns the Batches (Clinic Cases) this Patient is assigned to
     """
     query = dict(portal_type="Batch", getPatientUID=api.get_uid(self))
     batches = api.search(query, BIKA_CATALOG)
     if full_objects:
         return map(api.get_object, batches)
     return batches
Exemple #29
0
 def get_brain(self, uid, catalog):
     if not api.is_uid(uid):
         return None
     query = dict(UID=uid)
     brains = api.search(query, catalog)
     if brains and len(brains) == 1:
         return brains[0]
     return None
Exemple #30
0
def move_doctors_to_clients(portal):
    """Moves the doctors into their assigned Client, if any
    """
    logger.info("Moving Doctors inside Clients...")
    query = {"portal_type": "Doctor"}
    doctors = map(api.get_object, api.search(query, "portal_catalog"))
    map(move_doctor_to_client, doctors)
    logger.info("Moving Doctors inside Clients [DONE]")
Exemple #31
0
    def do_unassign(self, analysis_uids):
        actions = ActionHandlerPool.get_instance()
        actions.queue_pool()
        # Remove duplicates first
        query = dict(UID=analysis_uids, portal_type="DuplicateAnalysis")
        for brain in api.search(query, CATALOG_ANALYSIS_LISTING):
            doActionFor(api.get_object(brain), "unassign")
        # Now remove the rest
        query = dict(UID=analysis_uids)
        for brain in api.search(query, CATALOG_ANALYSIS_LISTING):
            doActionFor(api.get_object(brain), "unassign")
        actions.resume()

        message = _("Changes saved.")
        self.context.plone_utils.addPortalMessage(message, 'info')
        self.destination_url = self.context.absolute_url()
        self.request.response.redirect(self.destination_url)
Exemple #32
0
 def getBatches(self, full_objects=False):
     """
     Returns the Batches this Doctor is assigned to
     :return:
     """
     query = dict(portal_type='Batch', getDoctorUID=self.UID())
     brains = api.search(query, 'bika_catalog')
     if full_objects:
         return map(lambda brain: api.get_object(brain), brains)
     return brains
Exemple #33
0
 def getAnalysisRequests(self, full_objects=False):
     """
     Returns the Analysis Requests this Doctor is assigned to
     :return:
     """
     query = dict(portal_type='AnalysisRequest', getDoctorUID=self.UID())
     brains = api.search(query, CATALOG_ANALYSIS_REQUEST_LISTING)
     if full_objects:
         return map(lambda brain: api.get_object(brain), brains)
     return brains
Exemple #34
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)
Exemple #35
0
def search_catalogs(portal_type):
    """Returns brains which share the same portal_type
    """
    catalog_names = ['portal_catalog', 'bika_setup_catalog', 'bika_catalog']
    UIDs = []
    all_brains = []
    for catalog_name in catalog_names:
        catalog = api.get_tool(catalog_name)
        brains = api.search({"portal_type": portal_type}, catalog=catalog_name)
        for brain in brains:
            if brain.UID not in UIDs:
                all_brains.append(brain)
                UIDs.append(brain.UID)
    return all_brains
Exemple #36
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)
Exemple #37
0
def setup_patients_ownership(portal):
    """Set the role "Owner" to all the client contacts that belong to the same
    client as the patient, if any
    """
    logger.info("Applying Patients ownership ...")
    brains = api.search(dict(portal_type="Patient"), CATALOG_PATIENTS)
    total = len(brains)
    for num, brain in enumerate(brains):
        if num % 100 == 0:
            logger.info("Applying Patients Ownership {}/{}".format(num, total))
        purge_owners_for(api.get_object(brain))

        if num % 1000 == 0:
            commit_transaction()
    commit_transaction()
Exemple #38
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)
Exemple #39
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)
Exemple #40
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))
Exemple #41
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()
Exemple #42
0
def setup_catalogs(catalogs_by_type, indexes_by_catalog,
                   columns_by_catalog):
    """Setup Plone catalogs
    """
    logger.info("Setup Catalogs ...")

    # Setup catalogs by type
    for type_name, catalogs in catalogs_by_type:
        at = api.get_tool("archetype_tool")
        # get the current registered catalogs
        current_catalogs = at.getCatalogsByType(type_name)
        # get the desired catalogs this type should be in
        desired_catalogs = map(api.get_tool, catalogs)
        # check if the catalogs changed for this portal_type
        if set(desired_catalogs).difference(current_catalogs):
            # fetch the brains to reindex
            brains = api.search({"portal_type": type_name})
            # updated the catalogs
            at.setCatalogsByType(type_name, catalogs)
            logger.info("Assign '%s' type to Catalogs %s" %
                        (type_name, catalogs))
            for brain in brains:
                obj = api.get_object(brain)
                logger.info("Reindexing '%s'" % repr(obj))
                obj.reindexObject()

    # Setup catalog indexes
    to_index = []
    for catalog, name, meta_type in indexes_by_catalog:
        c = api.get_tool(catalog)
        indexes = c.indexes()
        if name in indexes:
            logger.info("Index '%s' already in Catalog [SKIP]" % name)
            continue

        logger.info("Adding Index '%s' for field '%s' to catalog '%s"
                    % (meta_type, name, catalog))
        if meta_type == "ZCTextIndex":
            addZCTextIndex(c, name)
        else:
            c.addIndex(name, meta_type)
        to_index.append((c, name))
        logger.info("Added Index '%s' for field '%s' to catalog [DONE]"
                    % (meta_type, name))

    for catalog, name in to_index:
        logger.info("Indexing new index '%s' ..." % name)
        catalog.manage_reindexIndex(name)
        logger.info("Indexing new index '%s' [DONE]" % name)

    # Setup catalog metadata columns
    for catalog, name in columns_by_catalog:
        c = api.get_tool(catalog)
        if name not in c.schema():
            logger.info("Adding Column '%s' to catalog '%s' ..."
                        % (name, catalog))
            c.addColumn(name)
            logger.info("Added Column '%s' to catalog '%s' [DONE]"
                        % (name, catalog))
        else:
            logger.info("Column '%s' already in catalog '%s'  [SKIP]"
                        % (name, catalog))
            continue