Generic, light-weight & extensible Workflow Engine for agile automation of Business Processes | Django, Python
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?
WORKFLOW_APPS = ['leave_request']
from activflow.core.models import AbstractActivity, AbstractInitialActivity, AbstractEntity
from activflow.leave_request.validators import validate_initial_cap
class SampleRequest(AbstractInitialActivity):
"""Sample 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 Itinerary(AbstractEntity):
"""Itinerary details"""
request = ForeignKey(RequestInitiation, related_name="itineraries")
destination = CharField("Destination", max_length=200)
date = DateField("Visit Date")
def clean(self):
"""Custom validation logic should go here"""
pass
class ManagementReview(AbstractActivity):
"""Management review/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
from activflow.leave_request.models import SampleRequest, ManagementReview
from activflow.leave_request.rules import validate_request
FLOW = {
'sample_leave_request': {
'name': 'Sample Request',
'model': SampleRequest,
'role': 'Submitter',
'transitions': {
'management_review': validate_request,
}
},
'management_review': {
'name': 'Management's Review',
'model': ManagementReview,
'role': 'Approver',
'transitions': None
}
}
INITIAL = 'sample_leave_request'
def validate_request(self):
return self.reason == 'Emergency'
from collections import OrderedDict
ACTIVITY_CONFIG = OrderedDict([
('Foo', OrderedDict([
('Fields', OrderedDict([
('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'])
])),
('Relations', OrderedDict([
('Itinerary', OrderedDict([
('destination', ['create', 'update', 'display']),
('date', ['create', 'update', 'display'])
])),
...
]))
])),
...
])
# register fields that need WYSIWYG editor
WYSIWYG_CONFIG = {
'RequestInitiation': ['reason']
}
# register custom forms
FORM_CONFIG = {
'RequestInitiation': 'CustomRequestForm'
}
The core logic to restrict access is defined as AccessDeniedMixin under core/mixins which developers can customize depending on the requirements
Execute the below command to configure ActivFlow for demo purpose
python demo.py
Alternatively, launch the docker containers by simply running
docker-compose up
Submitter: john.doe/12345, Reviewer: jane.smith/12345