[#3023] Solde des cotisations par année + détermination des établissements délinquants
authorEric Mc Sween <eric.mcsween@auf.org>
Wed, 2 May 2012 17:58:41 +0000 (13:58 -0400)
committerEric Mc Sween <eric.mcsween@auf.org>
Wed, 2 May 2012 17:58:41 +0000 (13:58 -0400)
auf/django/coda/managedcoda/models.py
setup.py

index b746d8d..62cf618 100644 (file)
@@ -1,7 +1,11 @@
 # encoding: utf-8
 
+from datetime import date
+
 from auf.django.references import models as ref
 from django.db import models
+from django.db.models import Sum
+from django.db.models.query import QuerySet
 
 
 class Element(models.Model):
@@ -24,12 +28,60 @@ class PCG(Element):
 
 
 class TiersOperation(Element):
-    etablissement = models.OneToOneField(ref.Etablissement, related_name='coda_tiers_operation',
-                                         blank=True, null=True)
+    etablissement = models.OneToOneField(
+        ref.Etablissement, related_name='coda_tiers_operation',
+        blank=True, null=True
+    )
 
     class Meta:
         db_table = 'coda_tiersoperation'
 
+    def solde_cotisations_par_annee(self):
+        """
+        Retourne une liste de paires (annee, solde) contenant le solde des
+        cotisations à payer par année pour cet établissement.
+        """
+        cotisations_impayees = self.lignes.cotisations().exclude(
+            etat_paiement='P'
+        )
+        factures_par_annee = list(
+            cotisations_impayees
+            .filter(montant_eur__gt=0)
+            .values('ecriture__annee')
+            .annotate(Sum('montant_eur'))
+            .order_by('-ecriture__annee')
+        )
+        paiements = (
+            cotisations_impayees
+            .filter(montant_eur__lt=0)
+            .aggregate(Sum('montant_eur'))
+        )['montant_eur__sum'] or 0
+
+        while paiements < 0 and len(factures_par_annee) > 0:
+            paiements += factures_par_annee[-1]['montant_eur__sum']
+            if paiements <= 0:
+                factures_par_annee.pop()
+        if paiements > 0 and len(factures_par_annee) > 0:
+            # Ajuster le solde à payer sur la dernière facture
+            factures_par_annee[-1]['montant_eur__sum'] = paiements
+        return [(x['ecriture__annee'], x['montant_eur__sum'])
+                for x in factures_par_annee]
+
+    def delinquant(self):
+        """
+        Teste si l'établissement lié à ce tiers est délinquant ou pas.
+
+        Un établissement délinquant a 3 années ou plus de cotisations
+        impayées.
+        """
+        today = date.today()
+        annee_max = today.year
+        if today.month < 6:
+            # Ne pas considérer l'année en cours avant le mois de juin
+            annee_max -= 1
+        return len([x for x in self.solde_cotisations_par_annee()
+                    if x[0] <= annee_max]) >= 3
+
 
 class ProjetPoste(Element):
 
@@ -51,6 +103,32 @@ class Ecriture(models.Model):
         ordering = ['id']
 
 
+class LigneQuerySet(QuerySet):
+
+    def cotisations(self):
+        """
+        Filtre qui ne garde que les lignes qui représentent des factures ou
+        des paiements de cotisations d'établissements membres.
+        """
+        return self \
+                .exclude(tiers_operation__etablissement=None) \
+                .exclude(montant_eur=0) \
+                .exclude(ecriture__code='G-CLOT-BILAN') \
+                .exclude(ecriture__code='C-ENC-INSCR') \
+                .exclude(ecriture__code='G-ODD',
+                         ecriture__numero__in=(19912, 29582))
+
+
+class LigneManager(models.Manager):
+    use_for_related_fields = True
+
+    def get_query_set(self):
+        return LigneQuerySet(self.model)
+
+    def cotisations(self):
+        return self.get_query_set().cotisations()
+
+
 class Ligne(models.Model):
     DEBIT_CREDIT_CHOICES = (
         ('D', 'Débit'),
@@ -72,8 +150,12 @@ class Ligne(models.Model):
     numero = models.IntegerField()
     timestamp = models.BigIntegerField()
     pcg = models.ForeignKey(PCG, related_name='lignes')
-    tiers_operation = models.ForeignKey(TiersOperation, related_name='lignes', blank=True, null=True)
-    projet_poste = models.ForeignKey(ProjetPoste, related_name='lignes', blank=True, null=True)
+    tiers_operation = models.ForeignKey(
+        TiersOperation, related_name='lignes', blank=True, null=True
+    )
+    projet_poste = models.ForeignKey(
+        ProjetPoste, related_name='lignes', blank=True, null=True
+    )
     description = models.CharField(max_length=36)
     montant_eur = models.DecimalField(max_digits=17, decimal_places=2)
     debit_credit = models.CharField(max_length=1, choices=DEBIT_CREDIT_CHOICES)
@@ -82,7 +164,12 @@ class Ligne(models.Model):
     implantation = models.CharField(max_length=32)
     salarie = models.CharField(max_length=32)
     numero_cheque = models.CharField(max_length=32)
-    etat_paiement = models.CharField(max_length=1, choices=ETAT_PAIEMENT_CHOICES)
+    etat_paiement = models.CharField(
+        max_length=1, choices=ETAT_PAIEMENT_CHOICES
+    )
+
+    # Managers
+    objects = LigneManager()
 
     class Meta:
         db_table = 'coda_ligne'
index 7c660b6..1642980 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -1,11 +1,9 @@
 # encoding: utf-8
 
-import os
-import sys
 from setuptools import setup, find_packages
 
 name = 'auf.django.coda'
-version = '0.7'
+version = '0.8'
 
 setup(name=name,
       version=version,