diff --git a/rental_fees/models/rental_fees_computation.py b/rental_fees/models/rental_fees_computation.py index e0369b649..339493c18 100644 --- a/rental_fees/models/rental_fees_computation.py +++ b/rental_fees/models/rental_fees_computation.py @@ -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() @@ -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: diff --git a/rental_fees/models/rental_fees_definition.py b/rental_fees/models/rental_fees_definition.py index 8a913f5a4..c06f73d2b 100644 --- a/rental_fees/models/rental_fees_definition.py +++ b/rental_fees/models/rental_fees_definition.py @@ -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 = ( @@ -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"]: @@ -311,7 +319,7 @@ 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 @@ -319,7 +327,7 @@ def compute_fees(self, period): "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"]), @@ -327,11 +335,18 @@ def compute_fees(self, period): (_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":