Objectifs

  • Définir des états et transitions
  • Valider l'enchaînement des états
  • Effectuer des actions lors des transitions
  • Décrire lisiblement la logique métier

Exemple :

example.png

Presenter Notes

Définir un workflow

class TicketWorkflow(xworkflows.Workflow):
    states = [
        ('new', _(u"New")),
        ('assigned', _(u"Assigned")),
        ('closed', _(u"Closed")),
    ]
    transitions = [
        ('assign', ['new'], 'assigned'),
        ('reject', ['assigned'], 'new'),
        ('reassign', ['assigned'], 'assigned'),
        ('close', ['new', 'assigned'], 'closed'),
    ]
    initial_state = 'new'

class Ticket(xworkflows.WorkflowEnabled):
    state = TicketWorkflow()

Presenter Notes

Utiliser un workflow

>>> ticket = MyTicket()
>>> ticket.state
State('new')

>>> ticket.assign()
>>> ticket.state
State('assigned')

>>> ticket.assign()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
InvalidTransitionError: Transition "assign" isn't available from state "assigned"

Presenter Notes

Actions

class Ticket(xworkflows.WorkflowEnabled):
    state = TicketWorkflow()

    @transition()
    def assign(self, to):
        self.assignee = to
>>> ticket = MyTicket()
>>> ticket.state
State('new')

>>> ticket.assign('ponyconseil')
>>> ticket.state
State('assigned')
>>> ticket.assignee
'ponyconseil'

Presenter Notes

Fonctions complémentaires

Pour tester l'état d'un objet

# short for ticket.state == TicketWorkflow.states.new
ticket.state.is_new

Si le nom de la transition est déjà utilisé

class SomeObject(xworkflows.WorkflowEnabled):
    @transition('bar')
    def gobar(self, x):
        if x != 42:
            raise xworkflows.AbortTransition()

Introspection

>>> ticket.state
State('assigned')
>>> ticket.state.transitions
[Transition('reassign'), Transition('close')]

Presenter Notes

Intégration avec Django

  • Appelle automatiquement .save() après chaque transition
class MyModel(django_xworkflows.XWorkflowEnabled):
    state = MyWorkflow()
  • Crée un TransitionLog à chaque transition
>>> MyModel().gobar(log=True, save=True)    # default options
>>> django_xworkflows.TransitionLog.objects.all()
[<TransitionLog(obj, 'gobar')>]

Presenter Notes