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 .. code-block:: python 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``) : .. warning:: 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.