1
0
Parcourir la source

Fix invoice monthly creation failures

Fabs il y a 11 ans
Parent
commit
e250968e92

+ 82 - 51
coin/billing/create_subscriptions_invoices.py

@@ -1,7 +1,9 @@
 # -*- coding: utf-8 -*-
 # -*- coding: utf-8 -*-
 import datetime
 import datetime
+from decimal import Decimal
 from dateutil.relativedelta import relativedelta
 from dateutil.relativedelta import relativedelta
 from django.http import HttpResponse
 from django.http import HttpResponse
+from django.db import transaction
 from django.db.models import Q
 from django.db.models import Q
 from coin.offers.models import Offer, OfferSubscription
 from coin.offers.models import Offer, OfferSubscription
 from coin.members.models import Member
 from coin.members.models import Member
@@ -9,74 +11,87 @@ from coin.billing.models import Invoice, InvoiceDetail
 
 
 
 
 
 
-def create_all_members_invoices_for_a_period(date):
+def create_all_members_invoices_for_a_period(date=datetime.date.today()):
     """
     """
     Pour chaque membre ayant au moins un abonnement actif, génère les factures
     Pour chaque membre ayant au moins un abonnement actif, génère les factures
     en prenant la date comme premier mois de la période de facturation
     en prenant la date comme premier mois de la période de facturation
     """
     """
     members = Member.objects.filter(
     members = Member.objects.filter(
         Q(offersubscription__resign_date__isnull=True) |
         Q(offersubscription__resign_date__isnull=True) |
-        Q(offersubscription__resign_date__gte=datetime.date.today()))
+        Q(offersubscription__resign_date__gte=date))
 
 
     for member in members:
     for member in members:
         create_member_invoice_for_a_period(member,date)
         create_member_invoice_for_a_period(member,date)
 
 
-
+@transaction.atomic
 def create_member_invoice_for_a_period(member, date):
 def create_member_invoice_for_a_period(member, date):
     """
     """
     Créé si necessaire une facture pour un membre en prenant la date passée
     Créé si necessaire une facture pour un membre en prenant la date passée
     en paramètre comme premier mois de période. Renvoi la facture générée
     en paramètre comme premier mois de période. Renvoi la facture générée
-    ou None si aucune facture n'était pas necessaire.
+    ou None si aucune facture n'était necessaire.
     """
     """
-    invoice = None
+    sid = transaction.savepoint()
+
+    date_first_of_month = datetime.date(date.year, date.month, 1)
+    date_last_of_month = (date_first_of_month + relativedelta(months=+1) -
+                          relativedelta(days=+1))
+
+    invoice = Invoice.objects.create(
+        date_due=datetime.date.today(),
+        member=member
+    )
 
 
-    # Récupère les abonnements en cours du membre
-    offer_subscriptions = member.get_active_subscriptions(date)
+    # Récupère les abonnements actifs du membre à la fin du mois
+    offer_subscriptions = member.get_active_subscriptions(date_last_of_month)
 
 
     # Pour chaque abonnement
     # Pour chaque abonnement
     for offer_subscription in offer_subscriptions:
     for offer_subscription in offer_subscriptions:
         # Récupère l'offre de l'abonnement
         # Récupère l'offre de l'abonnement
         offer = offer_subscription.offer
         offer = offer_subscription.offer
 
 
-        # Recherche dans les factures déjà existantes de ce membre des items
-        # ayant cet abonnement pour lesquels la période de facturation englobe
-        # la date
+        # Vérifie s'il s'agit de la première facture d'un abonnement,
+        # Alors facture en plus les frais de mise en service
+        invoicedetail_test_first = InvoiceDetail.objects.filter(
+            offersubscription__exact=offer_subscription.pk,
+            invoice__member__exact=member.pk)
+        if not invoicedetail_test_first.exists():
+           invoice.details.create(
+                label=offer.name + " - Frais de mise en service",
+                amount=offer.initial_fees,
+                offersubscription=offer_subscription,
+                period_from=None,
+                period_to=None)
+
+        # Période de facturation de l'item par defaut
+        # - Du début du mois de la date passée en paramètre
+        # - Jusqu'à la fin du mois de la période de facturation de l'offre
+        period_from = date_first_of_month
+        period_to = (date_first_of_month +
+                     relativedelta(months=+offer.billing_period) -
+                     relativedelta(days=+1))
+        planned_period_number_of_days = (period_to - period_from).days + 1
+        quantity = 1
+
+        # Si la facture est le premier mois de l'abonnement, alors met la 
+        # date de début de facturation au jour de l'ouverture de
+        # l'abonnement
+        if date_first_of_month == datetime.date(
+            offer_subscription.subscription_date.year, 
+            offer_subscription.subscription_date.month, 1):
+            period_from = offer_subscription.subscription_date
+
+        # Recherche dans les factures déjà existantes de ce membre des
+        # items ayant cet abonnement pour lesquels la période de
+        # facturation englobe le début de notre période de facturation
+        # actuelle
         invoicedetail_test_before = InvoiceDetail.objects.filter(
         invoicedetail_test_before = InvoiceDetail.objects.filter(
             offersubscription__exact=offer_subscription.pk,
             offersubscription__exact=offer_subscription.pk,
-            period_from__lte=date,
-            period_to__gte=date,
+            period_from__lte=period_from,
+            period_to__gt=period_from,
             invoice__member__exact=member.pk)
             invoice__member__exact=member.pk)
 
 
-        # Si une telle facture n'existe pas, alors ajout l'item à facturer à la
-        # facture à générer
+        # Si une facture de ce genre existe alors ne fait rien.
         if not invoicedetail_test_before.exists():
         if not invoicedetail_test_before.exists():
-            # Si l'object facture n'a pas encore été créé, le créé
-            if invoice is None:
-                invoice = Invoice.objects.create(
-                    date_due=datetime.date.today(),
-                    member=member
-                )
-
-            # Vérifie s'il s'agit de la première facture d'un abonnement,
-            # Alors facture en plus les frais de mise en service
-            invoicedetail_test_first = InvoiceDetail.objects.filter(
-                offersubscription__exact=offer_subscription.pk,
-                invoice__member__exact=member.pk)
-            if not invoicedetail_test_first.exists():
-                invoice.details.create(
-                    label=offer.name + " - Frais de mise en service",
-                    amount=offer.initial_fees,
-                    offersubscription=offer_subscription,
-                    period_from=None,
-                    period_to=None)
-
-            # Période de facturation de l'item par defaut
-            # - Du début du mois de la date passée en paramètre
-            # - Jusqu'à la fin du mois de la période de facturation de l'offre
-            period_from = datetime.date(date.year, date.month, 1)
-            period_to = (datetime.date(date.year, date.month, 1) +
-                         relativedelta(months=+offer.billing_period) -
-                         relativedelta(days=+1))
 
 
             # Recherche dans les factures déjà existantes de ce membre des
             # Recherche dans les factures déjà existantes de ce membre des
             # items ayant cet abonnement pour lesquels la période de
             # items ayant cet abonnement pour lesquels la période de
@@ -97,13 +112,29 @@ def create_member_invoice_for_a_period(member, date):
                                   invoicedetail_after.period_from.month, 1) -
                                   invoicedetail_after.period_from.month, 1) -
                     relativedelta(days=+1))
                     relativedelta(days=+1))
 
 
