def workflow_script_cancel(self): if skip(self, "cancel"): return sample = self.aq_parent workflow = getToolByName(self, 'portal_workflow') self.reindexObject(idxs=["cancellation_state", ]) sample_c_state = workflow.getInfoFor(sample, 'cancellation_state') # if all sibling partitions are cancelled, cancel sample if not skip(sample, "cancel", peek=True): active = [sp for sp in sample.objectValues("SamplePartition") if workflow.getInfoFor(sp, 'cancellation_state') == 'active'] if sample_c_state == 'active' and not active: workflow.doActionFor(sample, 'cancel')
def workflow_script_sample_due(self): if skip(self, "sample_due"): return # All associated AnalysisRequests are also transitioned for ar in self.getAnalysisRequests(): doActionFor(ar, "sample_due") ar.reindexObject()
def workflow_script_cancel(self): if skip(self, "cancel"): return workflow = getToolByName(self, "portal_workflow") parts = self.objectValues("SamplePartition") self.reindexObject(idxs=["cancellation_state"]) # Cancel all partitions for sp in [sp for sp in parts if workflow.getInfoFor(sp, "cancellation_state") == "active"]: workflow.doActionFor(sp, "cancel") # cancel all ARs for this self. ars = self.getAnalysisRequests() for ar in ars: if not skip(ar, "cancel", peek=True): ar_state = workflow.getInfoFor(ar, "cancellation_state") if ar_state == "active": workflow.doActionFor(ar, "cancel")
def workflow_script_cancel(self): if skip(self, "cancel"): return sample = self.aq_parent workflow = getToolByName(self, 'portal_workflow') self.reindexObject(idxs=[ "cancellation_state", ]) sample_c_state = workflow.getInfoFor(sample, 'cancellation_state') # if all sibling partitions are cancelled, cancel sample if not skip(sample, "cancel", peek=True): active = [ sp for sp in sample.objectValues("SamplePartition") if workflow.getInfoFor(sp, 'cancellation_state') == 'active' ] if sample_c_state == 'active' and not active: workflow.doActionFor(sample, 'cancel')
def workflow_script_attach(self): if skip(self, "attach"): return self.reindexObject(idxs=[ "review_state", ]) # Don't cascade. Shouldn't be attaching WSs for now (if ever). return
def workflow_script_cancel(self): if skip(self, "cancel"): return workflow = getToolByName(self, 'portal_workflow') parts = self.objectValues('SamplePartition') self.reindexObject(idxs=["cancellation_state", ]) # Cancel all partitions for sp in [sp for sp in parts if workflow.getInfoFor(sp, 'cancellation_state') == 'active']: workflow.doActionFor(sp, 'cancel') # cancel all ARs for this self. ars = self.getAnalysisRequests() for ar in ars: if not skip(ar, "cancel", peek=True): ar_state = workflow.getInfoFor(ar, 'cancellation_state') if ar_state == 'active': workflow.doActionFor(ar, 'cancel')
def workflow_script_receive(self): if skip(self, "receive"): return sample = self.aq_parent workflow = getToolByName(self, 'portal_workflow') sample_state = workflow.getInfoFor(sample, 'review_state') self.setDateReceived(DateTime()) self.reindexObject(idxs=["getDateReceived", ]) # Transition our analyses analyses = self.getBackReferences('AnalysisSamplePartition') for analysis in analyses: doActionFor(analysis, "receive") # if all sibling partitions are received, promote sample if not skip(sample, "receive", peek=True): due = [sp for sp in sample.objectValues("SamplePartition") if workflow.getInfoFor(sp, 'review_state') == 'sample_due'] if sample_state == 'sample_due' and not due: doActionFor(sample, 'receive')
def workflow_script_to_be_preserved(self): if skip(self, "to_be_preserved"): return workflow = getToolByName(self, "portal_workflow") parts = self.objectValues("SamplePartition") # Transition our children tbs = [sp for sp in parts if workflow.getInfoFor(sp, "review_state") == "to_be_preserved"] for sp in tbs: doActionFor(sp, "to_be_preserved") # All associated AnalysisRequests are also transitioned for ar in self.getAnalysisRequests(): doActionFor(ar, "to_be_preserved") ar.reindexObject()
def workflow_script_receive(self): if skip(self, "receive"): return sample = self.aq_parent workflow = getToolByName(self, 'portal_workflow') sample_state = workflow.getInfoFor(sample, 'review_state') self.setDateReceived(DateTime()) self.reindexObject(idxs=[ "getDateReceived", ]) # Transition our analyses analyses = self.getBackReferences('AnalysisSamplePartition') for analysis in analyses: doActionFor(analysis, "receive") # if all sibling partitions are received, promote sample if not skip(sample, "receive", peek=True): due = [ sp for sp in sample.objectValues("SamplePartition") if workflow.getInfoFor(sp, 'review_state') == 'sample_due' ] if sample_state == 'sample_due' and not due: doActionFor(sample, 'receive')
def workflow_script_verify(self): if skip(self, "verify"): return workflow = getToolByName(self, 'portal_workflow') self.reindexObject(idxs=["review_state", ]) if not "verify all analyses" in self.REQUEST['workflow_skiplist']: # verify all analyses in this self. analyses = self.getAnalyses() for analysis in analyses: state = workflow.getInfoFor(analysis, 'review_state', '') if state != 'to_be_verified': continue doActionFor(analysis, "verify")
def workflow_script_to_be_preserved(self): if skip(self, "to_be_preserved"): return workflow = getToolByName(self, 'portal_workflow') parts = self.objectValues('SamplePartition') # Transition our children tbs = [sp for sp in parts if workflow.getInfoFor(sp, 'review_state') == 'to_be_preserved'] for sp in tbs: doActionFor(sp, "to_be_preserved") # All associated AnalysisRequests are also transitioned for ar in self.getAnalysisRequests(): doActionFor(ar, "to_be_preserved") ar.reindexObject()
def workflow_script_retract(self): if skip(self, "retract"): return workflow = getToolByName(self, 'portal_workflow') self.reindexObject(idxs=["review_state", ]) if not "retract all analyses" in self.REQUEST['workflow_skiplist']: # retract all analyses in this self. # (NB: don't retract if it's verified) analyses = self.getAnalyses() for analysis in analyses: state = workflow.getInfoFor(analysis, 'review_state', '') if state not in ('attachment_due', 'to_be_verified',): continue doActionFor(analysis, 'retract')
def workflow_script_sample(self): if skip(self, "sample"): return workflow = getToolByName(self, "portal_workflow") parts = self.objectValues("SamplePartition") # This action can happen in the Sample UI. So we transition all # partitions that are still 'to_be_sampled' tbs = [sp for sp in parts if workflow.getInfoFor(sp, "review_state") == "to_be_sampled"] for sp in tbs: doActionFor(sp, "sample") # All associated AnalysisRequests are also transitioned for ar in self.getAnalysisRequests(): doActionFor(ar, "sample") ar.reindexObject()
def workflow_script_sample(self): if skip(self, "sample"): return workflow = getToolByName(self, 'portal_workflow') parts = self.objectValues('SamplePartition') # This action can happen in the Sample UI. So we transition all # partitions that are still 'to_be_sampled' tbs = [sp for sp in parts if workflow.getInfoFor(sp, 'review_state') == 'to_be_sampled'] for sp in tbs: doActionFor(sp, "sample") # All associated AnalysisRequests are also transitioned for ar in self.getAnalysisRequests(): doActionFor(ar, "sample") ar.reindexObject()
def workflow_script_verify(self): if skip(self, "verify"): return workflow = getToolByName(self, 'portal_workflow') self.reindexObject(idxs=[ "review_state", ]) if not "verify all analyses" in self.REQUEST['workflow_skiplist']: # verify all analyses in this self. analyses = self.getAnalyses() for analysis in analyses: state = workflow.getInfoFor(analysis, 'review_state', '') if state != 'to_be_verified': continue doActionFor(analysis, "verify")
def workflow_script_retract(self): if skip(self, "retract"): return workflow = getToolByName(self, 'portal_workflow') self.reindexObject(idxs=[ "review_state", ]) if not "retract all analyses" in self.REQUEST['workflow_skiplist']: # retract all analyses in this self. # (NB: don't retract if it's verified) analyses = self.getAnalyses() for analysis in analyses: state = workflow.getInfoFor(analysis, 'review_state', '') if state not in ( 'attachment_due', 'to_be_verified', ): continue doActionFor(analysis, 'retract')
def workflow_script_to_be_preserved(self): if skip(self, "to_be_preserved"): return sample = self.aq_parent workflow = getToolByName(self, 'portal_workflow') # Transition our analyses analyses = self.getBackReferences('AnalysisSamplePartition') for analysis in analyses: doActionFor(analysis, "to_be_preserved") # if all our siblings are now up to date, promote sample and ARs. parts = sample.objectValues("SamplePartition") if parts: lower_states = ['to_be_sampled', 'to_be_preserved', ] escalate = True for part in parts: if workflow.getInfoFor(part, 'review_state') in lower_states: escalate = False if escalate: doActionFor(sample, "to_be_preserved") for ar in sample.getAnalysisRequests(): doActionFor(ar, "to_be_preserved")
def workflow_script_sample_due(self): if skip(self, "sample_due"): return sample = self.aq_parent workflow = getToolByName(self, 'portal_workflow') # Transition our analyses analyses = self.getBackReferences('AnalysisSamplePartition') for analysis in analyses: doActionFor(analysis, "sample_due") # if all our siblings are now up to date, promote sample and ARs. parts = sample.objectValues("SamplePartition") if parts: lower_states = [ 'to_be_preserved', ] escalate = True for part in parts: pstate = workflow.getInfoFor(part, 'review_state') if pstate in lower_states: escalate = False if escalate: doActionFor(sample, "sample_due") for ar in sample.getAnalysisRequests(): doActionFor(ar, "sample_due")
def workflow_script_reject(self): """Copy real analyses to RejectAnalysis, with link to real create a new worksheet, with the original analyses, and new duplicates and references to match the rejected worksheet. """ if skip(self, "reject"): return utils = getToolByName(self, 'plone_utils') workflow = self.portal_workflow def copy_src_fields_to_dst(src, dst): # These will be ignored when copying field values between analyses ignore_fields = [ 'UID', 'id', 'title', 'allowDiscussion', 'subject', 'description', 'location', 'contributors', 'creators', 'effectiveDate', 'expirationDate', 'language', 'rights', 'creation_date', 'modification_date', 'Layout', # ws 'Analyses', # ws ] fields = src.Schema().fields() for field in fields: fieldname = field.getName() if fieldname in ignore_fields: continue getter = getattr( src, 'get' + fieldname, src.Schema().getField(fieldname).getAccessor(src)) setter = getattr( dst, 'set' + fieldname, dst.Schema().getField(fieldname).getMutator(dst)) if getter is None or setter is None: # ComputedField continue setter(getter()) analysis_positions = {} for item in self.getLayout(): analysis_positions[item['analysis_uid']] = item['position'] old_layout = [] new_layout = [] # New worksheet worksheets = self.aq_parent new_ws = _createObjectByType('Worksheet', worksheets, tmpID()) new_ws.unmarkCreationFlag() new_ws_id = renameAfterCreation(new_ws) copy_src_fields_to_dst(self, new_ws) new_ws.edit(Number=new_ws_id, Remarks=self.getRemarks()) # Objects are being created inside other contexts, but we want their # workflow handlers to be aware of which worksheet this is occurring in. # We save the worksheet in request['context_uid']. # We reset it again below.... be very sure that this is set to the # UID of the containing worksheet before invoking any transitions on # analyses. self.REQUEST['context_uid'] = new_ws.UID() # loop all analyses analyses = self.getAnalyses() new_ws_analyses = [] old_ws_analyses = [] for analysis in analyses: # Skip published or verified analyses review_state = workflow.getInfoFor(analysis, 'review_state', '') if review_state in ['published', 'verified', 'retracted']: old_ws_analyses.append(analysis.UID()) old_layout.append({ 'position': position, 'type': 'a', 'analysis_uid': analysis.UID(), 'container_uid': analysis.aq_parent.UID() }) continue # Normal analyses: # - Create matching RejectAnalysis inside old WS # - Link analysis to new WS in same position # - Copy all field values # - Clear analysis result, and set Retested flag if analysis.portal_type == 'Analysis': reject = _createObjectByType('RejectAnalysis', self, tmpID()) reject.unmarkCreationFlag() reject_id = renameAfterCreation(reject) copy_src_fields_to_dst(analysis, reject) reject.setAnalysis(analysis) reject.reindexObject() analysis.edit( Result=None, Retested=True, ) analysis.reindexObject() position = analysis_positions[analysis.UID()] old_ws_analyses.append(reject.UID()) old_layout.append({ 'position': position, 'type': 'r', 'analysis_uid': reject.UID(), 'container_uid': self.UID() }) new_ws_analyses.append(analysis.UID()) new_layout.append({ 'position': position, 'type': 'a', 'analysis_uid': analysis.UID(), 'container_uid': analysis.aq_parent.UID() }) # Reference analyses # - Create a new reference analysis in the new worksheet # - Transition the original analysis to 'rejected' state if analysis.portal_type == 'ReferenceAnalysis': service_uid = analysis.getService().UID() reference = analysis.aq_parent reference_type = analysis.getReferenceType() new_analysis_uid = reference.addReferenceAnalysis( service_uid, reference_type) position = analysis_positions[analysis.UID()] old_ws_analyses.append(analysis.UID()) old_layout.append({ 'position': position, 'type': reference_type, 'analysis_uid': analysis.UID(), 'container_uid': reference.UID() }) new_ws_analyses.append(new_analysis_uid) new_layout.append({ 'position': position, 'type': reference_type, 'analysis_uid': new_analysis_uid, 'container_uid': reference.UID() }) workflow.doActionFor(analysis, 'reject') new_reference = reference.uid_catalog( UID=new_analysis_uid)[0].getObject() workflow.doActionFor(new_reference, 'assign') analysis.reindexObject() # Duplicate analyses # - Create a new duplicate inside the new worksheet # - Transition the original analysis to 'rejected' state if analysis.portal_type == 'DuplicateAnalysis': src_analysis = analysis.getAnalysis() ar = src_analysis.aq_parent service = src_analysis.getService() duplicate_id = new_ws.generateUniqueId('DuplicateAnalysis') new_duplicate = _createObjectByType('DuplicateAnalysis', new_ws, duplicate_id) new_duplicate.unmarkCreationFlag() copy_src_fields_to_dst(analysis, new_duplicate) workflow.doActionFor(new_duplicate, 'assign') new_duplicate.reindexObject() position = analysis_positions[analysis.UID()] old_ws_analyses.append(analysis.UID()) old_layout.append({ 'position': position, 'type': 'd', 'analysis_uid': analysis.UID(), 'container_uid': self.UID() }) new_ws_analyses.append(new_duplicate.UID()) new_layout.append({ 'position': position, 'type': 'd', 'analysis_uid': new_duplicate.UID(), 'container_uid': new_ws.UID() }) workflow.doActionFor(analysis, 'reject') analysis.reindexObject() new_ws.setAnalyses(new_ws_analyses) new_ws.setLayout(new_layout) new_ws.replaces_rejected_worksheet = self.UID() for analysis in new_ws.getAnalyses(): review_state = workflow.getInfoFor(analysis, 'review_state', '') if review_state == 'to_be_verified': changeWorkflowState(analysis, "bika_analysis_workflow", "sample_received") self.REQUEST['context_uid'] = self.UID() self.setLayout(old_layout) self.setAnalyses(old_ws_analyses) self.replaced_by = new_ws.UID()
def workflow_script_attach(self): if skip(self, "attach"): return self.reindexObject(idxs=["review_state", ]) # Don't cascade. Shouldn't be attaching WSs for now (if ever). return
def workflow_script_reject(self): """Copy real analyses to RejectAnalysis, with link to real create a new worksheet, with the original analyses, and new duplicates and references to match the rejected worksheet. """ if skip(self, "reject"): return utils = getToolByName(self, 'plone_utils') workflow = self.portal_workflow def copy_src_fields_to_dst(src, dst): # These will be ignored when copying field values between analyses ignore_fields = ['UID', 'id', 'title', 'allowDiscussion', 'subject', 'description', 'location', 'contributors', 'creators', 'effectiveDate', 'expirationDate', 'language', 'rights', 'creation_date', 'modification_date', 'Layout', # ws 'Analyses', # ws ] fields = src.Schema().fields() for field in fields: fieldname = field.getName() if fieldname in ignore_fields: continue getter = getattr(src, 'get'+fieldname, src.Schema().getField(fieldname).getAccessor(src)) setter = getattr(dst, 'set'+fieldname, dst.Schema().getField(fieldname).getMutator(dst)) if getter is None or setter is None: # ComputedField continue setter(getter()) analysis_positions = {} for item in self.getLayout(): analysis_positions[item['analysis_uid']] = item['position'] old_layout = [] new_layout = [] # New worksheet worksheets = self.aq_parent new_ws = _createObjectByType('Worksheet', worksheets, tmpID()) new_ws.unmarkCreationFlag() new_ws_id = renameAfterCreation(new_ws) copy_src_fields_to_dst(self, new_ws) new_ws.edit( Number = new_ws_id, Remarks = self.getRemarks() ) # Objects are being created inside other contexts, but we want their # workflow handlers to be aware of which worksheet this is occurring in. # We save the worksheet in request['context_uid']. # We reset it again below.... be very sure that this is set to the # UID of the containing worksheet before invoking any transitions on # analyses. self.REQUEST['context_uid'] = new_ws.UID() # loop all analyses analyses = self.getAnalyses() new_ws_analyses = [] old_ws_analyses = [] for analysis in analyses: # Skip published or verified analyses review_state = workflow.getInfoFor(analysis, 'review_state', '') if review_state in ['published', 'verified', 'retracted']: old_ws_analyses.append(analysis.UID()) old_layout.append({'position': position, 'type':'a', 'analysis_uid':analysis.UID(), 'container_uid':analysis.aq_parent.UID()}) continue # Normal analyses: # - Create matching RejectAnalysis inside old WS # - Link analysis to new WS in same position # - Copy all field values # - Clear analysis result, and set Retested flag if analysis.portal_type == 'Analysis': reject = _createObjectByType('RejectAnalysis', self, tmpID()) reject.unmarkCreationFlag() reject_id = renameAfterCreation(reject) copy_src_fields_to_dst(analysis, reject) reject.setAnalysis(analysis) reject.reindexObject() analysis.edit( Result = None, Retested = True, ) analysis.reindexObject() position = analysis_positions[analysis.UID()] old_ws_analyses.append(reject.UID()) old_layout.append({'position': position, 'type':'r', 'analysis_uid':reject.UID(), 'container_uid':self.UID()}) new_ws_analyses.append(analysis.UID()) new_layout.append({'position': position, 'type':'a', 'analysis_uid':analysis.UID(), 'container_uid':analysis.aq_parent.UID()}) # Reference analyses # - Create a new reference analysis in the new worksheet # - Transition the original analysis to 'rejected' state if analysis.portal_type == 'ReferenceAnalysis': service_uid = analysis.getService().UID() reference = analysis.aq_parent reference_type = analysis.getReferenceType() new_analysis_uid = reference.addReferenceAnalysis(service_uid, reference_type) position = analysis_positions[analysis.UID()] old_ws_analyses.append(analysis.UID()) old_layout.append({'position': position, 'type':reference_type, 'analysis_uid':analysis.UID(), 'container_uid':reference.UID()}) new_ws_analyses.append(new_analysis_uid) new_layout.append({'position': position, 'type':reference_type, 'analysis_uid':new_analysis_uid, 'container_uid':reference.UID()}) workflow.doActionFor(analysis, 'reject') new_reference = reference.uid_catalog(UID=new_analysis_uid)[0].getObject() workflow.doActionFor(new_reference, 'assign') analysis.reindexObject() # Duplicate analyses # - Create a new duplicate inside the new worksheet # - Transition the original analysis to 'rejected' state if analysis.portal_type == 'DuplicateAnalysis': src_analysis = analysis.getAnalysis() ar = src_analysis.aq_parent service = src_analysis.getService() duplicate_id = new_ws.generateUniqueId('DuplicateAnalysis') new_duplicate = _createObjectByType('DuplicateAnalysis', new_ws, duplicate_id) new_duplicate.unmarkCreationFlag() copy_src_fields_to_dst(analysis, new_duplicate) workflow.doActionFor(new_duplicate, 'assign') new_duplicate.reindexObject() position = analysis_positions[analysis.UID()] old_ws_analyses.append(analysis.UID()) old_layout.append({'position': position, 'type':'d', 'analysis_uid':analysis.UID(), 'container_uid':self.UID()}) new_ws_analyses.append(new_duplicate.UID()) new_layout.append({'position': position, 'type':'d', 'analysis_uid':new_duplicate.UID(), 'container_uid':new_ws.UID()}) workflow.doActionFor(analysis, 'reject') analysis.reindexObject() new_ws.setAnalyses(new_ws_analyses) new_ws.setLayout(new_layout) new_ws.replaces_rejected_worksheet = self.UID() for analysis in new_ws.getAnalyses(): review_state = workflow.getInfoFor(analysis, 'review_state', '') if review_state == 'to_be_verified': changeWorkflowState(analysis, "bika_analysis_workflow", "sample_received") self.REQUEST['context_uid'] = self.UID() self.setLayout(old_layout) self.setAnalyses(old_ws_analyses) self.replaced_by = new_ws.UID()