mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-12-23 07:23:46 +00:00
Merge branch 'fix-overlapping-invoices' into 'dev'
Fix Overlapping invoices. See merge request federez/re2o!476
This commit is contained in:
commit
9e87f796aa
3 changed files with 126 additions and 43 deletions
|
@ -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):
|
||||
|
@ -488,9 +513,7 @@ class Vente(RevMixin, AclMixin, models.Model):
|
|||
|
||||
def create_cotis(self, date_start=False):
|
||||
"""
|
||||
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
|
||||
|
@ -500,33 +523,16 @@ class Vente(RevMixin, AclMixin, models.Model):
|
|||
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"]
|
||||
cotisation.date_start = date_start
|
||||
cotisation.date_end = cotisation.date_start + relativedelta(
|
||||
months=(self.duration or 0) * self.number,
|
||||
days=(self.duration_days or 0) * self.number,
|
||||
)
|
||||
elif self.type_cotisation == "Adhesion":
|
||||
end_cotisation = invoice.user.end_adhesion()
|
||||
self.save()
|
||||
cotisation.save()
|
||||
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,82 @@ 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 test_date_start_cotisation(self):
|
||||
"""
|
||||
It should be possible to add a cotisation with a specific start date
|
||||
"""
|
||||
v = Vente(
|
||||
facture=self.f,
|
||||
number=1,
|
||||
name="Test purchase",
|
||||
duration=0,
|
||||
duration_days=1,
|
||||
type_cotisation = 'All',
|
||||
prix=0
|
||||
)
|
||||
v.create_cotis(date_start=timezone.make_aware(datetime.datetime(1998, 10, 16)))
|
||||
v.save()
|
||||
self.assertEqual(v.cotisation.date_end, timezone.make_aware(datetime.datetime(1998, 10, 17)))
|
||||
|
||||
|
||||
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()
|
||||
|
|
Loading…
Reference in a new issue