-            # Ajout l'item de l'offre correspondant à l'abonnement à la facture
-            invoice.details.create(label=offer.name,
-                                   amount=offer.period_fees,
-                                   offersubscription=offer_subscription,
-                                   period_from=period_from,
-                                   period_to=period_to)
-
-            invoice.save()
-
-    return invoice
+            # Si la période de facturation varie par rapport à celle prévue par
+            # l'offre, calcul au prorata en faisant varier la quantité
+            period_number_of_days = (period_to - period_from).days + 1
+            if (planned_period_number_of_days != period_number_of_days):
+                quantity = (Decimal(period_number_of_days) /
+                            Decimal(planned_period_number_of_days))
+
+            # Si durée de 0jours ou dates incohérentes, alors on ajoute pas
+            # (Si la period est de 0jours c'est que la facture existe déjà.)
+            if (period_from<period_to):
+                # Ajout l'item de l'offre correspondant à l'abonnement à la facture
+                invoice.details.create(label=offer.name,
+                                       amount=offer.period_fees,
+                                       quantity=quantity,
+                                       offersubscription=offer_subscription,
+                                       period_from=period_from,
+                                       period_to=period_to)
+    
+    # S'il n'y a pas d'items dans la facture, ne commit pas la transaction.
+    if (invoice.details.count()>0):
+        invoice.save()
+        transaction.savepoint_commit(sid)
+        return invoice
+    else:
+        transaction.savepoint_rollback(sid)
+        return None

+ 94 - 0
coin/billing/migrations/0014_auto__chg_field_invoicedetail_quantity.py

