diff --git a/account_spread_cost_revenue/models/account_spread.py b/account_spread_cost_revenue/models/account_spread.py index 6ee0f6f5..445d732b 100644 --- a/account_spread_cost_revenue/models/account_spread.py +++ b/account_spread_cost_revenue/models/account_spread.py @@ -3,6 +3,7 @@ import calendar import time +from datetime import timedelta from dateutil.relativedelta import relativedelta @@ -44,6 +45,11 @@ class AccountSpread(models.Model): help="Period length for the entries", required=True, ) + days_calc = fields.Boolean( + string="Calculate by days", + default=False, + help="Use number of days to calculate amount", + ) use_invoice_line_account = fields.Boolean() credit_account_id = fields.Many2one( "account.account", @@ -242,6 +248,7 @@ class AccountSpread(models.Model): self.period_type = self.template_id.period_type if self.template_id.start_date: self.spread_date = self.template_id.start_date + self.days_calc = self.template_id.days_calc @api.depends("invoice_type", "company_id") def _compute_journal_id(self): @@ -368,8 +375,9 @@ class AccountSpread(models.Model): for x in range(len(posted_line_ids), number_of_periods): sequence = x + 1 + date = self._get_last_day_of_month(spread_date) amount = self._compute_board_amount( - sequence, unposted_amount, number_of_periods + sequence, unposted_amount, number_of_periods, date ) amount = self.currency_id.round(amount) rounding = self.currency_id.rounding @@ -380,7 +388,7 @@ class AccountSpread(models.Model): "amount": amount, "spread_id": self.id, "name": self._get_spread_entry_name(sequence), - "date": self._get_last_day_of_month(spread_date), + "date": date, } commands.append((0, False, vals)) @@ -398,22 +406,78 @@ class AccountSpread(models.Model): self.ensure_one() return self.period_number + 1 if month_day != 1 else self.period_number + @staticmethod + def _get_first_day_of_month(spread_date): + return spread_date + relativedelta(day=1) + @staticmethod def _get_last_day_of_month(spread_date): return spread_date + relativedelta(day=31) - def _compute_board_amount(self, sequence, amount, number_of_periods): + def _get_spread_start_date(self, period_type, spread_end_date): + self.ensure_one() + spread_start_date = spread_end_date + relativedelta(days=1) + if period_type == "month": + spread_start_date = spread_end_date + relativedelta(day=1) + elif period_type == "quarter": + spread_start_date = spread_start_date - relativedelta(months=3) + elif period_type == "year": + spread_start_date = spread_start_date - relativedelta(years=1) + spread_start_date = self._get_first_day_of_month(spread_start_date) + spread_start_date = max(spread_start_date, self.spread_date) + return spread_start_date + + def _get_spread_end_date(self, period_type, period_number, spread_start_date): + self.ensure_one() + spread_end_date = spread_start_date + number_of_periods = ( + period_number if spread_start_date.day != 1 else period_number - 1 + ) + if period_type == "month": + spread_end_date = spread_start_date + relativedelta( + months=number_of_periods + ) + elif period_type == "quarter": + months = number_of_periods * 3 + spread_end_date = spread_start_date + relativedelta(months=months) + elif period_type == "year": + spread_end_date = spread_start_date + relativedelta(years=number_of_periods) + # calculate by days and not first day of month should compute residual day only + if self.days_calc and spread_end_date.day != 1: + spread_end_date = spread_end_date - timedelta(days=1) + else: + spread_end_date = self._get_last_day_of_month(spread_end_date) + return spread_end_date + + def _get_amount_per_day(self, amount): + self.ensure_one() + spread_start_date = self.spread_date + spread_end_date = self._get_spread_end_date( + self.period_type, self.period_number, spread_start_date + ) + number_of_days = (spread_end_date - spread_start_date).days + 1 + return amount / number_of_days + + def _compute_board_amount( + self, sequence, amount, number_of_periods, spread_end_date + ): """Calculates the amount for the spread lines.""" self.ensure_one() amount_to_spread = self.total_amount + period = self.period_number if sequence != number_of_periods: - amount = amount_to_spread / self.period_number + amount = amount_to_spread / period if sequence == 1: date = self.spread_date month_days = calendar.monthrange(date.year, date.month)[1] days = month_days - date.day + 1 - period = self.period_number amount = (amount_to_spread / period) / month_days * days + if self.days_calc: + spread_start_date = self._get_spread_start_date( + self.period_type, spread_end_date + ) + days = (spread_end_date - spread_start_date).days + 1 + amount = self._get_amount_per_day(amount_to_spread) * days return amount def compute_spread_board(self): diff --git a/account_spread_cost_revenue/models/account_spread_template.py b/account_spread_cost_revenue/models/account_spread_template.py index 56944a71..090e76f6 100644 --- a/account_spread_cost_revenue/models/account_spread_template.py +++ b/account_spread_cost_revenue/models/account_spread_template.py @@ -50,6 +50,11 @@ class AccountSpreadTemplate(models.Model): help="Period length for the entries", ) start_date = fields.Date() + days_calc = fields.Boolean( + string="Calculate by days", + default=False, + help="Use number of days to calculate amount", + ) auto_spread = fields.Boolean( string="Auto assign template on invoice validate", help="If checked, provide option to auto create spread during " @@ -120,6 +125,7 @@ class AccountSpreadTemplate(models.Model): "template_id": self.id, "journal_id": self.spread_journal_id.id, "use_invoice_line_account": self.use_invoice_line_account, + "days_calc": self.days_calc, "company_id": company.id, } diff --git a/account_spread_cost_revenue/views/account_spread.xml b/account_spread_cost_revenue/views/account_spread.xml index 8461f21f..737cd56d 100644 --- a/account_spread_cost_revenue/views/account_spread.xml +++ b/account_spread_cost_revenue/views/account_spread.xml @@ -249,6 +249,7 @@ domain="[('company_id', '=', company_id)]" widget="selection" /> + diff --git a/account_spread_cost_revenue/views/account_spread_template.xml b/account_spread_cost_revenue/views/account_spread_template.xml index 9686ad56..ebf6cfef 100644 --- a/account_spread_cost_revenue/views/account_spread_template.xml +++ b/account_spread_cost_revenue/views/account_spread_template.xml @@ -26,6 +26,7 @@ +