def guard_verify(analysis_request): """Returns whether the transition "verify" can be performed or not. Returns True if at there is at least one analysis in a non-dettached state and all analyses in a non-detached state are in "verified" state. """ # Discard detached analyses analyses = analysis_request.getAnalyses(full_objects=True) analyses = filter( lambda an: api.get_workflow_status_of(an) not in ANALYSIS_DETACHED_STATES, analyses) # If not all analyses are for internal use, rely on "regular" analyses internals = map(IInternalUse.providedBy, analyses) omit_internals = not all(internals) analyses_ready = False for analysis in analyses: # Omit analyses for internal use if omit_internals and IInternalUse.providedBy(analysis): continue # All analyses must be in verified (or further) status if not IVerified.providedBy(analysis): return False analyses_ready = True return analyses_ready
def guard_submit(analysis_request): """Return whether the transition "submit" can be performed or not. Returns True if there is at least one analysis in a non-detached state and all analyses in a non-detached analyses have been submitted. """ # Discard detached analyses analyses = analysis_request.getAnalyses(full_objects=True) analyses = filter( lambda an: api.get_workflow_status_of(an) not in ANALYSIS_DETACHED_STATES, analyses) # If not all analyses are for internal use, rely on "regular" analyses internals = map(IInternalUse.providedBy, analyses) omit_internals = not all(internals) analyses_ready = False for analysis in analyses: # Omit analyses for internal use if omit_internals and IInternalUse.providedBy(analysis): continue analysis_status = api.get_workflow_status_of(analysis) if analysis_status in ['assigned', 'unassigned', 'registered']: return False analyses_ready = True return analyses_ready
def ObjectModifiedEventHandler(instance, event): """Actions to be taken when AnalysisRequest object is modified """ # If Internal Use value has been modified, apply suitable permissions internal_use = instance.getInternalUse() if internal_use != IInternalUse.providedBy(instance): # Update permissions for current sample update_internal_use_permissions(instance) # Mark/Unmark all analyses with IInternalUse to control their # visibility in results reports for analysis in instance.objectValues("Analysis"): if internal_use: alsoProvides(analysis, IInternalUse) else: noLongerProvides(analysis, IInternalUse) # Reindex analysis security in catalogs analysis.reindexObjectSecurity() # If internal use is True, cascade same setting to partitions if internal_use: for partition in instance.getDescendants(): partition.setInternalUse(internal_use) # Notify the partition has been modified modified(partition)
def get_analyses(self, model_or_collection): """Returns a flat list of all analyses for the given model or collection """ collection = self.to_list(model_or_collection) analyses = chain(*map(lambda m: m.Analyses, collection)) # Boil out analyses meant to be used for internal use only analyses = filter(lambda an: not IInternalUse.providedBy(an.instance), analyses) return self.sort_items(analyses)
def guard_publish(analysis_request): """Returns whether the transition "publish" can be performed or not. Returns True if the analysis request is not labeled for internal use or if at least one of the contained analyses is not for internal use """ if IInternalUse.providedBy(analysis_request): return False # Note we return True without checking anything else because this # transition is only available when sample is in verified status return True
def guard_prepublish(analysis_request): """Returns whether 'prepublish' transition can be perform or not. Returns True if the analysis request has at least one analysis in 'verified' or in 'to_be_verified' status. Otherwise, return False """ if IInternalUse.providedBy(analysis_request): return False valid_states = ['verified', 'to_be_verified'] for analysis in analysis_request.getAnalyses(): analysis = api.get_object(analysis) if api.get_workflow_status_of(analysis) in valid_states: return True return False
def after_submit(analysis): """Event fired when an analysis result gets submitted """ if not IASTAnalysis.providedBy(analysis): return # Check that values for all interim fields are set interim_fields = analysis.getInterimFields() values = map(lambda interim: interim.get("value"), interim_fields) if not all(values): return # All siblings for same microorganism and sample have to be submitted siblings = utils.get_ast_siblings(analysis) submitted = map(ISubmitted.providedBy, siblings) if not all(submitted): return # Calculate the hidden analyses and results analyses = siblings + [analysis] # We only do report results from "resistance" analysis resistance = filter(lambda an: an.getKeyword() == RESISTANCE_KEY, analyses) resistance = resistance[0] # Results are the values (R/S/+/-) set for resistance' interim fields results = resistance.getInterimFields() # Find out the resistance results to report report_analysis = filter(lambda an: an.getKeyword() == REPORT_KEY, analyses) if report_analysis: # The results to be reported are defined by the Y/N values set for the # interim fields of the "selective reporting" analysis to_report = report_analysis[0].getInterimFields() # XXX senaite.app.listing has no support boolean type for interim fields to_report = filter(lambda k: k.get("value") == "1", to_report) # Get the abbreviation of microorganisms (keyword) keywords = map(lambda k: k.get("keyword"), to_report) # Filter the interim fields from resistance results = filter(lambda r: r.get("keyword") in keywords, results) # The "selected" result options are those to be reported options = resistance.getResultOptions() def to_report(option): key = option.get("InterimKeyword") val = option.get("InterimValue") for target in results: if key == target.get("keyword") and val == target.get("value"): return True return False # Remove the antibiotics to not report from options options = filter(to_report, options) # The final result is a list with result option values result = map(lambda o: o.get("ResultValue"), options) # No need to keep track of this in audit (this is internal) noLongerProvides(resistance, IAuditable) # Set the final result capture_date = resistance.getResultCaptureDate() resistance.setResult(result) resistance.setResultCaptureDate(capture_date) # We do want to report this resistance analysis if IInternalUse.providedBy(resistance): noLongerProvides(resistance, IInternalUse) # Re-enable the audit for this analysis alsoProvides(resistance, IAuditable)