Last active
August 29, 2015 14:02
-
-
Save mariocesar/882e911d8863dbc738b2 to your computer and use it in GitHub Desktop.
Workflow Model Helper for Django
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from django.db import models | |
from .workflow import Workflow, StateField | |
class SaleOrder(Workflow, models.Model): | |
DRAFT = 'draft' | |
QUOTATION = 'quotation' | |
CONFIRMED = 'confirmed' | |
PROCESSING = 'processing' | |
CANCEL = 'cancel' | |
DONE = 'done' | |
ORDER_STATES = ( | |
(DRAFT, 'Draft'), | |
(QUOTATION, 'Quotation'), | |
(CONFIRMED, 'Confirmed'), | |
(PROCESSING, 'Processing'), | |
(CANCEL, 'Cancel'), | |
(DONE, 'Done') | |
) | |
state = StateField(choices=ORDER_STATES, default=DRAFT) | |
_transitions = ( | |
((DRAFT, QUOTATION), 'Send Quotation'), | |
((QUOTATION, CONFIRMED), 'Confirm Sale'), | |
((CONFIRMED, PROCESSING), 'Process'), | |
((PROCESSING, PROCESSING), 'Process'), # To Force an update | |
((PROCESSING, DONE), 'Sale'), | |
((DONE, PROCESSING), 'Update'), | |
((DRAFT, CANCEL), 'Cancel'), | |
((QUOTATION, CANCEL), 'Canel'), | |
((QUOTATION, DRAFT), 'Revert as Draft'), | |
((CANCEL, DRAFT), 'Cancel') | |
) | |
@Workflow.transition(CANCEL) | |
def cancel(self, context): | |
pass | |
@Workflow.transition(DRAFT) | |
def draft(self, context): | |
pass | |
@Workflow.transition(QUOTATION) | |
def quote(self, context): | |
pass | |
@Workflow.transition(CONFIRMED) | |
def confirm(self, context): | |
pass | |
@Workflow.transition(PROCESSING) | |
def proceed(self, context): | |
pass | |
@Workflow.transition(DONE) | |
def do(self, context): | |
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from django.db.models import CharField | |
from functools import wraps | |
class Workflow: | |
_state_field_name = 'state' | |
_transitions = None | |
@staticmethod | |
def transition(state): | |
"""Decorador para transicion""" | |
def check_transition(func): | |
@wraps(func) | |
def wrapper(self, context=None, *args, **kwargs): | |
current_state = self.get_current_state() | |
# actionable transition | |
transition = (current_state, state) | |
if self._transitions: | |
# If the transition is declared we will apply | |
for transition, label in self._transitions: | |
if transition in self._transitions: | |
return func(self, context) | |
return wrapper | |
return check_transition | |
def get_current_state(self): | |
return getattr(self, self._state_field_name) | |
def get_available_transitions(self): | |
current_state = self.get_current_state() | |
state_field = self._meta.get_field(self._state_field_name) | |
current_state_label = dict(state_field.flatchoices).get(current_state, current_state) | |
available_transitions = [(current_state, current_state_label)] | |
for transition, label in self._transitions: | |
step, next_state = transition | |
if next_state not in available_transitions and step == current_state: | |
available_transitions.append((next_state, label)) | |
return available_transitions | |
class StateField(CharField): | |
def __init__(self, *args, **kwargs): | |
kwargs['max_length'] = 20 | |
kwargs['db_index'] = True | |
kwargs['null'] = False | |
kwargs['blank'] = False | |
super(CharField, self).__init__(*args, **kwargs) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment