Skip to content

Commit

Permalink
WIP unroll periods on forecast mode
Browse files Browse the repository at this point in the history
  • Loading branch information
fcayre committed Oct 20, 2023
1 parent ad1e414 commit 0fc4ca6
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 24 deletions.
39 changes: 31 additions & 8 deletions rental_fees/models/rental_fees_computation.py
Original file line number Diff line number Diff line change
Expand Up @@ -599,23 +599,44 @@ def _add_compensation(
)

def _add_fees_periods(self, device, periods):
for period in periods:
def_line = period["fees_def_line"]
"Insert computation details, further detailing the period in forecast mode"

def insert_detail(fees, contract, from_date, to_date, def_line, is_forecast):
self.env["rental_fees.computation.detail"].sudo().create(
{
"fees_computation_id": self.id,
"fees": period["fees"],
"fees_type": "fees",
"lot_id": device.id,
"contract_id": period["contract"].id,
"from_date": period["from_date"],
"to_date": period["to_date"] - one_day, # dates included in the DB
"contract_id": contract.id,
"from_date": from_date,
"to_date": to_date - one_day,
"fees_definition_id": def_line.fees_definition_id.id,
"fees_definition_line_id": def_line.id,
"is_forecast": period["is_forecast"],
"is_forecast": is_forecast,
}
)

for period in periods:
if self.has_forecast:
for from_date, to_date, amount in period["monthly_fees"]:
insert_detail(
amount,
period["contract"],
from_date,
to_date,
period["fees_def_line"],
period["is_forecast"],
)
else:
insert_detail(
period["fees"],
period["contract"],
period["from_date"],
period["to_date"],
period["fees_def_line"],
period["is_forecast"],
)

@job(default_channel="root")
def _run(self):
self.ensure_one()
Expand Down Expand Up @@ -647,7 +668,9 @@ def _run_for_fees_def(self, fees_def):

device_fees = 0.0
for period in periods:
period["fees"] = period["fees_def_line"].compute_fees(period)
monthly_fees = period["fees_def_line"].compute_monthly_fees(period)
period["monthly_fees"] = monthly_fees
period["fees"] = sum(amount for _ds, _de, amount in monthly_fees)
device_fees += period["fees"]

if no_rental_limit:
Expand Down
47 changes: 31 additions & 16 deletions rental_fees/models/rental_fees_definition.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@
from odoo.tools import misc


def month_intervals(period):
one_month = relativedelta(months=1)
from_date = period["from_date"]
while from_date < period["to_date"]:
to_date = from_date + one_month
yield from_date, to_date
from_date = to_date


class RentalFeesDefinition(models.Model):
_name = "rental_fees.definition"
_description = (
Expand Down Expand Up @@ -283,24 +292,23 @@ def compute_end_date(self, origin_date):
)

@api.multi
def compute_fees(self, period):
"""Simplist computation of the fees based on the invoiced amounts in
the period.
def compute_monthly_fees(self, period):
"""Return a (from_date, to_date, amount) list of monthly fees for the period
When contract periodicity is bigger than a month, the fees may
be 0 for a while then paid in one big go.
When the period is a forecast, we use the contract forecast table,
otherwise the invoice table is used.
"""

self.ensure_one()

result = []

if self.fees_type == "fix":
if self.monthly_fees == 0.0:
return 0.0
else:
return (
self.monthly_fees
* relativedelta(period["to_date"], period["from_date"]).months
)
for from_date, to_date in month_intervals(period):
result.append((from_date, to_date, self.monthly_fees))

elif self.fees_type == "proportional":
if period["is_forecast"]:
Expand All @@ -311,27 +319,34 @@ def compute_fees(self, period):
("date_invoice", "<", period["to_date"]),
]
)
return sum(p.price_subtotal * self.monthly_fees for p in forecasts)
date_amounts = [(p.date_invoice, p.price_subtotal) for p in forecasts]

else:
_pt = self.fees_definition_id.product_template_id
_path_to_storable = (
"contract_line_id.sale_order_line_id"
".product_id.product_tmpl_id.storable_product_id"
)
invoice_lines = self.env["account.invoice.line"].search(
ilines = self.env["account.invoice.line"].search(
[
("contract_line_id.contract_id", "=", period["contract"].id),
("date_invoice", ">=", period["from_date"]),
("date_invoice", "<", period["to_date"]),
(_path_to_storable, "=", _pt.id),
],
)
date_amounts = [
(i.date_invoice, i.price_total - i.price_tax) for i in ilines
]

return (
sum(i.price_total - i.price_tax for i in invoice_lines)
* self.monthly_fees
)
for from_date, to_date in month_intervals(period):
total = 0.0
for date, amount in date_amounts:
if from_date <= date < to_date:
total += amount
result.append((from_date, to_date, total * self.monthly_fees))

return result

def format_fees_amount(self):
if self.fees_type == "proportional":
Expand Down

0 comments on commit 0fc4ca6

Please sign in to comment.