def _get_draftdoc_by_name(self, wfdoc_name): result = None search_dict = {"name": wfdoc_name} dfraft_repo = DomainRepo("Draftdata") lst = dfraft_repo.list_domain_obj(**search_dict) if len(lst) == 1 : result = lst[0] return result
def _get_wfdoc_by_name(self, wfdoc_name): '''search by primary key id, hence expected to get one object''' result = None search_dict = {"name": wfdoc_name} wfdoc_repo = DomainRepo("Wfdoc") lst = wfdoc_repo.list_domain_obj(**search_dict) if len(lst) == 1 : result = lst[0] return result
def _list_wfdocObj(self): wfdoc_repo = DomainRepo("Wfdoc") search_f = {"associated_doctype_name": self.doctype_name} #if wfc_filter: # search_f = {"associated_doctype_name": self.doctype_name, # "doc_data": wfc_filter} wfdocObj_list = wfdoc_repo.list_domain_obj(**search_f) return wfdocObj_list
def _get_doctype_obj_from_name(self): '''search by primary key name, hence expected to get one object''' result = None search_dict = {"name": self.doctype_name} doctype_repo = DomainRepo("Doctype") lst = doctype_repo.list_domain_obj(**search_dict) if not lst: conf_lst = doctype_repo.list_domain_obj() raise rexc.DocCategoryNotConfigured(self.doctype_name, conf_lst) if len(lst) == 1 : result = lst[0] return result
def _list_from_holddoc_filtered_by_logged_in_user_roles(self, wfc_filter=None): wfdoctype_repo = DomainRepo('Holddoc') search_f = {"associated_doctype_name": self.doctype_name} lst = wfdoctype_repo.list_dict(**search_f) if wfc_filter: lst = self._filter_by_wfc_on_doc_data(lst, wfc_filter) holddocs_filter_by_role = [] for urole in self.wfc.roles: for hold_doc in lst: if urole == hold_doc.get('target_role'): holddocs_filter_by_role.append(hold_doc) return holddocs_filter_by_role
def _delete_all_holddoc_for_a_wfdoc(self, wfdocObj): '''may not be required any more ''' search_string = {"wfdoc_name": wfdocObj.name} holddoc_repo = DomainRepo("Holddoc") result = holddoc_repo.delete(**search_string)#TODO: should be no doc found when not present return result
def get_full_wfdoctype_as_dict(self): wfdoctypeObj = None wfdoctype_repo = DomainRepo('Doctype') wfdoctypeObj = wfdoctype_repo.list_domain_obj(**{"name": self.doctype_name}) if wfdoctypeObj: wfdoctypeObj = wfdoctypeObj[0] datadocfields = [] for fObj in wfdoctypeObj.datadocfields: fdict = fObj.to_dict() fdict.pop('associated_doctype') fdict.pop('associated_doctype_name') datadocfields.append(fdict) wfdoctype_dict = wfdoctypeObj.to_dict() wfdoctype_dict.update({"datadocfields": datadocfields}) return utils.lower_case_keys(wfdoctype_dict)
def _create_with_audit(self, wfdocObj, docid, input_data): wfdoc_repo = DomainRepo("Wfdoc") msg = wfdoc_repo.add_list_of_domain_obj([wfdocObj]) try: audit_msg = self._create_audit_record(wfdocObj, 'Create', input_data) msg.update({"audit_msg": audit_msg}) if audit_msg.get('status').lower().strip() in ['failed', 'Failed', 'error']: raise rexc.AuditRecordCreationFailed(docid, audit_msg.get('message') ) except (rexc.AuditRecordCreationFailed, rexc.FlexFlowException, Exception) as e: status = wfdoc_repo.delete(**{"name": docid}) #status_roll_back_holddoc = holddoc_repo.delete(**search_filter) rollback_msg = {"status": status, "message": str(e) } msg.update({"rollback_msg": rollback_msg}) raise rexc.AuditRecordCreationFailed(docid, audit_msg.get('message'), str(e) ) return msg
def _get_detail_holddoc_for_a_wfdoc(self, wfdoc_dict): hodl_doc_dict = None holddoc_repo = DomainRepo('Holddoc') for urole in self.wfc.roles: #for multiple roles, only the first match is considered search_f = {#"associated_doctype_name": self.doctype_name, #TODO: reinforce once update restapi takes <doctype> as param "wfdoc_name": wfdoc_dict.get('name'), "target_role": urole, "name": urole+wfdoc_dict.get('name')} print('serach string ...........', search_f) result = holddoc_repo.list_dict(**search_f) if result: hodl_doc_dict = result[0] print('got result from holddoc...........', hodl_doc_dict) break return hodl_doc_dict
def _unhide_or_hide_action_to_roles(self, wfdocObj, intended_action, new_born): holddoc_repo = DomainRepo("Holddoc") self._delete_prev_holddoc_by_unhide_roles(wfdocObj, intended_action, holddoc_repo) hide_to_roles = self._get_hide_to_roles_from_wfdoc(wfdocObj, intended_action) if isinstance(hide_to_roles, list) and len(hide_to_roles) > 0: for urole in hide_to_roles: self._create_holddoc_for_current_role(urole, intended_action, wfdocObj, holddoc_repo, new_born)
def test_models(self): m.dbdriver.delete(m.Holddoc) m.dbdriver.delete(m.Wfdocaudit) m.dbdriver.delete(m.Wfdoc) m.dbdriver.delete(m.Wfaction) m.dbdriver.delete(m.Wfstatus) m.dbdriver.delete(m.Datadocfield) m.dbdriver.delete(m.Doctype) docrepo = DomainRepo("Wfdoc") ###########ADDING SINGLE RECORD record = m.Wfstatus(name="Status1") msg = m.dbdriver.insert(record) #print(msg) self.assertTrue('has been registered' in msg) ############UPDATING THE RECORD data = {"name": "Status1111"} msg = m.dbdriver.update(m.Wfstatus, data, name='Status1') self.assertTrue(msg['status'] == "success") msg = m.dbdriver.list_as_dict(m.Wfstatus, name="Status1111") self.assertTrue(msg[0]['name'] == 'Status1111') #DELETE A SINGLE RECORD FILTERED BY NAME msg = m.dbdriver.delete(m.Wfstatus, name="Status1111") self.assertTrue("has been deleted successfully" in msg) #########INSERT BULK lod = [{"name": "status2"}, {"name": "status3"}, {"name": "status4"}] msg = m.dbdriver.insert_bulk(m.Wfstatus, lod) msg = m.dbdriver.list_as_dict(m.Wfstatus) self.assertTrue(len(msg) == 3) ###########DELETE ALL msg = m.dbdriver.delete(m.Wfstatus) self.assertTrue("has been deleted successfully" in msg)
def _create_audit_record(self, wfdocObj, intended_action, input_data:dict): WfdocauditObj = ent.Wfdocaudit(name=str(uuid.uuid4()), #self.wfc.request_id, wfdoc=wfdocObj, username=self.wfc.username, email=self.wfc.email, time_stamp=self.wfc.time_stamp, client_address=self.wfc.client_address, org=self.wfc.org, orgunit=self.wfc.orgunit, department=self.wfc.department, roles=self.wfc.roles, action=intended_action, data=input_data) wfdocaudit_repo = DomainRepo('Wfdocaudit') msg = wfdocaudit_repo.add_list_of_domain_obj([WfdocauditObj]) #print(msg) return msg
def _create_draft_or_roll_back(self, wfdocObj, draft_data): draft_create_msg = {} draftdataObj = ent.Draftdata(name=wfdocObj.name, drafted_by=self.wfc.email, target_role = self.wfc.roles, wfdoc=wfdocObj, doc_data=draft_data) try: draftdoc_repo = DomainRepo("Draftdata") draft_search_string = {"name": wfdocObj.name}#delete before creating prev_draf_cleared_status = draftdoc_repo.delete(**draft_search_string) status = draftdoc_repo.add_list_of_domain_obj([draftdataObj]) wfdoc_update_msg = self._update_wfdoc_draft_status(wfdocObj, self.wfc.roles) draft_create_msg.update({"draft_create_msg": status, "wfdoc_update_msg": wfdoc_update_msg, "prev_draf_cleared_status": prev_draf_cleared_status}) except (rexc.FlexFlowException, Exception) as e: delete_stat = draftdoc_repo.delete(**{"name": wfdocObj.name}) reset_wfdoc_stat = self._update_wfdoc_draft_status(wfdocObj) draft_create_msg.update({"delete_stat": delete_stat, "reset_wfdoc_stat": reset_wfdoc_stat, "rollback_msg": str(e)}) raise rexc.FlexFlowException return draft_create_msg
def _updadate_with_audit(self, wfdocObj, intended_action, changed_data ): ''' also takes care "has_draft_for_roles" role back''' wfdoc_repo = DomainRepo("Wfdoc") draftdata_repo = DomainRepo("Draftdata") target_doc_name = {"name": wfdocObj.name} msg = wfdoc_repo.update_from_dict(changed_data, **target_doc_name) try: draft_search_string = {"name": wfdocObj.name} audit_msg = self._create_audit_record(wfdocObj, intended_action, changed_data) draf_cleared_status = draftdata_repo.delete(**draft_search_string) msg.update({"audit_msg": audit_msg, "draf_cleared_status": draf_cleared_status}) if audit_msg.get('status').lower().strip() in ['failed', 'Failed', 'error']: raise rexc.AuditRecordCreationFailed(target_doc_name, audit_msg.get('message') ) except Exception as e: updated_data_dict = {"current_status": wfdocObj.current_status, "prev_status": wfdocObj.prev_status, "has_draft_for_roles": wfdocObj.has_draft_for_roles, "doc_data": wfdocObj.doc_data} rollback_msg = wfdoc_repo.update_from_dict(updated_data_dict, **target_doc_name) msg.update({"rollback_msg": rollback_msg}) raise rexc.AuditRecordCreationFailed(target_doc_name, audit_msg.get('message'), str(e) ) return msg
def _update_wfdoc_draft_status(self, wfdocObj, draft_for_role=None): wfdoc_repo = DomainRepo("Wfdoc") target_wfdoc_name = {"name": wfdocObj.name} updated_wfdoc_draft_roles = {"has_draft_for_roles": draft_for_role} ustatus = wfdoc_repo.update_from_dict(updated_wfdoc_draft_roles, **target_wfdoc_name) return ustatus
def _register_doctype_n_actions(self): m.dbdriver.delete(m.Wfdoc) m.dbdriver.delete(m.Wfaction) m.dbdriver.delete(m.Wfstatus) m.dbdriver.delete(m.Datadocfield) m.dbdriver.delete(m.Doctype) doctype1 = ent.Doctype("doctype1", "dk1") doctype2 = ent.Doctype("doctype2", "invoiceno") lodobj = [doctype1, doctype2] doctype_repo = DomainRepo("Doctype") doctype_repo.add_list_of_domain_obj(lodobj) ####DEFINING FIELDS FOR DOCTYPE2 f1_dict = { "name": "invoiceno", "associated_doctype": { "name": "doctype2" }, "ftype": "str", "flength": 100, "status_needed_edit": [""] } #this should be status not role f2_dict = { "name": "dk2", "associated_doctype": { "name": "doctype2" }, "ftype": "str", "flength": 10, "status_needed_edit": ["Created"] } docf_repo = repos.DomainRepo("Datadocfield") docf_repo.add_form_lod([f1_dict, f2_dict]) wfcaction_create = { "name": "Create", "associated_doctype": { "name": "doctype2" }, "need_prev_status": "NewBorn", "need_current_status": "NewBorn", "leads_to_status": "Created", "permitted_to_roles": [ "role1", ] } wfaction1_dict = { "name": "wfaction1", "associated_doctype": { "name": "doctype2" }, "need_prev_status": "", "need_current_status": "Created", "leads_to_status": "s1", "permitted_to_roles": [ "r1", ] } wfaction2_dict = { "name": "wfaction2", "associated_doctype": { "name": "doctype2" }, "need_prev_status": "Created", "need_current_status": "s1", "leads_to_status": "s2", "permitted_to_roles": [ "r2", ] } wfaction3_dict = { "name": "wfaction3", "associated_doctype": { "name": "doctype2" }, "need_prev_status": "s1", "need_current_status": "s2", "leads_to_status": "s3", "permitted_to_roles": [ "r3", ] } wfactionCreate = ent.Wfaction.from_dict(wfcaction_create) wfaction1 = ent.Wfaction.from_dict(wfaction1_dict) wfaction2 = ent.Wfaction.from_dict(wfaction2_dict) wfaction3 = ent.Wfaction.from_dict(wfaction3_dict) lodobj = [wfactionCreate, wfaction1, wfaction2, wfaction3] action_repo = DomainRepo("Wfaction") action_repo.add_list_of_domain_obj(lodobj)
def _register_doctype_n_actions(self): doctype1 = ent.Doctype("doctype1", "dk1", ['role1']) doctype2 = ent.Doctype("doctype2", "dk2", ['role1']) lodobj = [doctype1, doctype2] doctype_repo = DomainRepo("Doctype") doctype_repo.add_list_of_domain_obj(lodobj) ####DEFINING FIELDS FOR DOCTYPE2 f1_dict = { "name": "dk1", "associated_doctype": { "name": "doctype2" }, "ftype": "str", "flength": 25, "status_needed_edit": ["s1", "Created", "s2"], #this should be status not role "wfc_filter": "", "wfc_filter_to_roles": [] } f2_dict = { "name": "dk2", "associated_doctype": { "name": "doctype2" }, "ftype": "str", "flength": 10, "status_needed_edit": [""], "wfc_filter": "", "wfc_filter_to_roles": [] } f3_dict = { "name": "tsp", "associated_doctype": { "name": "doctype2" }, "ftype": "str", "flength": 10, "status_needed_edit": [""], "wfc_filter": "org", "wfc_filter_to_roles": ['r1'] } f4_dict = { "name": "division", "associated_doctype": { "name": "doctype2" }, "ftype": "str", "flength": 10, "status_needed_edit": [""], "wfc_filter": "ou", "wfc_filter_to_roles": ['r3'] } docf_repo = repos.DomainRepo("Datadocfield") docf_repo.add_form_lod([f1_dict, f2_dict, f3_dict, f4_dict]) wfcaction_create = { "name": "Create", "associated_doctype": { "name": "doctype2" }, #"need_prev_status": "NewBorn", "need_current_status": ["NewBorn"], "leads_to_status": "Created", "permitted_to_roles": [ "r1", ], "hide_to_roles": ["r7"], "undo_prev_hide_for": [], } wfaction1_dict = { "name": "wfaction1", "associated_doctype": { "name": "doctype2" }, #"need_prev_status": "NewBorn", "need_current_status": ["Created"], "leads_to_status": "s1", "permitted_to_roles": [ "r1", ], "hide_to_roles": ["r4", "r5"], "undo_prev_hide_for": [], } wfaction2_dict = { "name": "wfaction2", "associated_doctype": { "name": "doctype2" }, #"need_prev_status": "Created", "need_current_status": ["s1"], "leads_to_status": "s2", "permitted_to_roles": [ "r2", ], "hide_to_roles": ["r5", "r6"], "undo_prev_hide_for": [ "r4", ], #r4 hold doc shold be deleted but r5 to be retained } wfaction3_dict = { "name": "wfaction3", "associated_doctype": { "name": "doctype2" }, #"need_prev_status": "s1", "need_current_status": ["s2"], "leads_to_status": "s3", "permitted_to_roles": [ "r3", ], "hide_to_roles": [ "r1", ], "undo_prev_hide_for": ["r5", "r6"], } wfaction4_dict = { "name": "wfaction4", "associated_doctype": { "name": "doctype2" }, #"need_prev_status": "s2", "need_current_status": ["s3"], "leads_to_status": "s4", "permitted_to_roles": [ "r3", ], "hide_to_roles": [ "r5", ], "undo_prev_hide_for": [], } wfactionCreate = ent.Wfaction.from_dict(wfcaction_create) wfaction1 = ent.Wfaction.from_dict(wfaction1_dict) wfaction2 = ent.Wfaction.from_dict(wfaction2_dict) wfaction3 = ent.Wfaction.from_dict(wfaction3_dict) lodobj = [wfactionCreate, wfaction1, wfaction2, wfaction3] action_repo = DomainRepo("Wfaction") action_repo.add_list_of_domain_obj(lodobj)
def test_workflow(self): m.dbdriver.delete(m.Draftdata) m.dbdriver.delete(m.Holddoc) m.dbdriver.delete(m.Wfdocaudit) m.dbdriver.delete(m.Wfdoc) m.dbdriver.delete(m.Wfaction) m.dbdriver.delete(m.Wfstatus) m.dbdriver.delete(m.Datadocfield) m.dbdriver.delete(m.Doctype) self._register_doctype_n_actions() testconf.testwfc.roles = ['r1'] wf = Workflow('doctype2', wfc=testconf.testwfc) ##create should fail when primary key fields in datadoc is not in rule try: msg = wf.create_doc({ "dk1": "dv1", "dk2-nonprim": "dv22", }) except Exception as e: self.assertTrue(e.status == "PrimaryKeyNotPresentInDataDict") ##Converts data type when fields dk1 is not string #wf.create_doc({"dk1": 100, "dk2": "dv2222", }) ##Fail when fields dk3 is not present in the rule at all try: msg = wf.create_doc({ "dk3": "not defined in the rule", "dk2": "dv22", "dk1": 100, "tsp": "tata", "division": "divison1" }) except Exception as e: self.assertTrue(e.status == "UnknownFieldNameInDataDoc") ### WORKFLOW IS ABLE TO CREATE DOC testconf.testwfc.roles = ['r1'] testconf.testwfc.org = 'org1' msg = wf.create_doc({ "dk1": "dv1", "dk2": "dv22", "tsp": "org1", "division": "divison1" }) self.assertTrue(msg['message'] == "has been registered") ####ABLE TO RETRIEVE THE BY THE PRIMKEY AS DEFINED IN THE DOCTYPE doc_repo = DomainRepo("Wfdoc") wfdocObj_list = doc_repo.list_domain_obj(name="dv22") self.assertTrue(wfdocObj_list[0].name == "dv22") ####UPDATE DOC STATUS AS PER THE ACTION RULE, testconf.testwfc.request_id = str(uuid.uuid4()) wf = Workflow('doctype2', wfc=testconf.testwfc) msg = wf.action_change_status("dv22", "wfaction1", {"dk1": "changed_data_on_action1"}) ### check that self._validate_editable_fields(wfdocObj, data) working self.assertTrue(msg['status'] == "success") ###wdoc should be able to understand that dk2 is editable and dk1 is not self.assertTrue("dk2" not in [ f.name for f in wfdocObj_list[0].editable_fields_at_current_status ]) self.assertTrue("dk1" in [ f.name for f in wfdocObj_list[0].editable_fields_at_current_status ]) ###USE ROLE "hide_to_roles": ["r4", "r5"] to see that data is showing from holddoc #data still should show previous data {"dk1": "dv1", "dk2": "dv22", } testconf.testwfc.roles = ['r4'] testconf.testwfc.request_id = str(uuid.uuid4()) wf = Workflow('doctype2', wfc=testconf.testwfc) result = wf.list_wfdoc() self.assertTrue(result[0].get('doc_data').get('dk1') == 'dv1') # data is showing from holddoc for role r4 ####same for r5 testconf.testwfc.roles = ['r5'] testconf.testwfc.request_id = str(uuid.uuid4()) wf = Workflow('doctype2', wfc=testconf.testwfc) result = wf.list_wfdoc() self.assertTrue(result[0].get('doc_data').get('dk1') == 'dv1') #########FOR R6 AND R1 THE UPDATED DATA IS VISIBLE testconf.testwfc.roles = ['r1', 'r6'] testconf.testwfc.request_id = str(uuid.uuid4()) wf = Workflow('doctype2', wfc=testconf.testwfc) result = wf.list_wfdoc() self.assertTrue( result[0].get('doc_data').get('dk1') == 'changed_data_on_action1') ####SHOULD FAIL FOR INCORRECT ROLE testconf.testwfc.roles = ['r1'] testconf.testwfc.request_id = str(uuid.uuid4()) wf = Workflow('doctype2', wfc=testconf.testwfc) try: msg = wf.action_change_status("dv22", "wfaction2") except rexc.RoleNotPermittedForThisAction as err: self.assertTrue(err.status == "RoleNotPermittedForThisAction") ###SHOULD PASS THE ROLE AND THE RULE testconf.testwfc.request_id = str(uuid.uuid4()) testconf.testwfc.roles = ['r2'] wf = Workflow('doctype2', wfc=testconf.testwfc) msg = wf.action_change_status("dv22", "wfaction2", {"dk1": "changed_data_on_action2"}) self.assertTrue(msg['status'] == "success") ##during action1 "hide_to_roles": ["r4", "r5"], and in action2 "undo_prev_hide_for": ["r4",], ####should be able to see latest data ##########hold for R4 has now been removed ####should be able to see latest data testconf.testwfc.roles = ['r4'] testconf.testwfc.request_id = str(uuid.uuid4()) wf = Workflow('doctype2', wfc=testconf.testwfc) result = wf.list_wfdoc() self.assertTrue( result[0].get('doc_data').get('dk1') == 'changed_data_on_action2') ##########hold for R5 stil remains testconf.testwfc.roles = ['r5'] testconf.testwfc.request_id = str(uuid.uuid4()) wf = Workflow('doctype2', wfc=testconf.testwfc) result = wf.list_wfdoc() self.assertTrue( result[0].get('doc_data').get('dk1') == 'dv1' ) # data remained what it was before action1 which is the data at create stage ####HAVE A TEST FOR RULE STATUS VALIDATION FAILURE testconf.testwfc.request_id = str(uuid.uuid4()) testconf.testwfc.roles = ['r1'] wf = Workflow('doctype2', wfc=testconf.testwfc) try: msg = wf.action_change_status("dv22", "wfaction1") except rexc.WorkflowActionRuleViolation as err: self.assertTrue(err.status == "WorkflowActionRuleViolation") ####WFDOC SHOULD HAVE actions_for_current_stattus actions_for_current_status = [ a.name for a in wfdocObj_list[0].actions_for_current_status ] self.assertTrue(actions_for_current_status == ['wfaction1']) ###fail due to data having non editable field dk1 ###develop logic to check if the data has actually changed testconf.testwfc.request_id = str(uuid.uuid4()) testconf.testwfc.roles = ['r3'] wf = Workflow('doctype2', wfc=testconf.testwfc) try: wf.action_change_status("dv22", "wfaction3", { "dk1": "dv1", "dk2": "dv22" }) except Exception as e: self.assertTrue(e.status == "EditNotAllowedForThisField") ###get full wfdoc dict including current action list and editable field list msg = wf.get_full_wfdoc_as_dict('dv22') self.assertTrue('dk1' in msg.get('current_edit_fields')) self.assertTrue('wfaction3' in msg.get('current_actions')) ###WITH R5 ROLE SEE HOLDDOC IS CREATED # testconf.testwfc.request_id = str(uuid.uuid4()) # testconf.testwfc.roles= ['r3'] # wf = Workflow('doctype2', wfc=testconf.testwfc) ############################################################## ############document was created as tsp="org1", division="division1" ###field to wfc mapping was tsp field maps to org for role r1 ###and divison maps to ou for role r3 testconf.testwfc.org = "org2" testconf.testwfc.orgunit = "divison1" testconf.testwfc.roles = ['r3'] testconf.testwfc.request_id = str(uuid.uuid4()) wf = Workflow('doctype2', wfc=testconf.testwfc) result = wf.list_wfdoc() self.assertTrue( result[0].get('doc_data').get('division') == 'divison1') ####division1 cant see when the doc is created for divison2 testconf.testwfc.roles = ['r1'] testconf.testwfc.org = 'org1' msg = wf.create_doc({ "dk1": "dv1", "dk2": "dkdiv2", "tsp": "org1", "division": "divison2" }) testconf.testwfc.org = "org2" testconf.testwfc.orgunit = "divison1" testconf.testwfc.roles = ['r3'] testconf.testwfc.request_id = str(uuid.uuid4()) wf = Workflow('doctype2', wfc=testconf.testwfc) result = wf.list_wfdoc() self.assertTrue(not len(result) == 2) ###TSPorg2 cant see doc created by tsp=org1 testconf.testwfc.roles = ['r1'] testconf.testwfc.org = 'tsporg2' wf = Workflow('doctype2', wfc=testconf.testwfc) result = wf.list_wfdoc() self.assertTrue(not result) ###AT THIS STAGE ACTION 3 IS PERMITTED TO ROLE3 ###Role3 should be able to put some data in save as draft testconf.testwfc.org = "org2" testconf.testwfc.orgunit = "divison1" testconf.testwfc.roles = ['r3'] testconf.testwfc.request_id = str(uuid.uuid4()) wf = Workflow('doctype2', wfc=testconf.testwfc) draft_data = {"dk1": "want_to_save_as_draft"} result = wf.save_as_draft("dv22", draft_data) self.assertTrue( result.get('draft_create_msg').get('status') == "success") self.assertTrue( result.get('wfdoc_update_msg').get('status') == "success") ##get draft data for same role result = wf.get_draft_data_for_role('dv22') self.assertTrue(result.get('dk1') == 'want_to_save_as_draft') ##other are not seeing the draft doc even when queried testconf.testwfc.roles = ['r2'] testconf.testwfc.request_id = str(uuid.uuid4()) wf = Workflow('doctype2', wfc=testconf.testwfc) result = wf.get_draft_data_for_role('dv22') self.assertTrue(not result) #list draft doc result = wf.list_wfdocs_superimposed_by_draft( ) #????????????????????????????????? #TODO: check why this is failing ??????? #self.assertTrue(result[0].get('doc_data').get('dk1') == "want_to_save_as_draft") ##update or action from draft testconf.testwfc.roles = ['r3'] testconf.testwfc.request_id = str(uuid.uuid4()) wf = Workflow('doctype2', wfc=testconf.testwfc) result = wf.action_from_draft('dv22', "wfaction3") self.assertTrue("want_to_save_as_draft" in result.get('message'))
def test_entities(self): m.dbdriver.delete(m.Holddoc) m.dbdriver.delete(m.Wfdocaudit) m.dbdriver.delete(m.Wfdoc) m.dbdriver.delete(m.Wfaction) m.dbdriver.delete(m.Wfstatus) m.dbdriver.delete(m.Datadocfield) m.dbdriver.delete(m.Doctype) docrepo = DomainRepo("Wfdoc") ###########REGISTER DOCTYPE doctype1 = ent.Doctype("doctype1", "dk1", ["r1"]) doctype2 = ent.Doctype("doctype2", "dk2", ["r1"]) lodobj = [doctype1, doctype2] doctype_repo = DomainRepo("Doctype") msg = doctype_repo.add_list_of_domain_obj(lodobj) self.assertTrue(msg['message'] == "has been registered") ########REGISTER ACTION RULES wfaction1_dict = { "name": "wfaction1", "associated_doctype": { "name": "doctype1" }, "need_prev_status": "s0", "need_current_status": "s1", "leads_to_status": "s2", "permitted_to_roles": [ "r1", ], "hide_to_roles": [ "r5", ] } wfaction2_dict = { "name": "wfaction2", "associated_doctype": { "name": "doctype2" }, "need_prev_status": "s1", "need_current_status": "s2", "leads_to_status": "s3", "permitted_to_roles": [ "r2", ], "hide_to_roles": [ "r5", ] } wfaction3_dict = { "name": "wfaction3", "associated_doctype": { "name": "doctype2" }, "need_prev_status": "s2", "need_current_status": "s3", "leads_to_status": "s4", "permitted_to_roles": [ "r3", ], "hide_to_roles": [ "r5", ] } wfaction1 = ent.Wfaction.from_dict(wfaction1_dict) wfaction2 = ent.Wfaction.from_dict(wfaction2_dict) wfaction3 = ent.Wfaction.from_dict(wfaction3_dict) lodobj = [wfaction1, wfaction2, wfaction3] action_repo = DomainRepo("Wfaction") msg = action_repo.add_list_of_domain_obj(lodobj) self.assertTrue(msg['message'] == "has been registered") ############RETRIEVE ACTION1 FROM REPO doctype_list_sobj = doctype_repo.list_obj() self.assertTrue(isinstance(doctype_list_sobj[0], m.Doctype)) doctype_list_dobj = doctype_repo.list_domain_obj() self.assertTrue(isinstance(doctype_list_dobj[0], ent.Doctype)) action_list_dict = action_repo.list_dict() self.assertTrue( isinstance(action_list_dict[0]['associated_doctype'], dict)) action_list_sobj = action_repo.list_obj() self.assertTrue(isinstance(action_list_sobj[0], m.Wfaction)) action_list_dobj = action_repo.list_domain_obj() self.assertTrue(isinstance(action_list_dobj[0], ent.Wfaction)) seearchf = {"associated_doctype": {"name": "doctype2"}} action_list_filtered_by_doctype = action_repo.list_domain_obj( **seearchf) self.assertTrue(action_list_filtered_by_doctype[0].associated_doctype. name == 'doctype2') self.assertTrue(action_list_filtered_by_doctype[1].associated_doctype. name == 'doctype2') ####UPDATE RELATTIONSHIP FIELD ACTION1 DOCTYPE FROM 1 TO 2 wfaction1_dict.update({"associated_doctype": {"name": "doctype2"}}) searchf = {"name": "wfaction1"} msg = action_repo.update_from_dict(wfaction1_dict, **searchf) self.assertTrue(msg['status'] == "success") action_list_filtered_by_doctype = action_repo.list_domain_obj( **seearchf) self.assertTrue(len(action_list_filtered_by_doctype) == 3) ####DEFINING FIELDS FOR DOCTYPE2 f1_dict = { "name": "field1", "associated_doctype": { "name": "doctype2" }, "ftype": "str", "flength": 2, "status_needed_edit": ["s3"] } f2_dict = { "name": "field2", "associated_doctype": { "name": "doctype2" }, "ftype": "int", "flength": 2, "status_needed_edit": [""] } docf_repo = repos.DomainRepo("Datadocfield") msg = docf_repo.add_form_lod([f1_dict, f2_dict]) self.assertTrue(msg['status'] == "success") datadocfields_repo = repos.DomainRepo("Datadocfield") searh_filter = {"associated_doctype": {"name": "doctype2"}} result = datadocfields_repo.list_domain_obj(**searh_filter) fnames = [item.name for item in result] self.assertTrue("field1" in fnames) ###CHECK THE ID ATTRIBUTE FROM SQL OBJ HAS BEEN PASSED TO DOMAINOBJ #self.assertTrue(hasattr(action_list_filtered_by_doctype[0], 'id')) doc_data1 = {"field1": "v1", "field2": 10} primval_datadoc = doc_data1["field1"] wfdoc_dict1 = { "name": primval_datadoc, "associated_doctype": { "name": "doctype2" }, "prev_status": "s2", "current_status": "s3", "doc_data": doc_data1, } wfdoc_lod = [wfdoc_dict1] wfdoc_repo = repos.DomainRepo("Wfdoc") msg = wfdoc_repo.add_form_lod(wfdoc_lod) #######RETRIEVE DOC USING PRIMKEY wfdoc_list = wfdoc_repo.list_domain_obj(**{"name": "v1"}) ##########SEE THE COMNNETS above IN CASE OF INPUT TYPE EXCEPTION self.assertTrue(len(wfdoc_list[0].wfactions) == 3) self.assertTrue((wfdoc_list[0].doc_data == doc_data1)) #####FROM DICT CREATE DOMAIN OBJ AND THEN SAVE TO REPO doc_data1 = {"field1": "v2", "field2": 10} primval_datadoc = doc_data1["field1"] wfdoc_dict2 = { "name": primval_datadoc, "associated_doctype": { "name": "doctype2" }, "prev_status": "s2", "current_status": "s3", "doc_data": doc_data1, } wfdoc2 = ent.Wfdoc.from_dict(wfdoc_dict2) ###ADD THE DOMAIN OBJECT TO THE DOMAIN REPO msg = wfdoc_repo.add_list_of_domain_obj([wfdoc2]) self.assertTrue(msg['message'] == "has been registered") ###SEE DOCTYPE2 HAVE THE DOCDATAFIELDS doctype2Obj_list = doctype_repo.list_domain_obj(**{"name": "doctype2"}) ###CREATE DOC ONCE ITS FIELDS ARE DEFINED ABOVE doc_data3 = {"field1": "v3", "field2": 10} wfdoc_dict3 = { "name": 'v3', "associated_doctype": { "name": "doctype2" }, "prev_status": "", "current_status": "Created", "doc_data": doc_data3, } ###FAIL FOR FIELD NAME MISTACH try: ent.Wfdoc.from_dict(wfdoc_dict3) except rexc.UnknownFieldNameInDataDoc as e: self.assertTrue(e.status == "UnknownFieldNameInDataDoc") ##FAILURE FOR FIELD LENGTH LARGER THAN CONFIGURED doc_data3 = {"field1": "v44444", "field2": 10} wfdoc_dict3.update({"doc_data": doc_data3}) try: ent.Wfdoc.from_dict(wfdoc_dict3) except rexc.DataLengthViolation as e: self.assertTrue(e.status == "DataLengthViolation") ####FAIL FOR FIELD TYPE, FIELD2 SHOULD BE INT TYPE wfdoc_dict3.update({ "name": "v3", "doc_data": { "field1": "v3", "field2": "v2" } }) try: ent.Wfdoc.from_dict(wfdoc_dict3) except rexc.DataTypeViolation as e: self.assertTrue(e.status == "DataTypeViolation") ###########CHECK SUCCESS wfdoc_dict3.update({ "name": "v3", "doc_data": { "field1": "v3", "field2": 10 } }) docobj = ent.Wfdoc.from_dict(wfdoc_dict3) self.assertTrue(docobj.name == "v3")
def _list_from_wfdoc(self, wfc_filter:dict=None): wfdoc_repo = DomainRepo('Wfdoc') search_f = {"associated_doctype_name": self.doctype_name} lst = wfdoc_repo.list_dict(**search_f) if wfc_filter: lst = self._filter_by_wfc_on_doc_data(lst, wfc_filter) return lst
def _register_doctype_n_actions(self): m.dbdriver.delete(m.Draftdata) m.dbdriver.delete(m.Holddoc) m.dbdriver.delete(m.Wfdocaudit) m.dbdriver.delete(m.Wfdoc) m.dbdriver.delete(m.Wfaction) m.dbdriver.delete(m.Wfstatus) m.dbdriver.delete(m.Datadocfield) m.dbdriver.delete(m.Doctype) tspinvoice = ent.Doctype("tspinvoice", "InvoiceNo", ['role1']) lodobj = [tspinvoice] doctype_repo = DomainRepo("Doctype") doctype_repo.add_list_of_domain_obj(lodobj) ####DEFINING FIELDS FOR tspinvoice InvoiceNo = { "name": "InvoiceNo", "associated_doctype": { "name": "tspinvoice" }, "ftype": "str", "flength": 25, "status_needed_edit": ["", "NewBorn"], #this should be status not role "wfc_filter": "", "wfc_filter_to_roles": [] } Action = { "name": "Action", "associated_doctype": { "name": "tspinvoice" }, "ftype": "str", "flength": 25, "status_needed_edit": [""], "wfc_filter": "", "wfc_filter_to_roles": [] } TSP = { "name": "TSP", "associated_doctype": { "name": "tspinvoice" }, "ftype": "str", "flength": 25, "status_needed_edit": [""], "wfc_filter": "org", "wfc_filter_to_roles": ['r1'] } Division = { "name": "Division", "associated_doctype": { "name": "tspinvoice" }, "ftype": "str", "flength": 25, "status_needed_edit": [""], "wfc_filter": "ou", "wfc_filter_to_roles": ['r3'] } InfoID = { "name": "InfoID", "associated_doctype": { "name": "tspinvoice" }, "ftype": "str", "flength": 25, "status_needed_edit": [""], "wfc_filter": "", "wfc_filter_to_roles": [''] } CircuitID = { "name": "CircuitID", "associated_doctype": { "name": "tspinvoice" }, "ftype": "str", "flength": 25, "status_needed_edit": [""], "wfc_filter": "", "wfc_filter_to_roles": [''] } Speed = { "name": "Speed", "associated_doctype": { "name": "tspinvoice" }, "ftype": "str", "flength": 25, "status_needed_edit": [""], "wfc_filter": "", "wfc_filter_to_roles": [] } ARC = { "name": "ARC", "associated_doctype": { "name": "tspinvoice" }, "ftype": "str", "flength": 25, "status_needed_edit": [""], "wfc_filter": "", "wfc_filter_to_roles": [] } ServiceType = { "name": "ServiceType", "associated_doctype": { "name": "tspinvoice" }, "ftype": "str", "flength": 25, "status_needed_edit": [""], "wfc_filter": "", "wfc_filter_to_roles": [] } SiteID = { "name": "SiteID", "associated_doctype": { "name": "tspinvoice" }, "ftype": "str", "flength": 25, "status_needed_edit": [""], "wfc_filter": "", "wfc_filter_to_roles": [] } FullSiteAddress = { "name": "FullSiteAddress", "associated_doctype": { "name": "tspinvoice" }, "ftype": "str", "flength": 50, "status_needed_edit": [""], "wfc_filter": "", "wfc_filter_to_roles": [] } GSTNo = { "name": "GSTNo", "associated_doctype": { "name": "tspinvoice" }, "ftype": "str", "flength": 25, "status_needed_edit": [""], "wfc_filter": "", "wfc_filter_to_roles": [] } BillingDateFrom = { "name": "BillingDateFrom", "associated_doctype": { "name": "tspinvoice" }, "ftype": "str", "flength": 25, "status_needed_edit": [""], "wfc_filter": "", "wfc_filter_to_roles": [] } BillingDateTO = { "name": "BillingDateTO", "associated_doctype": { "name": "tspinvoice" }, "ftype": "str", "flength": 25, "status_needed_edit": [""], "wfc_filter": "", "wfc_filter_to_roles": [] } InvoiceDate = { "name": "InvoiceDate", "associated_doctype": { "name": "tspinvoice" }, "ftype": "str", "flength": 25, "status_needed_edit": [""], "wfc_filter": "", "wfc_filter_to_roles": [] } TaxName = { "name": "TaxName", "associated_doctype": { "name": "tspinvoice" }, "ftype": "str", "flength": 25, "status_needed_edit": [""], "wfc_filter": "", "wfc_filter_to_roles": [] } Total = { "name": "Total", "associated_doctype": { "name": "tspinvoice" }, "ftype": "int", "flength": 25, "status_needed_edit": [""], "wfc_filter": "", "wfc_filter_to_roles": [] } REMARKS = { "name": "REMARKS", "associated_doctype": { "name": "tspinvoice" }, "ftype": "str", "flength": 100, "status_needed_edit": [""], "wfc_filter": "", "wfc_filter_to_roles": [] } docf_repo = DomainRepo("Datadocfield") docf_repo.add_form_lod([ InvoiceNo, Action, TSP, Division, InfoID, CircuitID, Speed, ARC, ServiceType, SiteID, FullSiteAddress, GSTNo, BillingDateFrom, BillingDateTO, InvoiceDate, TaxName, Total, REMARKS ]) wfcaction_create = { "name": "Create", "associated_doctype": { "name": "tspinvoice" }, #"need_prev_status": "NewBorn", "need_current_status": ["NewBorn"], "leads_to_status": "Created", "permitted_to_roles": [ "role1", ], "hide_to_roles": ["r7"], "undo_prev_hide_for": [], } wfaction1_dict = { "name": "wfaction1", "associated_doctype": { "name": "tspinvoice" }, #"need_prev_status": "NewBorn", "need_current_status": ["Created"], "leads_to_status": "s1", "permitted_to_roles": [ "r1", ], "hide_to_roles": ["r4", "r5"], "undo_prev_hide_for": [], } wfaction2_dict = { "name": "wfaction2", "associated_doctype": { "name": "tspinvoice" }, #"need_prev_status": "Created", "need_current_status": ["s1"], "leads_to_status": "s2", "permitted_to_roles": [ "r2", ], "hide_to_roles": ["r5", "r6"], "undo_prev_hide_for": [ "r4", ], #r4 hold doc shold be deleted but r5 to be retained } wfaction3_dict = { "name": "wfaction3", "associated_doctype": { "name": "tspinvoice" }, #"need_prev_status": "s1", "need_current_status": ["s2"], "leads_to_status": "s3", "permitted_to_roles": [ "r3", ], "hide_to_roles": [ "r1", ], "undo_prev_hide_for": ["r5", "r6"], } wfaction4_dict = { "name": "wfaction4", "associated_doctype": { "name": "tspinvoice" }, #"need_prev_status": "s2", "need_current_status": ["s3"], "leads_to_status": "s4", "permitted_to_roles": [ "r3", ], "hide_to_roles": [ "r5", ], "undo_prev_hide_for": [], } wfactionCreate = ent.Wfaction.from_dict(wfcaction_create) wfaction1 = ent.Wfaction.from_dict(wfaction1_dict) wfaction2 = ent.Wfaction.from_dict(wfaction2_dict) wfaction3 = ent.Wfaction.from_dict(wfaction3_dict) lodobj = [wfactionCreate, wfaction1, wfaction2, wfaction3] action_repo = DomainRepo("Wfaction") action_repo.add_list_of_domain_obj(lodobj)
def test_workflow(self): m.dbdriver.delete(m.Wfdoc) m.dbdriver.delete(m.Wfaction) m.dbdriver.delete(m.Wfstatus) m.dbdriver.delete(m.Datadocfield) m.dbdriver.delete(m.Doctype) self._register_doctype_n_actions() wf = Workflow('doctype2', 'r1') ##create should fail when primary key fields in datadoc is not in rule try: wf.create_doc({ "dk1": "dv1", "dk2-nonprim": "dv2", }, 'r1') except Exception as e: self.assertTrue(e.status == "PrimaryKeyNotPresentInDataDict") ##Fail when fields dk1 is not string try: wf.create_doc({ "dk1": 100, "dk2": "dv2", }, 'r1') except Exception as e: self.assertTrue(e.status == "DataTypeViolation") ##Fail when fields dk3 is not present in the rule at all try: wf.create_doc({ "dk3": "not defined in the rule", "dk2": "dv2", }, 'r1') except Exception as e: self.assertTrue(e.status == "UnknownFieldNameInDataDoc") ### WORKFLOW IS ABLE TO CREATE DOC msg = wf.create_doc({ "dk1": "dv1", "dk2": "dv2", }, 'r1') self.assertTrue(msg['message'] == "has been registered") ####ABLE TO RETRIEVE THE BY THE PRIMKEY AS DEFINED IN THE DOCTYPE doc_repo = DomainRepo("Wfdoc") wfdocObj_list = doc_repo.list_domain_obj(name="dv2") self.assertTrue(wfdocObj_list[0].name == "dv2") ####UPDATE DOC STATUS AS PER THE ACTION RULE msg = wf.action_change_status("dv2", "wfaction1", {"dk2": "dv2"}) ### check that self._validate_editable_fields(wfdocObj, data) working self.assertTrue(msg['status'] == "success") ###wdoc should be able to understand that dk2 is editable and dk1 is not self.assertTrue( "dk2" in wfdocObj_list[0].editable_fields_at_current_status) self.assertTrue( "dk1" not in wfdocObj_list[0].editable_fields_at_current_status) ####SHOULD FAIL FOR INCORRECT ROLE wf = Workflow('doctype2', 'r1') try: msg = wf.action_change_status("dv2", "wfaction2") except rexc.RoleNotPermittedForThisAction as err: self.assertTrue(err.status == "RoleNotPermittedForThisAction") ###SHOULD PASS THE ROLE AND THE RULE wf = Workflow('doctype2', 'r2') msg = wf.action_change_status("dv2", "wfaction2") self.assertTrue(msg['status'] == "success") ####HAVE A TEST FOR RULE STATUS VALIDATION FAILURE try: msg = wf.action_change_status("dv2", "wfaction1") except rexc.WorkflowActionRuleViolation as err: self.assertTrue(err.status == "WorkflowActionRuleViolation") ####WFDOC SHOULD HAVE actions_for_current_stattus actions_for_current_status = wfdocObj_list[ 0].actions_for_current_status self.assertTrue(actions_for_current_status == ['wfaction1']) ###fail due to data having non editable field dk1 ###develop logic to check if the data has actually changed wf = Workflow('doctype2', 'r3') try: wf.action_change_status("dv2", "wfaction3", { "dk1": "dv1", "dk2": "dv2" }) except Exception as e: self.assertTrue(e.status == "EditNotAllowedForThisField")