Les documents

Modèles

Le modèle Task est le modèle de document de base pour les devis/factures.

Note

D’autres documents ne dérivent pas de Task (ex: factures fournisseur, NDD) ; mais tous dérivent de Node

Un polymorphisme est utilisé pour différencier les différentes Task, celui-ci est fait par le biais de la colonne type_.

Ainsi on obtient les correspondances suivantes:

  • type_=task correspond à un document de base

  • type_=invoice correspond à une facture (Invoice)

  • type_=cancelinvoice correspond à un avoir (CancelInvoice)

  • type_=estimation correspond à un devis (Estimation)

Il est ainsi possible d’effectuer des requêtes sur l’ensemble des devis et des factures grâce à la méthode with_polymorphic

Task.query()\
     .with_polymorphic([Invoice, CancelInvoice, Estimation])\
     .join(Task.phase)\
     .filter(and_(Task.status == 'wait', Phase.name is not None))\
     .order_by(Task.statusDate).all()

Les statuts

Différents statuts peuvent être gérés sur différents documents (héritant de endi.models.node.Node) :

Avertissement

Des chantiers sont en cours sur le sujet, cf #1335 et #1584

  • statut de validation

  • statut de paiement (facture, facture fournisseur)

  • statut de signature (devis)

  • statut de présence des justificatifs (note de dépenses)

L’état actuel du document est stocké sous forme de colonne du modèle concernés :

  • status ou validation_status pour ce qui concerne le statut de validation CAE

  • paid_status pour le statut de paiement

  • signed_status (pour les devis) : pour le statut de signature

D’autres éléments relatifs au dernier statut en date sont également stockés directement en colonne du document.

  • le dernier utilisateur a avoir enregistré un statut (ex: paid_status_user_id)

  • la date du dernier changement de statut (ex: paid_status_date)

Par ailleurs, l’historique de tous les statuts avec date/user/comment associés (ex: paid_status_history), cf ci-dessous :

Historique des statuts

L’historique des statuts est enregistré dans des modèles/tables qui varient selon le document :

  • StatusLogEntry (docs fournisseurs, mais générique pour s’attacher à n’importe quel descendant de Node)

  • TaskStatus (devis/facture/avoir)

  • Communication (NDD)

(il serait probablement judicieux d’harmoniser tout ça)

Workflow / machine à états

Une machine à état permet de gérer le workflow des documents. Elle hérite de la classe ActionManager et contient plusieurs Action qui sont des transitions d’un état à un autre. Ce sont des classes non persistantes (hors ORM).

Par exemple, get_validation_state_manager renvoie une machine à état dédiée au statut de validation.

Le workflow est composé de transitions qui sont caractérisés par :

  • un nom

  • un état destination

  • un état

Optionellement :

  • une fonction de callback

  • une permission (qui sera vérifiée avec le request.context et request.user)

  • des libellés et icônes pour construire les boutons

Trousse à outil

Mixins pour gérer les statuts

Certains modèles abritant des statuts (pas tous pour le moment) utilisent des mixins pour factoriser ces comportements. Ces mixins sont chacun spécialisés pour un type de statut :

  • ValidationStatusHolderMixin

  • PaidStatusHolderMixin

Ils doivent être hérités par les documents qui abritent ces statuts et prennent en charge les champs de BDD dédiés aux info de statut/état, la gestion l’historisation et le lien avec la machine à état.

Affichage de statuts

Un tas de fonctions relatives aux statuts dans endi.utils.strings

Le styleguide donne des indications.