20120616

Zum Thema “Workflows”. Darunter verstehen wir die Möglichkeit, dass der Systemverwalter per UI eine Liste von lokal konfigurierbaren “Statuswechsel-Aktionen” verwaltet. Eine Tabelle, die besagt: “Wer was wann klicken darf”.

Eine Workflow-Aktion (kurz Workflow) tut zunächst mal nichts anderes, als den Status eines Objekts zu wechseln. Wie das Objekt auf einen Statuswechsel reagiert (also was daraufhin eventuell noch alles tut), das ist anwendungsspezifisch und Programmierersache (d.h. dazu muss man Python-Code schreiben).

Der Benutzer sieht die Workflows eines Objekts als eine (virtuelle) Kolonne, deren Inhalt eine Serie von anklickbaren Buttons ist. In dieser Liste stehen natürlich nur die Workflows, die der ausführen darf. Sie ist dynamisch und hängt vom aktuellen Status des Objekts ab.

Workflows-Aktionen

Modell

Bezeichnung

Wer darf

Status vorher

Status nachher

cal.Task

Erledigt

Eigentümer

todo

done

cal.Task

Zurück

Dienstleiter

done

todo

cal.Event

Einladungen schicken

Eigentümer

geplant

scheduled

cal.Event

Absagen

Eigentümer

geplant

cancelled

cal.Event

Stattgefunden

Eigentümer

geplant

stattgefunden

cal.Event

Abgesagt

Eigentümer

geplant

cancelled

cal.Event

Bericht verfassen

Alle

stattgefunden

bericht

cal.Event

Bericht verfassen

Eigentümer

stattgefunden

done

“Wer darf” ist eigentlich eine Kombination von drei Feldern:

  • user_level : man muss mindestens diesen Benutzerlevel haben

  • user_groups : man muss mindestens einer dieser Gruppen angehören

  • owned_only : falls angekreuzt, gilt diese Aktion nur für “meine” Objekte (Datensätze)

Die Auswahlliste der möglichen Zustände (Statusse) ist ebenfalls anwendungsspezifisch, aber Programmierersache (d.h. dazu muss man Python-Code schreiben).

Entwurf Modell:

from lino.utils import ViewPermission

class Workflow(babel.BabelNamed,mixins.Sequenced):
    class Meta:
        sort_order = ['content_type','seqno']

    content_type = ForeignKey(ContentType)
    user_level = UserLevel.field()
    user_groups = CharField
    owned_only = BooleanField
    from_state = CharField
    to_state = CharField

    def get_permission(self,user):
        vp = ViewPermission(required_user_level=self.user_level,
          required_user_groups=self.user_groups.split())
        return vp.get_view_permission(user)



class Workflowable(models.Model):
    class Meta:
        abstract = True

    workflow_state_field = 'state' # subclasses usually override this

    @dd.displayfield
    def workflows(self,ar):
        ct = ContentType.objects.get_for_model(self.__class__)
        for wf in Workflow.objects.filter(content_type=ct):
            if wf.get_permission(ar.get_user())

“Status” or “State”?

The Introduction to Plone workflows speaks about “states” and never uses the word “status”. I am rather used to call it a “status”. Who’s right?

  • “a state is any condition which is durable or lasting (Zustand, Istzustand) whereas a status is a classification of state among several well-defined possibilities. An immigrant’s status is either legal or illegal, and if he is the latter, he may be in an anxious emotional state.” (konungursvia on wordreference.com

  • “State generally refers to the entire state of an entity - all its values and relationships at a particular point in time (usually, current). Status is more of a time-point, say, where something is at in a process or workflow - is it dirty (therefore requiring saving), is it complete, is it pending input, etc” (Luke Schafer on stackoverflow)

Conclusion for Lino. I suggest to adapt the following convention: use “state” at least when this field is being used as workflow selector. The default value for lino.models.Workflowable.workflow_state_field).

Changes in lino_xl.lib.cal

Replaced the models GuestStatus, TaskStatus and EventStatus by the choicelists GuestState, TaskState and EventState.