@@ -0,0 +1,94 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+
+        # Changing field 'InvoiceDetail.quantity'
+        db.alter_column(u'billing_invoicedetail', 'quantity', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=4, decimal_places=2))
+
+    def backwards(self, orm):
+
+        # Changing field 'InvoiceDetail.quantity'
+        db.alter_column(u'billing_invoicedetail', 'quantity', self.gf('django.db.models.fields.IntegerField')(null=True))
+
+    models = {
+        u'billing.invoice': {
+            'Meta': {'object_name': 'Invoice'},
+            'date': ('django.db.models.fields.DateField', [], {'default': 'datetime.date.today', 'null': 'True'}),
+            'date_due': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2014, 3, 31, 0, 0)', 'null': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'member': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['members.Member']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
+            'number': ('django.db.models.fields.CharField', [], {'default': "u'201403-872-331'", 'unique': 'True', 'max_length': '25'}),
+            'status': ('django.db.models.fields.CharField', [], {'default': "'open'", 'max_length': '50'})
+        },
+        u'billing.invoicedetail': {
+            'Meta': {'object_name': 'InvoiceDetail'},
+            'amount': ('django.db.models.fields.DecimalField', [], {'max_digits': '5', 'decimal_places': '2'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'invoice': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'details'", 'to': u"orm['billing.Invoice']"}),
+            'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'offersubscription': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['offers.OfferSubscription']", 'null': 'True', 'blank': 'True'}),
+            'period_from': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2014, 3, 1, 0, 0)', 'null': 'True', 'blank': 'True'}),
+            'period_to': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2014, 3, 31, 0, 0)', 'null': 'True', 'blank': 'True'}),
+            'quantity': ('django.db.models.fields.DecimalField', [], {'default': '1.0', 'null': 'True', 'max_digits': '4', 'decimal_places': '2'}),
+            'tax': ('django.db.models.fields.DecimalField', [], {'default': '0.0', 'null': 'True', 'max_digits': '4', 'decimal_places': '2'})
+        },
+        u'billing.payment': {
+            'Meta': {'object_name': 'Payment'},
+            'amount': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '7', 'decimal_places': '2'}),
+            'date': ('django.db.models.fields.DateField', [], {'default': 'datetime.date.today'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'invoice': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['billing.Invoice']"}),
+            'payment_mean': ('django.db.models.fields.CharField', [], {'default': "'transfer'", 'max_length': '100', 'null': 'True'})
+        },
+        u'members.member': {
+            'Meta': {'object_name': 'Member'},
+            'address': ('django.db.models.fields.TextField', [], {}),
+            'city': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
+            'country': ('django.db.models.fields.CharField', [], {'default': "'France'", 'max_length': '200'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '254'}),
+            'entry_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.date.today'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
+            'home_phone_number': ('django.db.models.fields.CharField', [], {'max_length': '25', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
+            'ldap_cn': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
+            'mobile_phone_number': ('django.db.models.fields.CharField', [], {'max_length': '25', 'blank': 'True'}),
+            'organization_name': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
+            'postal_code': ('django.db.models.fields.CharField', [], {'max_length': '15'}),
+            'resign_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'status': ('django.db.models.fields.CharField', [], {'default': "'non_adherent'", 'max_length': '50'}),
+            'type': ('django.db.models.fields.CharField', [], {'default': "'personne_physique'", 'max_length': '20'})
+        },
+        u'offers.offer': {
+            'Meta': {'object_name': 'Offer'},
+            'billing_period': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'initial_fees': ('django.db.models.fields.DecimalField', [], {'max_digits': '5', 'decimal_places': '2'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'period_fees': ('django.db.models.fields.DecimalField', [], {'max_digits': '5', 'decimal_places': '2'}),
+            'service': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['offers.Service']"})
+        },
+        u'offers.offersubscription': {
+            'Meta': {'object_name': 'OfferSubscription'},
+            'commitment': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'member': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['members.Member']"}),
+            'offer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['offers.Offer']"}),
+            'resign_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'subscription_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.date.today'})
+        },
+        u'offers.service': {
+            'Meta': {'object_name': 'Service'},
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        }
+    }
+
+    complete_apps = ['billing']

+ 2 - 2
coin/billing/models.py

@@ -66,8 +66,8 @@ class InvoiceDetail(models.Model):
     label = models.CharField(max_length=100)
     label = models.CharField(max_length=100)
     amount = models.DecimalField(max_digits=5, decimal_places=2,
     amount = models.DecimalField(max_digits=5, decimal_places=2,
                                  verbose_name='Montant')
                                  verbose_name='Montant')
-    quantity = models.IntegerField(null=True, verbose_name=u'Quantité',
-                                   default=1)
+    quantity = models.DecimalField(null=True, verbose_name=u'Quantité',
+                                   default=1.0, decimal_places=2, max_digits=4)
     tax = models.DecimalField(null=True, default=0.0, decimal_places=2,
     tax = models.DecimalField(null=True, default=0.0, decimal_places=2,
                               max_digits=4, verbose_name='TVA',
                               max_digits=4, verbose_name='TVA',
                               help_text='en %')
                               help_text='en %')

+ 55 - 49
coin/billing/tests.py

@@ -1,86 +1,94 @@
 # -*- coding: utf-8 -*-
 # -*- coding: utf-8 -*-
 import datetime
 import datetime
+from decimal import Decimal
 from django.test import TestCase, Client
 from django.test import TestCase, Client
 from coin.members.tests import MemberTestsUtils
 from coin.members.tests import MemberTestsUtils
 from coin.members.models import Member, LdapUser
 from coin.members.models import Member, LdapUser
 from coin.billing.models import Invoice
 from coin.billing.models import Invoice
 from coin.offers.models import Offer, Service, OfferSubscription
 from coin.offers.models import Offer, Service, OfferSubscription
 from coin.billing.create_subscriptions_invoices import create_member_invoice_for_a_period
 from coin.billing.create_subscriptions_invoices import create_member_invoice_for_a_period
+from coin.billing.create_subscriptions_invoices import create_all_members_invoices_for_a_period
 
 
 
 
 class BillingInvoiceCreationTests(TestCase):
 class BillingInvoiceCreationTests(TestCase):
 
 
+    def setUp(self):
+        # Créé une offre
+        self.service = Service(name='ServiceTest')
+        self.service.save()
+        self.offer = Offer(name='Offre', billing_period=3, period_fees=30,
+                           initial_fees=50, service=self.service)
+        self.offer.save()
+        # Créé un membre
+        self.ldap_cn = MemberTestsUtils.get_random_ldap_cn()
+        self.member = Member(first_name='Balthazar', last_name='Picsou',
+                             ldap_cn=self.ldap_cn)
+        self.member.save()
+        # Créé un abonnement
+        self.subscription = OfferSubscription(
+            subscription_date=datetime.date(2014, 1, 10),
+            member=self.member,
+            offer=self.offer)
+        self.subscription.save()
+    
+    def tearDown(self):
+        # Supprime l'utilisateur LDAP créé
+        LdapUser.objects.get(pk=self.ldap_cn).delete()
+
     def test_first_subscription_invoice_has_initial_fees(self):
     def test_first_subscription_invoice_has_initial_fees(self):
         """
         """
         Test que la première facture générée pour un abonnement possède les
         Test que la première facture générée pour un abonnement possède les
         frais de mise en service
         frais de mise en service
         """
         """
-        # Créé une offre
-        service = Service(name='ServiceTest')
-        service.save()
-        offer = Offer(name='Offre', billing_period=3, period_fees=30,
-                      initial_fees=50, service=service)
-        offer.save()
-        # Créé un membre
-        ldap_cn = MemberTestsUtils.get_random_ldap_cn()
-        member = Member(first_name='Balthazar', last_name='Picsou',
-                        ldap_cn=ldap_cn)
-        member.save()
-        # Créé un abonnement
-        subscription = OfferSubscription(
-            subscription_date=datetime.date(2014, 1, 1),
-            member=member,
-            offer=offer)
-        subscription.save()
         # Demande la création de la première facture
         # Demande la création de la première facture
         invoice = create_member_invoice_for_a_period(
         invoice = create_member_invoice_for_a_period(
-            member, datetime.date(2014, 1, 1))
+            self.member, datetime.date(2014, 1, 1))
         # La facture doit avoir les frais de mise en service
         # La facture doit avoir les frais de mise en service
         # Pour tester cela on tri par montant d'item décroissant.
         # Pour tester cela on tri par montant d'item décroissant.
         # Comme dans l'offre créé, les initial_fees sont plus élevées que
         # Comme dans l'offre créé, les initial_fees sont plus élevées que
         # les period_fees, il doit sortir en premier
         # les period_fees, il doit sortir en premier
         self.assertEqual(invoice.details.order_by('-amount').first().amount, 50)
         self.assertEqual(invoice.details.order_by('-amount').first().amount, 50)
 
 
+    def test_prorata_for_first_month_subscription(self):
+        """
+        Test que la première facture d'un abonnement est facturée au prorata du
+        nombre de jours restants
+        """
+        #Créé la facture pour le mois de janvier
+        invoice = create_member_invoice_for_a_period(self.member, datetime.date(2014,1,1))
+        #Comme l'abonnement a été souscris le 10/01 et que la période de
+        #facturation est de 3 mois, alors le prorata doit être :
+        #janvier :  22j (31-9)
+        #fevrier :  28j
+        #mars :     31j
+        #22+28+31 / 31+28+31
+        quantity = Decimal((22.0+28.0+31.0)/(31.0+28.0+31.0))
+        for detail in invoice.details.all():
+            if detail.amount != 50:
+                self.assertEqual(detail.quantity.quantize(Decimal('0.01')),
+                                 quantity.quantize(Decimal('0.01')))
+
     def test_subscription_cant_be_charged_twice(self):
     def test_subscription_cant_be_charged_twice(self):
         """
         """
         Test qu'un abonnement ne peut pas être facturé deux fois
         Test qu'un abonnement ne peut pas être facturé deux fois
         (pas de chevauchement possible)
         (pas de chevauchement possible)
         """
         """
-
-        # Créé une offre
-        service = Service(name='ServiceTest')
-        service.save()
-        offer = Offer(name='Offre', billing_period=3, period_fees=30,
-                      initial_fees=0, service=service)
-        offer.save()
-        # Créé un membre
-        ldap_cn = MemberTestsUtils.get_random_ldap_cn()
-        member = Member(first_name='Balthazar', last_name='Picsou',
-                        ldap_cn=ldap_cn)
-        member.save()
-        # Créé un abonnement
-        subscription = OfferSubscription(
-            subscription_date=datetime.date(2014, 1, 1),
-            member=member,
-            offer=offer)
-        subscription.save()
-
         # Créé une facture
         # Créé une facture
-        invoice = Invoice(member=member)
+        invoice = Invoice(member=self.member)
         invoice.save()
         invoice.save()
         # Créé une facturation pour cet abonnement pour la première période
         # Créé une facturation pour cet abonnement pour la première période
         # de janvier à mars
         # de janvier à mars
-        invoice.details.create(label=offer.name,
-                               amount=offer.period_fees,
-                               offersubscription=subscription,
+        invoice.details.create(label=self.offer.name,
+                               amount=self.offer.period_fees,
+                               offersubscription=self.subscription,
                                period_from=datetime.date(2014, 1, 1),
                                period_from=datetime.date(2014, 1, 1),
                                period_to=datetime.date(2014, 3, 31))
                                period_to=datetime.date(2014, 3, 31))
 
 
         # Créé une facturation pour cet abonnement pour une seconde période
         # Créé une facturation pour cet abonnement pour une seconde période
         # de juin à aout
         # de juin à aout
-        invoice.details.create(label=offer.name,
-                               amount=offer.period_fees,
-                               offersubscription=subscription,
+        invoice.details.create(label=self.offer.name,
+                               amount=self.offer.period_fees,
+                               offersubscription=self.subscription,
                                period_from=datetime.date(2014, 6, 1),
                                period_from=datetime.date(2014, 6, 1),
                                period_to=datetime.date(2014, 8, 31))
                                period_to=datetime.date(2014, 8, 31))
 
 
@@ -88,7 +96,7 @@ class BillingInvoiceCreationTests(TestCase):
         # Elle doit renvoyer None car l'offre est déjà facturée de
         # Elle doit renvoyer None car l'offre est déjà facturée de
         # janvier à mars
         # janvier à mars
         invoice_test_1 = create_member_invoice_for_a_period(
         invoice_test_1 = create_member_invoice_for_a_period(
-            member, datetime.date(2014, 2, 1))
+            self.member, datetime.date(2014, 2, 1))
         self.assertEqual(invoice_test_1, None)
         self.assertEqual(invoice_test_1, None)
 
 
         # Demande la création d'une facture pour avril
         # Demande la création d'une facture pour avril
@@ -96,14 +104,12 @@ class BillingInvoiceCreationTests(TestCase):
         # que de 2 mois, d'avril à mai car il y a déjà une facture pour
         # que de 2 mois, d'avril à mai car il y a déjà une facture pour
         # la période de juin à aout
         # la période de juin à aout
         invoice_test_2 = create_member_invoice_for_a_period(
         invoice_test_2 = create_member_invoice_for_a_period(
-            member, datetime.date(2014, 4, 1))
+            self.member, datetime.date(2014, 4, 1))
         self.assertEqual(invoice_test_2.details.first().period_from,
         self.assertEqual(invoice_test_2.details.first().period_from,
                          datetime.date(2014, 4, 1))
                          datetime.date(2014, 4, 1))
         self.assertEqual(invoice_test_2.details.first().period_to,
         self.assertEqual(invoice_test_2.details.first().period_to,
                          datetime.date(2014, 5, 31))
                          datetime.date(2014, 5, 31))
 
 
-        LdapUser.objects.get(pk=ldap_cn).delete()
-
 
 
 class BillingPDFTests(TestCase):
 class BillingPDFTests(TestCase):
 
 
@@ -139,7 +145,7 @@ class BillingPDFTests(TestCase):
         Test qu'une erreur 403 est bien retournée en cas de tentative
         Test qu'une erreur 403 est bien retournée en cas de tentative
         infructueuse
         infructueuse
         """
         """
-        # Créé un membre B
+        # Créé un membre A
         member_a_login = MemberTestsUtils.get_random_ldap_cn()
         member_a_login = MemberTestsUtils.get_random_ldap_cn()
         member_a_pwd = '1234'
         member_a_pwd = '1234'
         member_a = Member(first_name='A', last_name='A',
         member_a = Member(first_name='A', last_name='A',