Commit 05501c90 authored by klafyvel's avatar klafyvel Committed by root

Fix Overlapping invoices.

parent c3fc672f
Pipeline #2340 passed with stage
in 4 minutes and 8 seconds
......@@ -292,15 +292,40 @@ class Facture(BaseInvoice):
return bool(self.get_subscription())
def reorder_purchases(self):
date = self.date
date_adh = max(self.date, self.user.end_adhesion())
date_con = max(self.date, self.user.end_connexion())
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,
)
if cotisation.type_cotisation == 'Connexion':
cotisation.date_start = date_con
date_con += relativedelta(
months=(purchase.duration or 0) * purchase.number,
days=(purchase.duration_days or 0) * purchase.number,
)
cotisation.date_end = date_con
elif cotisation.type_cotisation == 'Adhesion':
cotisation.date_start = date_adh
date_adh += relativedelta(
months=(purchase.duration or 0) * purchase.number,
days=(purchase.duration_days or 0) * purchase.number,
)
cotisation.date_end = date_adh
else: # it is assumed that adhesion is required for a connexion
date = min(date_adh, date_con)
cotisation.date_start = date
date_adh += relativedelta(
months=(purchase.duration or 0) * purchase.number,
days=(purchase.duration_days or 0) * purchase.number,
)
date_con += relativedelta(
months=(purchase.duration or 0) * purchase.number,
days=(purchase.duration_days or 0) * purchase.number,
)
date = max(date_adh, date_con)
cotisation.date_end = date
cotisation.save()
purchase.facture = self
purchase.save()
def save(self, *args, **kwargs):
......@@ -486,11 +511,9 @@ class Vente(RevMixin, AclMixin, models.Model):
)
return
def create_cotis(self, date_start=False):
def create_cotis(self):
"""
Update and create a 'cotisation' related object if there is a
cotisation_type defined (which means the article sold represents
a cotisation)
Creates a cotisation without initializing the dates (start and end ar set to self.facture.facture.date) and without saving it. You should use Facture.reorder_purchases to set the right dates.
"""
try:
invoice = self.facture.facture
......@@ -499,34 +522,8 @@ class Vente(RevMixin, AclMixin, models.Model):
if not hasattr(self, "cotisation") and self.type_cotisation:
cotisation = Cotisation(vente=self)
cotisation.type_cotisation = self.type_cotisation
if date_start:
end_cotisation = (
Cotisation.objects.filter(
vente__in=Vente.objects.filter(
facture__in=Facture.objects.filter(
user=invoice.user
).exclude(valid=False)
)
)
.filter(
Q(type_cotisation="All")
| Q(type_cotisation=self.type_cotisation)
)
.filter(date_start__lt=date_start)
.aggregate(Max("date_end"))["date_end__max"]
)
elif self.type_cotisation == "Adhesion":
end_cotisation = invoice.user.end_adhesion()
else:
end_cotisation = invoice.user.end_connexion()
date_start = date_start or timezone.now()
end_cotisation = end_cotisation or date_start
date_max = max(end_cotisation, date_start)
cotisation.date_start = date_max
cotisation.date_end = cotisation.date_start + relativedelta(
months=(self.duration or 0) * self.number,
days=(self.duration_days or 0) * self.number,
)
cotisation.date_start = invoice.date
cotisation.date_end = invoice.date
def save(self, *args, **kwargs):
"""
......
......@@ -10,7 +10,7 @@ from .models import Vente, Facture, Cotisation, Paiement
class VenteModelTests(TestCase):
def setUp(self):
self.user = User.objects.create(pseudo="testUser", email="test@example.org")
self.user = User.objects.create(pseudo="testUserPlop", email="test@example.org")
self.paiement = Paiement.objects.create(moyen="test payment")
self.f = Facture.objects.create(
user=self.user, paiement=self.paiement, valid=True
......@@ -30,6 +30,7 @@ class VenteModelTests(TestCase):
type_cotisation="All",
prix=0,
)
self.f.reorder_purchases()
self.assertAlmostEqual(
self.user.end_connexion() - date,
datetime.timedelta(days=1),
......@@ -41,7 +42,7 @@ class VenteModelTests(TestCase):
It should be possible to have one day membership.
"""
date = timezone.now()
purchase = Vente.objects.create(
Vente.objects.create(
facture=self.f,
number=1,
name="Test purchase",
......@@ -50,16 +51,19 @@ class VenteModelTests(TestCase):
type_cotisation="All",
prix=0,
)
delta = relativedelta(self.user.end_connexion(), date)
delta.microseconds = 0
self.assertEqual(delta, relativedelta(months=1))
self.f.reorder_purchases()
end = self.user.end_connexion()
expected_end = date + relativedelta(months=1)
self.assertEqual(end.day, expected_end.day)
self.assertEqual(end.month, expected_end.month)
self.assertEqual(end.year, expected_end.year)
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(
Vente.objects.create(
facture=self.f,
number=1,
name="Test purchase",
......@@ -68,11 +72,64 @@ class VenteModelTests(TestCase):
type_cotisation="All",
prix=0,
)
delta = relativedelta(self.user.end_connexion(), date)
delta.microseconds = 0
self.assertEqual(delta, relativedelta(months=1, days=7))
self.f.reorder_purchases()
end = self.user.end_connexion()
expected_end = date + relativedelta(months=1, days=7)
self.assertEqual(end.day, expected_end.day)
self.assertEqual(end.month, expected_end.month)
self.assertEqual(end.year, expected_end.year)
def tearDown(self):
self.f.delete()
self.user.delete()
self.paiement.delete()
class FactureModelTests(TestCase):
def setUp(self):
self.user = User.objects.create(pseudo="testUserPlop", email="test@example.org")
self.paiement = Paiement.objects.create(moyen="test payment")
def tearDown(self):
self.user.delete()
self.paiement.delete()
def test_cotisations_prolongation(self):
"""When user already have one valid cotisation, the new one should be
added at the end of the existing one."""
date = timezone.now()
invoice1 = Facture.objects.create(
user=self.user, paiement=self.paiement, valid=True
)
Vente.objects.create(
facture=invoice1,
number=1,
name="Test purchase",
duration=1,
duration_days=0,
type_cotisation="All",
prix=0,
)
invoice1.reorder_purchases()
invoice2 = Facture.objects.create(
user=self.user, paiement=self.paiement, valid=True
)
Vente.objects.create(
facture=invoice2,
number=1,
name="Test purchase",
duration=1,
duration_days=0,
type_cotisation="All",
prix=0,
)
invoice1.reorder_purchases()
delta = relativedelta(self.user.end_connexion(), date)
delta.microseconds = 0
try:
self.assertEqual(delta, relativedelta(months=2))
except Exception as e:
invoice1.delete()
invoice2.delete()
raise e
invoice1.delete()
invoice2.delete()
......@@ -144,6 +144,8 @@ def new_facture(request, user, userid):
price_ok = True
if price_ok:
new_invoice_instance.save()
# Saving purchases so the invoice can find them. Invoice
# will modify them after being validated to put the right dates.
for p in purchases:
p.facture = new_invoice_instance
p.save()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment