misc: update future income computation with periodic invoicing (#326)
This commit is contained in:
parent
b29508c479
commit
0979cdaf80
|
@ -151,13 +151,22 @@ class Contrat(models.Model):
|
|||
|
||||
pourcentage_facture.short_description = 'Pourcentage facturé'
|
||||
|
||||
@property
|
||||
def montant_prestations(self):
|
||||
return Decimal(sum(p.montant() for p in self.prestations.all()))
|
||||
|
||||
def montant(self):
|
||||
"""
|
||||
Montant total d'un contrat, y compris les prestations
|
||||
optionnelles. Si pas de prestation définie, montant des factures émises.
|
||||
"""
|
||||
if self.prestations.exists():
|
||||
return Decimal(sum(p.montant() for p in self.prestations.all()))
|
||||
montant = self.montant_prestations
|
||||
if self.periodicite and self.periodicite_debut:
|
||||
return montant * self.periodicite_nombre_d_echeances()
|
||||
else:
|
||||
return montant
|
||||
|
||||
else:
|
||||
return self.montant_facture()
|
||||
|
||||
|
@ -171,12 +180,26 @@ class Contrat(models.Model):
|
|||
today_year = datetime.date.today().year
|
||||
montant_par_annee = defaultdict(Decimal)
|
||||
adjust = 0
|
||||
for year, fraction in self.percentage_per_year:
|
||||
amount = self.montant() * fraction
|
||||
if year > today_year:
|
||||
montant_par_annee[year] += amount
|
||||
else:
|
||||
adjust += amount
|
||||
if not self.periodicite:
|
||||
for year, fraction in self.percentage_per_year: # pylint: disable=not-an-iterable
|
||||
amount = self.montant() * fraction
|
||||
if year > today_year:
|
||||
montant_par_annee[year] += amount
|
||||
else:
|
||||
adjust += amount
|
||||
else:
|
||||
# calcule le montant par periode en sommant le montant des
|
||||
# prestations puis impute à chaque année ce même montant pour
|
||||
# chaque échéance arrivant dans cette année, pour les montants de
|
||||
# l'année en cours et des précédentes, tout mettre dans l'année
|
||||
# courante, ce sera diminué du total des factures déjà faites (même
|
||||
# comportement que dans le cas classique)
|
||||
montant = self.montant_prestations
|
||||
for _, debut, _ in self.periodicite_echeances(limit=20):
|
||||
if debut.year > today_year:
|
||||
montant_par_annee[debut.year] += montant
|
||||
else:
|
||||
adjust += montant
|
||||
for f in self.factures.all():
|
||||
if f.proforma:
|
||||
continue
|
||||
|
@ -234,9 +257,11 @@ class Contrat(models.Model):
|
|||
return dates
|
||||
|
||||
def periodicite_nombre_d_echeances(self):
|
||||
if not self.periodicite_fin:
|
||||
return '*'
|
||||
return len(list(self.periodicite_echeances(limit=1000)))
|
||||
if self.periodicite_fin:
|
||||
return len(list(self.periodicite_echeances(limit=1000)))
|
||||
else:
|
||||
# compter les échéances passées + 1
|
||||
return len(list(self.periodicite_echeances(limit=1)))
|
||||
|
||||
def periodicite_echeances(self, until=None, limit=3):
|
||||
i = 1
|
||||
|
|
|
@ -56,3 +56,47 @@ def test_contrat_montant_par_annee_percentage_per_year(db, django_user_model, fr
|
|||
facture.lignes.create(prix_unitaire_ht=1000, quantite=1, order=1)
|
||||
|
||||
assert sorted(list(contrat.montant_par_annee().items())) == [(2021, Decimal(5500)), (2022, Decimal(2500))]
|
||||
|
||||
|
||||
def test_contrat_montant_par_annee_recurrent(db, django_user_model, freezer):
|
||||
freezer.move_to('2021-06-01')
|
||||
client = Client.objects.create(nom=str(uuid.uuid4()))
|
||||
user = django_user_model.objects.all()[0]
|
||||
contrat = Contrat.objects.create(
|
||||
client=client,
|
||||
creator=user,
|
||||
intitule=str(uuid.uuid4()),
|
||||
periodicite='semestrielle',
|
||||
periodicite_debut=date(2020, 7, 1),
|
||||
periodicite_fin=date(2023, 7, 1),
|
||||
)
|
||||
contrat.clean()
|
||||
for i in range(2):
|
||||
contrat.prestations.create(intitule=str(i), quantite=1, prix_unitaire_ht=1000)
|
||||
|
||||
facture = Facture.objects.create(
|
||||
proforma=False,
|
||||
client=client,
|
||||
contrat=contrat,
|
||||
emission=date(2020, 1, 1),
|
||||
echeance=date(2020, 1, 16),
|
||||
creator=user,
|
||||
)
|
||||
facture.lignes.create(prix_unitaire_ht=1000, quantite=1, order=1)
|
||||
|
||||
facture = Facture.objects.create(
|
||||
proforma=False,
|
||||
client=client,
|
||||
contrat=contrat,
|
||||
emission=date(2021, 1, 1),
|
||||
echeance=date(2021, 1, 16),
|
||||
creator=user,
|
||||
)
|
||||
facture.lignes.create(prix_unitaire_ht=1000, quantite=1, order=1)
|
||||
|
||||
assert contrat.montant() == Decimal(1000) * 2 * 6
|
||||
assert sorted(list(contrat.montant_par_annee().items())) == [
|
||||
(2021, Decimal(4000)),
|
||||
(2022, Decimal(4000)),
|
||||
(2023, Decimal(2000)),
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue