Skip to content

A generic, light-weight and extensible Workflow Engine for agile automation of Business Processes | Django, Python

License

Notifications You must be signed in to change notification settings

smaisidoro/ActivFlow

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

95 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

activflow

Build Status Coverage Status Code Health Codacy Badge Code Issues

Introduction

ActivFlow is a generic, light-weight and extensible workflow engine for agile development and automation of complex Business Process operations.

Developers can emphasize towards mapping the Business Process model as ActivFlow workflow without having to worry about implementing the core workflow processing logic. The generic implementation of the workflow engine manages the automation of the Business Processes from start to finish in accordance with the defined flow.

What is an ActivFlow workflow?

  • Business Process flow mapped as ActivFlow configuration
  • Definition of data to be captured for each activity (state)
  • Business Roles mapped to workflow activities
  • Rules applied on transitions between activities

alt tag

Technology Stack

  • Python 2.7x, 3.4x, 3.5x
  • Django 1.9x
  • Bootstrap 3.x

Usage & Configuration

Step 1: Workflow App Registration

  • A Business Process must be represented in terms of a Django app
  • All apps must be registered to WORKFLOW_APPS under core/constants
WORKFLOW_APPS = ['leave_request']

Step 2: Activity Configuration

  • Activities (States/Nodes) are represented as Django models
  • Activity must inherit from AbstractInitialActivity/AbstractActivity respectively
  • Custom validation logic must be defined under clean() on the activity model
  • Custom field specific validation should go under app/validator and applied to the field as validators attribute
from activflow.core.models import AbstractActivity, AbstractInitialActivity
from activflow.leave_request.validators import validate_initial_cap

class RequestInitiation(AbstractInitialActivity):
    """Leave request details"""
    employee_name = CharField("Employee", max_length=200, validators=[validate_initial_cap])
    from = DateField("From Date")
    to = DateField("To Date")
    reason = TextField("Purpose of Leave", blank=True)

    def clean(self):
        """Custom validation logic should go here"""
        pass

class ManagementApproval(AbstractActivity):
    """Management approval"""
    approval_status = CharField(verbose_name="Status", max_length=3, choices=(
        ('APP', 'Approved'), ('REJ', 'Rejected')))
    remarks = TextField("Remarks")

    def clean(self):
        """Custom validation logic should go here"""
        pass

Step 3: Flow Definition

  • A flow is represented by collection of Activities (States/Nodes) connected using Transitions (Edges)
  • Rules are applied on transitions to allow routing between activities, provided, the condition satisfies
  • Business Process flow must be defined as FLOW under app/flow
  • As a default behavior, the Role maps OTO with django Group (developers, feel free to customize)
from activflow.leave_request.models import RequestInitiation, ManagementApproval
from activflow.leave_request.rules import validate_request

FLOW = {
    'initiate_request': {
        'name': 'Leave Request Initiation',
        'model': RequestInitiation,
        'role': 'Submitter',
        'transitions': {
            'management_approval': validate_request,
        }
    },
    'management_approval': {
        'name': 'Management Approval',
        'model': ManagementApproval,
        'role': 'Approver',
        'transitions': None
    }
}

INITIAL = 'initiate_request'

Step 4: Business Rules

  • Transition rules and conditions must be defined under app/rules
def validate_request(self):
    return self.reason == 'Emergency'

Step 5: Configure Field Visibility & Custom Forms (Optional)

  • Include config.py in the workflow app and define ACTIVITY_CONFIG as Nested Ordered Dictionary to have more control over what gets displayed on the UI.
  • Define for each activity model, the visibility of fields, for display on templates and forms
    • create: field will appear on activity create/initiate form
    • update: field will be available for activity update/revise operation
    • display: available for display in activity detail view
from collections import OrderedDict as odict

ACTIVITY_CONFIG = odict([
    ('RequestInitiation', odict([
        ('subject', ['create', 'update', 'display']),
        ('employee_name', ['create', 'update', 'display']),
        ('from', ['create', 'update', 'display']),
        ('to', ['create', 'update', 'display']),
        ('reason', ['create', 'update', 'display']),
        ('creation_date', ['display']),
        ('last_updated', ['display'])
    ])),
    ...
    ...
])

# register fields that need WYSIWYG editor

WYSIWYG_CONFIG = {
    'RequestInitiation': ['reason']
}

# register custom forms

FORM_CONFIG = {
    'RequestInitiation': 'CustomRequestForm'
}

Step 6: Access/Permission Configuration (Optional)

The core logic to restrict access is defined as AccessDeniedMixin under core/mixins which developers can customize depending on the requirements

Demo Instructions

Execute the below command to configure ActivFlow for demo purpose

python demo.py

Submitter: john.doe/12345, Reviewer: jane.smith/12345

About

A generic, light-weight and extensible Workflow Engine for agile automation of Business Processes | Django, Python

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Python 75.9%
  • HTML 23.4%
  • JavaScript 0.7%