Fabs 11 years ago
parent
commit
8da58b5461
4 changed files with 292 additions and 282 deletions
  1. 105 98
      coin/billing/create_subscriptions_invoices.py
  2. 19 17
      coin/billing/models.py
  3. 164 163
      coin/billing/tests.py
  4. 4 4
      coin/billing/views.py

+ 105 - 98
coin/billing/create_subscriptions_invoices.py

@@ -9,104 +9,111 @@ from coin.billing.models import Invoice, InvoiceDetail
 
 
 def create_missing_invoices(request):
-	"""
-	TODO
-	Pour chaque abonnement (OfferSubscription):
-		Vérifie pour chaque période de facturation si elle a été facturée
-		Sinon génère la facture correspondante
-	"""
-	members = Member.objects.filter(
-		Q(offersubscription__resign_date__isnull=True) |
-		Q(offersubscription__resign_date__gte=datetime.date.today()))
-	offer_subscriptions = OfferSubscription.objects.filter(
-		Q(resign_date__isnull=True) | Q(resign_date__gte=datetime.date.today()))
-	sortie = ""
-	for member in members:
-		sortie += '<br /> %s - %s' % (member, 
-			generate_invoice_for_a_period(member, datetime.date(2014,5,17)))
-
-	return HttpResponse(sortie)
+    """
+    TODO
+    Pour chaque abonnement (OfferSubscription):
+    Vérifie pour chaque période de facturation si elle a été facturée
+    Sinon génère la facture correspondante
+    """
+    members = Member.objects.filter(
+        Q(offersubscription__resign_date__isnull=True) |
+        Q(offersubscription__resign_date__gte=datetime.date.today()))
+    offer_subscriptions = OfferSubscription.objects.filter(
+        Q(resign_date__isnull=True) |
+        Q(resign_date__gte=datetime.date.today()))
+    sortie = ""
+    for member in members:
+        sortie += '<br /> %s - %s' % (
+            member,
+            generate_invoice_for_a_period(member,
+                                          datetime.date(2014, 5, 17))
+            )
+
+    return HttpResponse(sortie)
 
 
 def create_member_invoice_for_a_period(member, date):
