diff --git a/cotisations/models.py b/cotisations/models.py index b9d01b8d..77337a84 100644 --- a/cotisations/models.py +++ b/cotisations/models.py @@ -290,9 +290,22 @@ class Facture(BaseInvoice): """Returns True if this invoice contains at least one subscribtion.""" return bool(self.get_subscription()) + def reorder_purchases(self): + date = self.date + for purchase in self.vente_set.all(): + if hasattr(purchase, 'cotisation'): + cotisation = purchase.cotisation + cotisation.date_start = date + date += relativedelta( + months=(purchase.duration or 0)*purchase.number, + days=(purchase.duration_days or 0)*purchase.number, + ) + purchase.save() + def save(self, *args, **kwargs): super(Facture, self).save(*args, **kwargs) if not self.__original_valid and self.valid: + self.reorder_purchases() send_mail_invoice(self) if self.is_subscription() \ and not self.__original_control \ @@ -540,7 +553,6 @@ class Vente(RevMixin, AclMixin, models.Model): months=(self.duration or 0)*self.number, days=(self.duration_days or 0)*self.number, ) - return def save(self, *args, **kwargs): """ @@ -1042,7 +1054,7 @@ class Cotisation(RevMixin, AclMixin, models.Model): return True, None, None def __str__(self): - return str(self.vente) + return str(self.vente) + "from " + str(self.date_start) + " to " + str(self.date_end) @receiver(post_save, sender=Cotisation) diff --git a/cotisations/test_models.py b/cotisations/test_models.py index 33f32a18..ed53c0a1 100644 --- a/cotisations/test_models.py +++ b/cotisations/test_models.py @@ -2,6 +2,7 @@ from django.test import TestCase import datetime from django.utils import timezone +from dateutil.relativedelta import relativedelta from users.models import User from .models import Vente, Facture, Cotisation, Paiement @@ -41,6 +42,48 @@ class VenteModelTests(TestCase): delta=datetime.timedelta(seconds=1) ) + def test_one_month_cotisation(self): + """ + It should be possible to have one day membership. + """ + date = timezone.now() + purchase = Vente.objects.create( + facture=self.f, + number=1, + name="Test purchase", + duration=1, + duration_days=0, + type_cotisation="All", + prix=0, + ) + delta = relativedelta(self.user.end_connexion(), date) + delta.microseconds=0 + self.assertEqual( + delta, + relativedelta(months=1), + ) + + def test_one_month_and_one_week_cotisation(self): + """ + It should be possible to have one day membership. + """ + date = timezone.now() + purchase = Vente.objects.create( + facture=self.f, + number=1, + name="Test purchase", + duration=1, + duration_days=7, + type_cotisation="All", + prix=0, + ) + delta = relativedelta(self.user.end_connexion(), date) + delta.microseconds=0 + self.assertEqual( + delta, + relativedelta(months=1, days=7), + ) + def tearDown(self): self.f.delete() self.user.delete() diff --git a/cotisations/test_views.py b/cotisations/test_views.py new file mode 100644 index 00000000..ba24c4d6 --- /dev/null +++ b/cotisations/test_views.py @@ -0,0 +1,166 @@ +from django.test import TestCase +from django.urls import reverse +from django.contrib.auth.models import Permission + +import datetime +from dateutil.relativedelta import relativedelta +from django.utils import timezone + +from users.models import Adherent +from .models import Vente, Facture, Cotisation, Paiement, Article + +class NewFactureTests(TestCase): + def tearDown(self): + self.user.facture_set.all().delete() + self.user.delete() + self.paiement.delete() + self.article_one_day.delete() + self.article_one_month.delete() + self.article_one_month_and_one_week.delete() + + def setUp(self): + self.user = Adherent.objects.create( + pseudo="testUser", + email="test@example.org", + ) + self.user.set_password('plopiplop') + self.user.user_permissions.set( + [ + Permission.objects.get_by_natural_key("add_facture", "cotisations", "Facture"), + Permission.objects.get_by_natural_key("use_every_payment", "cotisations", "Paiement"), + ] + ) + self.user.save() + + self.paiement = Paiement.objects.create( + moyen="test payment", + + ) + self.article_one_day = Article.objects.create( + name="One day", + prix=0, + duration=0, + duration_days=1, + type_cotisation='All', + available_for_everyone=True + ) + self.article_one_month = Article.objects.create( + name="One day", + prix=0, + duration=1, + duration_days=0, + type_cotisation='All', + available_for_everyone=True + ) + self.article_one_month_and_one_week = Article.objects.create( + name="One day", + prix=0, + duration=1, + duration_days=7, + type_cotisation='All', + available_for_everyone=True + ) + self.client.login( + username="testUser", + password="plopiplop" + ) + + def test_invoice_with_one_day(self): + data = { + "Facture-paiement": self.paiement.pk, + "form-TOTAL_FORMS": 1, + "form-INITIAL_FORMS": 0, + "form-MIN_NUM_FORMS": 0, + "form-MAX_NUM_FORMS": 1000, + "form-0-article": 1, + "form-0-quantity": 1, + } + date = timezone.now() + response = self.client.post(reverse('cotisations:new-facture', kwargs={'userid':self.user.pk}), data) + self.assertEqual( + response.status_code, + 302 + ) + self.assertEqual( + response.url, + "/users/profil/%d"%self.user.pk + ) + self.assertAlmostEqual( + self.user.end_connexion() - date, + datetime.timedelta(days=1), + delta=datetime.timedelta(seconds=1) + ) + + def test_invoice_with_one_month(self): + data = { + "Facture-paiement": self.paiement.pk, + "form-TOTAL_FORMS": 1, + "form-INITIAL_FORMS": 0, + "form-MIN_NUM_FORMS": 0, + "form-MAX_NUM_FORMS": 1000, + "form-0-article": 2, + "form-0-quantity": 1, + } + date = timezone.now() + response = self.client.post(reverse('cotisations:new-facture', kwargs={'userid':self.user.pk}), data) + self.assertEqual( + response.status_code, + 302 + ) + self.assertEqual( + response.url, + "/users/profil/%d"%self.user.pk + ) + delta = relativedelta(self.user.end_connexion(), date) + delta.microseconds=0 + self.assertEqual( + delta, + relativedelta(months=1), + ) + + def test_invoice_with_one_month_and_one_week(self): + data = { + "Facture-paiement": self.paiement.pk, + "form-TOTAL_FORMS": 2, + "form-INITIAL_FORMS": 0, + "form-MIN_NUM_FORMS": 0, + "form-MAX_NUM_FORMS": 1000, + "form-0-article": 1, + "form-0-quantity": 7, + "form-1-article": 2, + "form-1-quantity": 1, + } + date = timezone.now() + response = self.client.post(reverse('cotisations:new-facture', kwargs={'userid':self.user.pk}), data) + self.assertEqual( + response.status_code, + 302 + ) + self.assertEqual( + response.url, + "/users/profil/%d"%self.user.pk + ) + invoice = self.user.facture_set.first() + delta = relativedelta(self.user.end_connexion(), date) + delta.microseconds=0 + self.assertEqual( + delta, + relativedelta(months=1, days=7), + ) + + + def test_several_articles_creates_several_purchases(self): + data = { + "Facture-paiement": self.paiement.pk, + "form-TOTAL_FORMS": 2, + "form-INITIAL_FORMS": 0, + "form-MIN_NUM_FORMS": 0, + "form-MAX_NUM_FORMS": 1000, + "form-0-article": 2, + "form-0-quantity": 1, + "form-1-article": 2, + "form-1-quantity": 1, + } + response = self.client.post(reverse('cotisations:new-facture', kwargs={'userid':self.user.pk}), data) + f = self.user.facture_set.first() + self.assertEqual(f.vente_set.count(), 2) diff --git a/users/test_models.py b/users/test_models.py new file mode 100644 index 00000000..e9cb7d7b --- /dev/null +++ b/users/test_models.py @@ -0,0 +1,51 @@ +from django.test import TestCase + +import datetime +from django.utils import timezone + +from users.models import User +from cotisations.models import Vente, Facture, Paiement + +class UserModelTests(TestCase): + def setUp(self): + self.user = User.objects.create( + pseudo="testUser" + ) + + def tearDown(self): + self.user.facture_set.all().delete() + self.user.delete() + + def test_multiple_cotisations_are_taken_into_account(self): + paiement = Paiement.objects.create( + moyen="test payment" + ) + invoice = Facture.objects.create( + user=self.user, + paiement=paiement, + valid=True + ) + date = timezone.now() + purchase1 = Vente.objects.create( + facture=invoice, + number=1, + name="Test purchase", + duration=0, + duration_days=1, + type_cotisation="All", + prix=0, + ) + purchase2 = Vente.objects.create( + facture=invoice, + number=1, + name="Test purchase", + duration=0, + duration_days=1, + type_cotisation="All", + prix=0, + ) + self.assertAlmostEqual( + self.user.end_connexion() - date, + datetime.timedelta(days=2), + delta=datetime.timedelta(seconds=1) + )