class HelloWorldFlow(Flow): process_class = HelloWorldProcess start = (flow.Start(CreateProcessView, fields=["text"]).Permission(auto_create=True).Next( this.approve)) approve = (flow.View(UpdateProcessView, fields=[ "approved" ]).Permission(auto_create=True).Next(this.check_approve)) check_approve = ( flow.If(lambda activation: activation.process.approved).Then( this.send).Else(this.end)) send = (flow.Handler(this.send_hello_world_request).Next(this.end)) end = flow.End() def send_hello_world_request(self, activation): print(activation.process.text)
class HelloWorldFlow(Flow): process_cls = models.HelloWorldProcess lock_impl = lock.select_for_update_lock start = flow.Start(StartProcessView, fields=["text"]) \ .Permission(auto_create=True) \ .Next(this.approve) approve = flow.View(ProcessView, fields=["approved"]) \ .Permission(auto_create=True) \ .Next(this.check_approve) check_approve = flow.If(cond=lambda p: p.approved) \ .OnTrue(this.send) \ .OnFalse(this.end) send = celery.Job(tasks.send_hello_world_request) \ .Next(this.end) end = flow.End()
class DynamicSplitFlow(Flow): """ Dynamic split Depends on initial decision, several instances on make_decision task would be instanciated """ process_cls = models.DynamicSplitProcess start = flow.Start(flow_views.StartProcessView, fields=['split_count']) \ .Permission(auto_create=True) \ .Next(this.spit_on_decision) spit_on_decision = DynamicSplit(lambda p: p.split_count) \ .Next(this.make_decision) make_decision = flow.View(views.DecisionView) \ .Next(this.join_on_decision) join_on_decision = flow.Join() \ .Next(this.end) end = flow.End()
class LeaveFlow(Flow): process_class = LeaveProcess summary_template = "{{ process.leave.req_by.user.username }}的请假" process_title = '请假' start = (flow.Start(LeaveStartView).Permission(auto_create=True).Next( this.dep_approve)) dep_approve = ( flow.View(approve_check).Assign( #提交到自己的manager lambda act: act.process.leave.req_by.Manager.user).Next( this.check_dep_approve)) check_dep_approve = ( flow.If(lambda activation: activation.process.dep_approved == 1).Then( this.hr_approve).Else(this.NG)) hr_approve = ( flow.View(approve_check).Permission( #有权限就可以签收,给特定的人赋权就可以。 auto_create=True).Next(this.check_hr_approve)) check_hr_approve = ( flow.If(lambda activation: activation.process.hr_approved == 1).Then( this.OK).Else(this.NG)) NG = (flow.Handler(this.send_NG_request).Next(this.end)) OK = (flow.Handler(this.send_OK_request).Next(this.end)) end = flow.End() def send_NG_request(self, activation): print('dep_approved==>' + str(activation.process.dep_approved)) print('hr_approved==>' + str(activation.process.hr_approved)) print('NG') def send_OK_request(self, activation): #print(activation.process.leave.user) print('OK')
class LparaFlow(Flow): process_class = LparaProcess start = (flow.Start(CreateProcessView, fields=[ "reason", 'ref_table' ]).Permission(auto_create=True).Next(this.approve)) approve = (flow.View(UpdateProcessView, fields=["approved", "appreciation_text" ]).Permission(auto_create=True).Next( this.check_approve)) check_approve = ( flow.If(lambda activation: activation.process.approved).Then( this.send).Else(this.end)) send = (flow.Handler(this.send_hello_world_request).Next(this.end)) end = flow.End() def send_hello_world_request(self, activation): print(activation.process.id)
class MayorOrdinanceFlow(Flow): process_class = DocumentProcess start = ( flow.Start(views.MayorOrdinanceCreateView) .Next(this.document_update) ) document_update = ( flow.View(views.MayorOrdinanceUpdateView) .Assign(lambda activation: activation.process.get_owner()) .Next(this.end) ) go_to_next_stage = ( flow.If(cond=lambda activation: activation.process.go_to_next_stage) .Then(this.end) .Else(this.document_update) ) end = ( flow.End() )
class CheckRequestFlow(Flow): process_class = CheckRequestProcess start = ( flow.Start( CreateProcessView, fields=["text", "department"] ).Permission( auto_create=True ).Next(this.approve) ) approve = ( flow.View( UpdateProcessView, fields=["approved"] ).Permission( auto_create=True ).Next(this.check_approve) ) check_approve = ( flow.If(lambda activation: activation.process.approved) .Then(this.send) .Else(this.end) ) send = ( flow.Handler( this.send_check ).Next(this.end) ) end = flow.End() def send_check(self, activation): print(activation.process.text)
class HelloWorldFlow(Flow): """ Hello world This process demonstrates hello world approval request flow. """ process_class = HelloWorldProcess lock_impl = lock.select_for_update_lock summary_template = "'{{ process.text }}' message to the world" start = ( flow.Start( flow_views.CreateProcessView, fields=['text']) .Permission(auto_create=True) .Next(this.approve) ) approve = ( flow.View( flow_views.UpdateProcessView, fields=['approved'], task_description="Message approvement required", task_result_summary="Messsage was {{ process.approved|yesno:'Approved,Rejected' }}") .Permission(auto_create=True) .Next(this.check_approve) ) check_approve = ( flow.If(cond=lambda act: act.process.approved) .Then(this.send) .Else(this.end) ) send = celery.Job(send_hello_world_request).Next(this.end) end = flow.End()
class OrderFlow(Flow): """ Order fulfilment Verify customers and send ordered items. """ process_class = models.OrderProcess lock_impl = lock.select_for_update_lock start = flow.Start(CreateProcessView, form_class=forms.OrderForm).Next(this.verify_customer) verify_customer = flow.Subprocess(CustomerVerificationFlow.start).Next( this.check_verify) check_verify = flow.If( cond=lambda act: models.CustomerVerificationProcess.objects.get( parent_task__status=STATUS.DONE, parent_task__process=act.process). trusted).Then(this.prepare_items).Else(this.end) prepare_items = flow.NSubprocess( OrderItemFlow.start, lambda p: p.orderitem_set.all()).Next(this.end) end = flow.End()
class VacationApprovalFlow(Flow): process_class = VacationApproval lock_impl = lock.no_lock process_description = 'Vacation Approval Request' label = 'vacation' flow_label = 'vacation' start = ( flow.Start( CreateProcessView, task_title='Request a vacation') .Permission('auth.no_permission') .Next(this.fill) ) fill = ( flow.View( FillVacationView, task_title='Fill your vacation details') .Permission('auth.no_permission') .Assign(lambda a: a.process.created_by) .Next(this.split) ) split = ( flow.Split() .Next( this.renew, cond=lambda act: act.process.vacation.requires_renewal()) .Always(this.approve) ) renew = ( flow.View( RenewPassportView, task_title='Renew this passport expiry date', ) .Permission('auth.can_renew_passport') .Assign(lambda a: User.objects.get(username='******')) .Next(this.join_) ) update = ( flow.View( UpdateVacationView, task_title='Update your vacation details') .Permission('auth.no_permission') .Assign(lambda a: a.process.created_by) .Next(this.approve) ) approve = ( flow.View( ApproveVacationView, task_title='Approve this vacation request', ) .Permission('auth.can_approve') .Next(this.check_approval) ) check_approval = ( flow.If(lambda a: a.task.process.vacation.is_approved()) .Then(this.join_) .Else(this.update) ) join_ = ( flow.Join() .Next(this.end) ) end = flow.End()
class ShipmentFlow(Flow): process_class = ShipmentProcess task_class = ShipmentTask lock_impl = CacheLock() summary_template = """ Shipment {{ process.shipment.shipmentitem_set.count }} items to {{ process.shipment.first_name }} {{ process.shipment.last_name }} / {{ process.shipment.city }} """ start = (flow.Start( views.start_view).Permission('shipment.can_start_request').Next( this.split_clerk_warehouse)) # clerk split_clerk_warehouse = (flow.Split().Next(this.shipment_type).Next( this.package_goods)) shipment_type = (flow.View(views.ShipmentView, fields=["carrier"], task_description="Carrier selection").Assign( lambda act: act.process.created_by).Next( this.delivery_mode)) delivery_mode = (flow.If( cond=lambda act: act.process.is_normal_post()).Then( this.check_insurance).Else(this.request_quotes)) request_quotes = (flow.View(views.ShipmentView, fields=[ "carrier_quote" ]).Assign(lambda act: act.process.created_by).Next( this.join_clerk_warehouse)) check_insurance = (flow.View(views.ShipmentView, fields=[ "need_insurance" ]).Assign(lambda act: act.process.created_by).Next( this.split_on_insurance)) split_on_insurance = (flow.Split().Next( this.take_extra_insurance, cond=lambda act: act.process.need_extra_insurance()).Always( this.fill_post_label)) fill_post_label = (flow.View(views.ShipmentView, fields=[ "post_label" ]).Assign(lambda act: act.process.created_by).Next(this.join_on_insurance)) join_on_insurance = (flow.Join().Next(this.join_clerk_warehouse)) # Logistic manager take_extra_insurance = (flow.View(views.InsuranceView).Permission( 'shipment.can_take_extra_insurance').Next(this.join_on_insurance)) # Warehouse worker package_goods = (flow.View(UpdateProcessView).Permission( 'shipment.can_package_goods').Next(this.join_clerk_warehouse)) join_clerk_warehouse = (flow.Join().Next(this.move_package)) move_package = (flow.View(UpdateProcessView).Assign( this.package_goods.owner).Next(this.end)) end = flow.End()
def test_managed_start_view_activation_prepare(self): act = ManagedStartViewActivation() act.initialize(self.init_node(flow.Start()), None) act.prepare(data={'_viewflow_activation-started': '1970-01-01'}) self.assertEqual(act.task.started, datetime(1970, 1, 1, tzinfo=pytz.UTC))
class ResearchFlow(Flow): process_class = ResearchProcess process_title = _("Research Assistant Process") process_description = _( "This process helps researchers to find and analyze papers") lock_impl = lock.select_for_update_lock summary_template = ("Research: '{{ process.research.name }}'") start = (flow.Start(views.StartView).Permission(auto_create=True).Next( this.select_bases)) select_bases = (flow.View( views.BasesView).Permission(auto_create=True).Next(this.search_params)) search_params = (flow.View( views.SearchParams).Permission(auto_create=True).Next(this.approve)) approve = (flow.View( flow_views.UpdateProcessView, fields=['approved'], task_title=('Approve'), task_description=("Research {{ process.text }} approvement required"), task_result_summary=( "Messsage was {{ process.approved }}")).Permission( auto_create=True).Next(this.check_approve)) check_approve = (flow.If(cond=lambda act: act.process.approved, task_title=_('Approvement check')).Then( this.get_metadata).Else(this.end)) get_metadata = (flow.Handler(this.get_papers_metadata, task_title="Getting papers metadata").Next( this.paper_review)) paper_review = (flow.View(views.paper_review).Permission( auto_create=True).Next(this.check_papers_for_review)) check_papers_for_review = (flow.If( cond=lambda act: len(act.process.research.papers.all()) == act.process. research.papers_metadata_analized, task_title=_('Approvement check'), ).Then(this.end).Else(this.paper_review)) end = flow.End(task_title=_('End')) def get_papers_metadata(self, activation): #import ipdb; ipdb.set_trace() logger.info("Starting get metadata function") research = activation.process.research search_params = { 'search_string': research.search_params_string, 'date': research.search_params_date } papers = {} try: os.environ["SD_TOKEN"] except KeyError: print( "Please set the environment variable SD_TOKEN as token for ScienceDirect API" ) sys.exit(1) token = os.environ["SD_TOKEN"] search_bases = research.search_bases.iterator() for base in search_bases: if base.name == "ACM Digital Library": logging.info("Getting ACM papers metadata") acm_search = acm.Acm() papers.update(acm_search.search(search_params)) elif base.name == "ScienceDirect": logging.info("Getting ScienceDirect papers metadata") sd_search = science_direct.ScienceDirect(token) papers.update(sd_search.search(search_params)) for doi in papers.keys(): paper = papers[doi] paper.save() logging.info("Adding paper {}".format(paper.title)) research.papers.add(paper)
class ActivityCalendarFlow(Flow): """ Plotting Activity to Calendar """ process_class = ActivityCalendarProcess task_class = ActivityCalendarTask #lock_impl = select_for_update_lock summary_template = """ Activity {{ process.activity.activity_set.count }} """ start = ( flow.Start(views.CalendarCreateView) .Permission('activity.can_create_activity_request') .Next(this.for_approval) ) for_approval = ( flow.Split() .Next(this.approved_request) .Next(this.revised_request) .Next(this.rejected_request) ) approved_request = ( flow.View( views.CalendarView, task_description="Approval Request" ) .Assign(lambda act: act.process.created_by) .Next(this.check_approve) ) revised_request = ( flow.If( cond=lambda act: act.process.is_revised_activity(), ) .Then(this.check_activity_request) .Else(this.check_approve) ) check_activity_request = ( flow.View(views.RevisedView, fields=['approved']) .Assign(lambda act: act.process.created_by) .Next(this.approved_request) ) rejected_request = ( flow.View(views.CalendarTemplateView) .Next(this.end) ) check_approve = ( flow.If(lambda act: act.process.approved) .Then(this.plot_to_calendar) .Else(this.end) ) plot_to_calendar = ( flow.View( views.CalendarTemplateView ) .Next(this.end) ) end = flow.End()
class TestFlowBaseFlow(Flow): process_cls = TestFlowBaseProcess start = flow.Start(lambda request: None)
class CSFlow(Flow): """ 并行会签demo 动态拆分见作者自带的customnode列子。 """ process_class = cs_process process_title = _('会签') process_description = _('会签演示.') lock_impl = lock.select_for_update_lock summary_template = _("'{{ process.mark }}' 会签") start = (flow.Start(flow_views.CreateProcessView, fields=['file', 'mark', 'version'], task_title=_('新会签')).Permission(auto_create=True).Next( this.split_sign)) split_sign = (flow.Split(task_title=_('并行会签')).Next(this.cfo_sign).Next( this.ceo_sign)) #财务官会签 cfo_sign = (flow.View( flow_views.UpdateProcessView, fields=['file', 'mark', 'cfo_approved'], task_title=_('CFO 会签'), task_result_summary= _("CFO{% ifequal process.cfo_approved '1' %} 同意 {% else %}不同意{% endifequal %}" )).Permission(auto_create=True).Next(this.join_on_sign)) #CEO会签 ceo_sign = (flow.View( flow_views.UpdateProcessView, fields=['file', 'mark', 'ceo_approved'], task_title=_('CEO 会签'), task_result_summary= _("CEO{% if process.ceo_approved == '1' %} 同意 {% else %}不同意{% endif %}" )).Permission(auto_create=True).Next(this.join_on_sign)) join_on_sign = (flow.Join(task_title=_('等待所有会签结束')).Next(this.decision)) #一票否决制。 decision = (flow.If( cond=lambda act: act.process.cfo_approved == '1' and act.process. ceo_approved == '1', task_title=_('会签结果'), task_result_summary= _("会签结果{% if process.ceo_approved == '1' and process.cfo_approved == '1'%} 通过 {% else %}不通过{% endif %}" )).Then(this.OK).Else(this.NG)) NG = (flow.Handler(this.send_NG_request).Next(this.end)) OK = (flow.Handler(this.send_OK_request).Next(this.end)) end = flow.End() def send_NG_request(self, activation): print('ceo_approved==>' + str(activation.process.ceo_approved)) print('cfo_approved==>' + str(activation.process.cfo_approved)) print('NG') def send_OK_request(self, activation): print('OK')
class PurchaseFlow(Flow): obsolete = flow.Obsolete() process_class = PurchaseProcess task_class = PurchaseTask lock_impl = select_for_update_lock process_title = _("Purchase1") summary_template = _("Purchase Form For Gozen Hold") start = (flow.Start( view.StartView).Permission('profile.can_create_purchase').Next( this.support)) support = (flow.View( view.SupportView, task_description=_("Support Team"), ).Permission('profile.can_support_purchase').Next( this.check_support_approve)) check_support_approve = (flow.If( cond=lambda act: act.process.purchase.support_approval == YES, task_title=_('Check Approval of Support'), ).Then(this.price_quote).Else(this.end)) price_quote = (flow.View( view.DoesNeedPriceQuote, task_title=_('Purchase Team Approval For Price Quote'), task_description=_("Does Need Get a Price Quote"), ).Permission('profile.can_purchase_team').Next(this.check_price_quote)) check_price_quote = (flow.If( cond=lambda act: act.process.purchase.need_price_quote == YES, task_title=_('Check Necessity of Price Quote'), ).Then(this.get_price_quote).Else(this.is_superior_approval_required)) get_price_quote = (flow.View( view.GetPriceQuote, task_title=_('Get a Price Quote '), task_description=_("Get a Price Quote"), ).Permission('profile.can_purchase_team').Next( this.is_superior_approval_required)) is_superior_approval_required = (flow.If( cond=lambda activation: activation.process. is_superior_approval_required).Then(this.superior_approval).Else( this.end)) superior_approval = (flow.View( view.SuperiorApprovalCheck, task_title=_('Manager Approve For Purchase'), task_description=_("Approvement is required"), task_result_summary=_( "Purchase was {{ " "process.purchase.superior_approval|yesno:'Approved,Rejected' " "}} by {{process.created_by}}")).Permission( 'profile.can_approve_purchase').Assign( lambda act: act.process.superior_assign()).Next( this.check_superior_approval)) check_superior_approval = (flow.If( cond=lambda act: act.process.purchase.superior_approval == YES, task_title=_('Check Approval of Manager'), ).Then(this.proceed_purchase).Else(this.end)) proceed_purchase = (flow.View( view.ProceedPurchase, task_title=_('Proceed Purchase'), task_description=_('Proceed Purchase'), ).Permission('profile.can_purchase_team').Next(this.end)) end = flow.End()
class ShipmentFlow(Flow): process_cls = ShipmentProcess task_cls = ShipmentTask lock_impl = select_for_update_lock summary_template = """ Shipment {{ process.shipment.shipmentitem_set.count }} items to {{ process.shipment.first_name }} {{ process.shipment.last_name }} / {{ process.shipment.city }} """ start = flow.Start(views.StartView) \ .Permission('shipment.can_start_request') \ .Next(this.split_clerk_warehouse) # clerk split_clerk_warehouse = flow.Split() \ .Next(this.shipment_type) \ .Next(this.package_goods) shipment_type = flow.View(views.ShipmentView, fields=["carrier"], task_description="Carrier selection") \ .Next(this.delivery_mode) \ .Assign(lambda p: p.created_by) delivery_mode = flow.If(cond=lambda p: p.is_normal_post()) \ .OnTrue(this.check_insurance) \ .OnFalse(this.request_quotes) request_quotes = flow.View(views.ShipmentView, fields=["carrier_quote"]) \ .Next(this.join_clerk_warehouse) \ .Assign(lambda p: p.created_by) check_insurance = flow.View(views.ShipmentView, fields=["need_insurance"]) \ .Next('split_on_insurance') \ .Assign(lambda p: p.created_by) split_on_insurance = flow.Split() \ .Next(this.take_extra_insurance, cond=lambda p: p.need_extra_insurance()) \ .Always(this.fill_post_label) fill_post_label = flow.View(views.ShipmentView, fields=["post_label"]) \ .Next(this.join_on_insurance) \ .Assign(lambda p: p.created_by) join_on_insurance = flow.Join() \ .Next(this.join_clerk_warehouse) # Logistic manager take_extra_insurance = flow.View(views.InsuranceView) \ .Next(this.join_on_insurance) \ .Permission('shipment.can_take_extra_insurance') # Warehouse worker package_goods = flow.View(ProcessView.as_view()) \ .Next(this.join_clerk_warehouse) \ .Permission('shipment.can_package_goods') join_clerk_warehouse = flow.Join() \ .Next(this.move_package) move_package = flow.View(ProcessView.as_view()) \ .Next(this.end) \ .Assign(this.package_goods.owner) end = flow.End()
class ChildFlow(Flow): process_class = ChildProcess task_class = ChildTask start = flow.Start(lambda rewquest: None)
class TestFlow(Flow): start = flow.Start().Next(this.end) end = flow.End()
class ListViewTestFlow(Flow): start1 = flow.StartFunction().Next(this.test_task) start2 = flow.Start(lambda request: None).Permission('auth.start_flow_perm').Next(this.test_task) start3 = flow.Start(lambda request: None).Next(this.test_task) test_task = flow.View(lambda request: None).Next(this.end) end = flow.End()
class ViewFlow(Flow): start = flow.Start(start_view).Next(this.task) task = flow.View(task_view).Next(this.end) end = flow.End()
class NoTaskFlow(Flow): start = flow.Start().Next(this.end) end = flow.End()
class SubmissionFlow(Flow): process_class = SubmissionProcess start = flow.Start( CreateProcessView, fields=['label'] ).Permission( auto_create=True ).Next( this.download ) download = flow.View( views.DownloadXLSXTemplateView, ).Assign( this.start.owner ).Next( this.check_download ) check_download = flow.If( lambda activation: activation.process.downloaded ).Then( this.upload ).Else( this.download ) upload = flow.View( views.UploadArchiveView, ).Assign( this.start.owner ).Next( this.check_upload ) check_upload = flow.If( lambda activation: activation.process.uploaded ).Then( this.meta ).Else( this.upload ) meta = flow.Handler( this.parse_meta, activation_class=NotPropagatedExceptionHandlerActivation, ).Next( this.check_meta ) check_meta = flow.If( lambda activation: activation.process.meta is not None ).Then( this.validation ).Else( this.upload ) validation = flow.View( views.ArchiveValidationView, ).Assign( this.start.owner ).Next( this.check_validation ) check_validation = flow.If( lambda activation: activation.process.validated ).Then( this.tags ).Else( this.validation ) tags = flow.View( views.TagsView, ).Assign( this.start.owner ).Next( this.import_archive ) import_archive = AsyncHandler( this.perform_archive_importation, ).Next( this.check_import ) check_import = flow.If( lambda activation: activation.process.imported ).Then( this.end ).Else( this.validation ) end = flow.End() def get_archive_path(self, activation): return Path( settings.MEDIA_ROOT ) / Path( activation.process.archive.name ) def parse_meta(self, activation): archive_path = self.get_archive_path(activation) archive = PixelArchive(archive_path) archive.parse(serialized=True) activation.process.meta = archive.meta activation.process.save() def perform_archive_importation(self, activation): archive_path = self.get_archive_path(activation) process = activation.process pixeler = process.created_by task = process.get_task(self.import_archive) @background.task def async_import_archive(): logger.debug("Async import started…") archive = PixelArchive(archive_path) logger.debug("Archive instanciated") logger.debug("Saving archive…") return archive.save(pixeler=pixeler, submission=process) @background.callback def importation_callback(future): """ We need to force databases connection closing since the background process (in a separated thread) creates a new connection that would never be closed otherwise. """ logger.debug("Background importation callback started…") e = future.exception() logger.debug("Future exception: {} ({})".format(e, type(e))) if e is not None: task.status = STATUS.ERROR task.comments = str(e) task.finished = now() task.save() # Re-raise the exception for lazy logging try: raise e except Exception: logger.exception( "Importation failed! archive: {} (pixeler: {})".format( archive_path, pixeler ) ) logger.debug( "Closing open database connections " "(background callback exception)" ) db.connections.close_all() raise process.imported = True process.save() logger.debug("Submission process updated (imported: True)") logger.debug("Proceeding with activation callback") activation.callback() logger.debug( "Closing open database connections (background callback)" ) db.connections.close_all() logger.debug("Background importation callback done") async_import_archive()
class GrandChildFlow(Flow): process_class = GrandChildProcess start = flow.Start(lambda request: None)
class TestFlow(Flow): start = flow.Start(lambda request: None).Next(this.end) end = flow.End()
class GrandChildFlow(Flow): process_class = TestModelsGrandChildProcess start = flow.Start(lambda rewquest: None)
class BillFlow(Flow): process_class = BillProcess # office register_bill = flow.Start( CreateProcessView, fields=[ 'order_department', 'order_item', 'quantity', 'description' ] ).Permission( auto_create=True ).Next(this.accept_bill) # project manager accept_bill = flow.View( UpdateProcessView, fields=[ 'accepted' ] ).Permission( 'users.can_accept_bill', obj=lambda process: process.billprocess.order_department ).Next(this.check_bill_accept) check_bill_accept = flow.If( lambda act: act.process.accepted ).Then(this.sign_bill).Else(this.incorrect_bill) incorrect_bill = flow.End() # board member sign_bill = flow.View( UpdateProcessView, fields=[ 'signed' ] ).Permission( 'users.can_sign_bill', obj=lambda process: process.billprocess.order_department ).Next(this.check_bill_sign) check_bill_sign = flow.If( lambda act: act.process.signed ).Then(this.validate_bill).Else(this.bill_rejected) bill_rejected = flow.End() # bookkeeping validate_bill = flow.View( UpdateProcessView, fields=[ 'validated' ] ).Permission( 'users.can_validate_bill', obj=lambda process: process.billprocess.order_department ).Next(this.check_bill_valid) check_bill_valid = flow.If( lambda act: act.process.validated ).Then(this.set_bill_paydate).Else(this.accept_bill) pay_bill = flow.View( UpdateProcessView ).Permission( 'users.can_pay_bill', obj=lambda process: process.billprocess.order_department ).Next(this.bill_paid) bill_paid = flow.End() # financial department set_bill_paydate = flow.View( UpdateProcessView, fields=[ 'payment_date' ] ).Permission( 'users.can_set_bill_paydate', obj=lambda process: process.billprocess.order_department ).Next(this.pay_bill)