-	"""
-	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
-	ou None si aucune facture n'était necessaire.
-	"""
-	invoice = None
-
-	# Récupère les abonnements en cours du membre
-	offer_subscriptions = member.get_active_subscriptions(date)
-
-	# Pour chaque abonnement
-	for offer_subscription in offer_subscriptions:
-		#Récupère l'offre de l'abonnement
-		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
-		invoicedetail_test_before = InvoiceDetail.objects.filter(
-			offersubscription__exact=offer_subscription.pk,
-			period_from__lte=date,
-			period_to__gte=date,
-			invoice__member__exact=member.pk)
-
-		# Si une telle facture n'existe pas, alors ajout l'item à facturer à la
-		# facture à générer
-		if not invoicedetail_test_before.exists():
-			#Si l'object facture n'a pas encore été créé, le créé
-			if invoice == 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 items
-			# ayant cet abonnement pour lesquels la période de facturation
-			# commence avant la fin de notre période de facturation actuelle
-			invoicedetail_test_after = InvoiceDetail.objects.filter(
-				offersubscription__exact=offer_subscription.pk,
-				period_from__lte=period_to,
-				period_from__gte=period_from,
-				invoice__member__exact=member.pk)
-			
-			# Si une telle facture existe, récupère la date de début de
-			# facturation pour en faire la date de fin de facturation
-			if invoicedetail_test_after.exists():
-				invoicedetail_after = invoicedetail_test_after.first()
-				period_to = (datetime.date(invoicedetail_after.period_from.year,
-							 invoicedetail_after.period_from.month,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
+    """
+    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
+    ou None si aucune facture n'était pas necessaire.
+    """
+    invoice = None
+
+    # Récupère les abonnements en cours du membre
+    offer_subscriptions = member.get_active_subscriptions(date)
+
+    # Pour chaque abonnement
+    for offer_subscription in offer_subscriptions:
+        # Récupère l'offre de l'abonnement
+        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
+        invoicedetail_test_before = InvoiceDetail.objects.filter(
+            offersubscription__exact=offer_subscription.pk,
+            period_from__lte=date,
+            period_to__gte=date,
+            invoice__member__exact=member.pk)
+
+        # Si une telle facture n'existe pas, alors ajout l'item à facturer à la
+        # facture à générer
+        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
+            # items ayant cet abonnement pour lesquels la période de
+            # facturation commence avant la fin de notre période de facturation
+            # actuelle
+            invoicedetail_test_after = InvoiceDetail.objects.filter(
+                offersubscription__exact=offer_subscription.pk,
+                period_from__lte=period_to,
+                period_from__gte=period_from,
+                invoice__member__exact=member.pk)
+
+            # Si une telle facture existe, récupère la date de début de
+            # facturation pour en faire la date de fin de facturation
+            if invoicedetail_test_after.exists():
+                invoicedetail_after = invoicedetail_test_after.first()
+                period_to = (
+                    datetime.date(invoicedetail_after.period_from.year,
+                                  invoicedetail_after.period_from.month, 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

+ 19 - 17
coin/billing/models.py

@@ -17,7 +17,7 @@ class Invoice(models.Model):
     )
 
     number = models.CharField(max_length=25,
-                              default=lambda:Invoice.next_invoice_number(),
+                              default=lambda: Invoice.next_invoice_number(),
                               unique=True,
                               verbose_name='Numéro')
     status = models.CharField(max_length=50, choices=INVOICES_STATUS_CHOICES,
@@ -31,26 +31,28 @@ class Invoice(models.Model):
         null=True,
         verbose_name=u'Date d\'échéance de paiement')
     member = models.ForeignKey(Member, null=True, blank=True, default=None,
-                               verbose_name='Membre', on_delete=models.SET_NULL)
+                               verbose_name='Membre',
+                               on_delete=models.SET_NULL)
 
     def amount(self):
-      "Calcul le montant de la facture en fonction des éléments de détails"
-      total = Decimal('0.0')
-      for detail in self.details.all():
-        total += detail.total()
-      return total.quantize(Decimal('0.01'))
+        "Calcul le montant de la facture en fonction des éléments de détails"
+        total = Decimal('0.0')
+        for detail in self.details.all():
+            total += detail.total()
+        return total.quantize(Decimal('0.01'))
 
     def has_owner(self, uid):
-      "Check if passed uid (ex gmajax) is owner of the invoice"
-      return self.member and self.member.ldap_cn and self.member.ldap_cn == uid
+        "Check if passed uid (ex gmajax) is owner of the invoice"
+        return (self.member and self.member.ldap_cn and
+                self.member.ldap_cn == uid)
 
     @staticmethod
     def next_invoice_number():
-      "Détermine un numéro de facture aléatoire"
-      return u'%s%02i-%i-%i' % (datetime.date.today().year,
-                                datetime.date.today().month,
-                                random.randrange(100, 999),
-                                random.randrange(100, 999))
+        "Détermine un numéro de facture aléatoire"
+        return u'%s%02i-%i-%i' % (datetime.date.today().year,
+                                  datetime.date.today().month,
+                                  random.randrange(100, 999),
+                                  random.randrange(100, 999))
 
     def __unicode__(self):
         return u'#%s %0.2f€ %s' % (self.number, self.amount(), self.date_due)
@@ -94,9 +96,9 @@ class InvoiceDetail(models.Model):
         return self.label
 
     def total(self):
-      "Calcul le total"
-      return (self.amount * (self.tax / Decimal('100.0') +
-              Decimal('1.0')) * self.quantity).quantize(Decimal('0.01'))
+        "Calcul le total"
+        return (self.amount * (self.tax / Decimal('100.0') +
+                Decimal('1.0')) * self.quantity).quantize(Decimal('0.01'))
 
     class Meta:
         verbose_name = 'détail de facture'

+ 164 - 163
coin/billing/tests.py

@@ -7,172 +7,173 @@ from coin.billing.models import Invoice
 from coin.offers.models import Offer, Service, OfferSubscription
 from coin.billing.create_subscriptions_invoices import create_member_invoice_for_a_period
 
+
 class BillingInvoiceCreationTests(TestCase):
 
-	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
-		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
-		invoice = create_member_invoice_for_a_period(member, datetime.date(2014,1,1))
-		# La facture doit avoir les frais de mise en service
-		# Pour tester cela on tri par montant d'item décroissant.
-		# Comme dans l'offre créé, les initial_fees sont plus élevées que
-		# les period_fees, il doit sortir en premier
-		self.assertEqual(invoice.details.order_by('-amount').first().amount, 50)
-
-	def test_subscription_cant_be_charged_twice(self):
-		"""
-		Test qu'un abonnement ne peut pas être facturé deux fois
-		(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
-		invoice = Invoice(member=member)
-		invoice.save()
-		# Créé une facturation pour cet abonnement pour la première période
-		# de janvier à mars
-		invoice.details.create(label=offer.name,
-				amount=offer.period_fees,
-				offersubscription=subscription,
-				period_from=datetime.date(2014,1,1),
-				period_to=datetime.date(2014,3,31))
-
-		# Créé une facturation pour cet abonnement pour une seconde période
-		# de juin à aout
-		invoice.details.create(label=offer.name,
-				amount=offer.period_fees,
-				offersubscription=subscription,
-				period_from=datetime.date(2014,6,1),
-				period_to=datetime.date(2014,8,31))
-
-		# Demande la génération d'une facture pour février
-		# Elle doit renvoyer None car l'offre est déjà facturée de
-		# janvier à mars
-		invoice_test_1 = create_member_invoice_for_a_period(
-			member,datetime.date(2014,2,1))
-		self.assertEqual(invoice_test_1, None)
-
-		# Demande la création d'une facture pour avril
-		# Elle doit fonctionner, mais devrait avoir une période de facturation
-		# que de 2 mois, d'avril à mai car il y a déjà une facture pour
-		# la période de juin à aout
-		invoice_test_2 = create_member_invoice_for_a_period(
-			member, datetime.date(2014,4,1))
-		self.assertEqual(invoice_test_2.details.first().period_from,
-						 datetime.date(2014,4,1))
-		self.assertEqual(invoice_test_2.details.first().period_to,
-						 datetime.date(2014,5,31))
-
-		LdapUser.objects.get(pk=ldap_cn).delete();
+    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
+        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
+        invoice = create_member_invoice_for_a_period(
+            member, datetime.date(2014, 1, 1))
+        # La facture doit avoir les frais de mise en service
+        # Pour tester cela on tri par montant d'item décroissant.
+        # Comme dans l'offre créé, les initial_fees sont plus élevées que
+        # les period_fees, il doit sortir en premier
+        self.assertEqual(invoice.details.order_by('-amount').first().amount, 50)
+
+    def test_subscription_cant_be_charged_twice(self):
+        """
+        Test qu'un abonnement ne peut pas être facturé deux fois
+        (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
+        invoice = Invoice(member=member)
+        invoice.save()
+        # Créé une facturation pour cet abonnement pour la première période
+        # de janvier à mars
+        invoice.details.create(label=offer.name,
+                               amount=offer.period_fees,
+                               offersubscription=subscription,
+                               period_from=datetime.date(2014, 1, 1),
+                               period_to=datetime.date(2014, 3, 31))
+
+        # Créé une facturation pour cet abonnement pour une seconde période
+        # de juin à aout
+        invoice.details.create(label=offer.name,
+                               amount=offer.period_fees,
+                               offersubscription=subscription,
+                               period_from=datetime.date(2014, 6, 1),
+                               period_to=datetime.date(2014, 8, 31))
+
+        # Demande la génération d'une facture pour février
+        # Elle doit renvoyer None car l'offre est déjà facturée de
+        # janvier à mars
+        invoice_test_1 = create_member_invoice_for_a_period(
+            member, datetime.date(2014, 2, 1))
+        self.assertEqual(invoice_test_1, None)
+
+        # Demande la création d'une facture pour avril
+        # Elle doit fonctionner, mais devrait avoir une période de facturation
+        # que de 2 mois, d'avril à mai car il y a déjà une facture pour
+        # la période de juin à aout
+        invoice_test_2 = create_member_invoice_for_a_period(
+            member, datetime.date(2014, 4, 1))
+        self.assertEqual(invoice_test_2.details.first().period_from,
+                         datetime.date(2014, 4, 1))
+        self.assertEqual(invoice_test_2.details.first().period_to,
+                         datetime.date(2014, 5, 31))
+
+        LdapUser.objects.get(pk=ldap_cn).delete()
 
 
 class BillingPDFTests(TestCase):
 
-	def test_download_invoice_pdf_return_a_pdf(self):
-		"""
-		Test que le téléchargement d'une facture en format pdf retourne bien un
-		pdf
-		"""
-		# Créé un membre
-		ldap_cn = MemberTestsUtils.get_random_ldap_cn()
-		member = Member(first_name = 'A', last_name = 'A',
-		                ldap_cn = ldap_cn)
-		member.save()
-		member.change_password('1234')
-
-		# Créé une facture
-		invoice = Invoice(member=member)
-		invoice.save()
-
-		#Se connect en tant que le membre
-		client = Client()
-		client.login(username = ldap_cn, password = '1234')
-		# Tente de télécharger la facture
-		response = client.get('/billing/invoice/%i/pdf' % invoice.id)
-		# Vérifie return code 200 et contient chaine %PDF-1.
-		self.assertContains(response, '%PDF-1.', status_code=200, html=False)
-		LdapUser.objects.get(pk=ldap_cn).delete();
-
-
-	def test_that_only_owner_of_invoice_can_download_it_as_pdf(self):
-		"""
-		Test qu'une facture ne peut pas être téléchargée par quelqu'un qui n'en
-		est pas le propriétaire.
-		Test qu'une erreur 403 est bien retournée en cas de tentative
-		infructueuse
-		"""
-		# Créé un membre B
-		member_a_login = MemberTestsUtils.get_random_ldap_cn()
-		member_a_pwd = '1234'
-		member_a = Member(first_name = 'A', last_name = 'A',
-		                ldap_cn = member_a_login)
-		member_a.save()
-		member_a.change_password(member_a_pwd)
-
-		# Créé un membre B
-		member_b_login =  MemberTestsUtils.get_random_ldap_cn()
-		member_b_pwd = '1234'
-		member_b = Member(first_name = 'B', last_name = 'B',
-		                ldap_cn = member_b_login)
-		member_b.save()
-		member_b.change_password(member_b_pwd)
-
-		# Créé une facture pour le membre A
-		invoice_a = Invoice(member=member_a)
-		invoice_a.save()
-
-		# Simule une connexion en tant que A
-		client = Client()
-		client.login(username = member_a_login, password = member_a_pwd)
-		# Tente de télécharger la facture de A en tant que A
-		response = client.get('/billing/invoice/%i/pdf' % invoice_a.id)
-		# Vérifie que B a reçu retour OK 200
-		self.assertEqual(response.status_code, 200)
-
-		# Simule une connexion en tant que B
-		client = Client()
-		client.login(username = member_b_login, password = member_b_pwd)
-		# Tente de télécharger la facture de A en tant que B
-		response = client.get('/billing/invoice/%i/pdf' % invoice_a.id)
-		# Vérifie que B a reçu retour Forbidden 403
-		self.assertEqual(response.status_code, 403)
-		
-		LdapUser.objects.get(pk=member_a_login).delete();
-		LdapUser.objects.get(pk=member_b_login).delete();
+    def test_download_invoice_pdf_return_a_pdf(self):
+        """
+        Test que le téléchargement d'une facture en format pdf retourne bien un
+        pdf
+        """
+        # Créé un membre
+        ldap_cn = MemberTestsUtils.get_random_ldap_cn()
+        member = Member(first_name='A', last_name='A',
+                        ldap_cn=ldap_cn)
+        member.save()
+        member.change_password('1234')
+
+        # Créé une facture
+        invoice = Invoice(member=member)
+        invoice.save()
+
+        # Se connect en tant que le membre
+        client = Client()
+        client.login(username=ldap_cn, password='1234')
+        # Tente de télécharger la facture
+        response = client.get('/billing/invoice/%i/pdf' % invoice.id)
+        # Vérifie return code 200 et contient chaine %PDF-1.
+        self.assertContains(response, '%PDF-1.', status_code=200, html=False)
+        LdapUser.objects.get(pk=ldap_cn).delete()
+
+    def test_that_only_owner_of_invoice_can_download_it_as_pdf(self):
+        """
+        Test qu'une facture ne peut pas être téléchargée par quelqu'un qui n'en
+        est pas le propriétaire.
+        Test qu'une erreur 403 est bien retournée en cas de tentative
+        infructueuse
+        """
+        # Créé un membre B
+        member_a_login = MemberTestsUtils.get_random_ldap_cn()
+        member_a_pwd = '1234'
+        member_a = Member(first_name='A', last_name='A',
+                          ldap_cn=member_a_login)
+        member_a.save()
+        member_a.change_password(member_a_pwd)
+
+        # Créé un membre B
+        member_b_login = MemberTestsUtils.get_random_ldap_cn()
+        member_b_pwd = '1234'
+        member_b = Member(first_name='B', last_name='B',
+                          ldap_cn=member_b_login)
+        member_b.save()
+        member_b.change_password(member_b_pwd)
+
+        # Créé une facture pour le membre A
+        invoice_a = Invoice(member=member_a)
+        invoice_a.save()
+
+        # Simule une connexion en tant que A
+        client = Client()
+        client.login(username=member_a_login, password=member_a_pwd)
+        # Tente de télécharger la facture de A en tant que A
+        response = client.get('/billing/invoice/%i/pdf' % invoice_a.id)
+        # Vérifie que B a reçu retour OK 200
+        self.assertEqual(response.status_code, 200)
+
+        # Simule une connexion en tant que B
+        client = Client()
+        client.login(username=member_b_login, password=member_b_pwd)
+        # Tente de télécharger la facture de A en tant que B
+        response = client.get('/billing/invoice/%i/pdf' % invoice_a.id)
+        # Vérifie que B a reçu retour Forbidden 403
+        self.assertEqual(response.status_code, 403)
+
+        LdapUser.objects.get(pk=member_a_login).delete()
+        LdapUser.objects.get(pk=member_b_login).delete()

+ 4 - 4
coin/billing/views.py

@@ -19,13 +19,13 @@ def invoice_pdf(request, id):
 
     if not invoice.has_owner(request.user.username) and not request.user.is_superuser:
         raise PermissionDenied
-        
+
     member = invoice.member
 
-    context = {"invoice": invoice, 'member':member}
-    
+    context = {"invoice": invoice, 'member': member}
+
     pdf = render_as_pdf('billing/invoice.html', context)
-    
+
     response = HttpResponse(content_type='application/pdf')
     #response['Content-Disposition'] = 'attachment; filename="facture.pdf"'