diff --git a/account_budget_forecast/__init__.py b/account_budget_forecast/__init__.py index cde864b..35e7c96 100644 --- a/account_budget_forecast/__init__.py +++ b/account_budget_forecast/__init__.py @@ -1,3 +1,4 @@ # -*- coding: utf-8 -*- from . import models +from . import wizard diff --git a/account_budget_forecast/__manifest__.py b/account_budget_forecast/__manifest__.py index 36b4b4a..ca01c1b 100644 --- a/account_budget_forecast/__manifest__.py +++ b/account_budget_forecast/__manifest__.py @@ -73,6 +73,7 @@ This module is maintained by ELABORE. # always loaded "data": [ "security/ir.model.access.csv", + "wizard/budget_forecast_model_choice.xml", "views/account_analytic_account.xml", "views/account_analytic_account_categories.xml", "views/account_invoice.xml", @@ -80,6 +81,7 @@ This module is maintained by ELABORE. "views/budget_forecast.xml", "views/budget_coefficient.xml", "views/budget_coefficient_model.xml", + "views/budget_forecast_model.xml", "views/product_template_form.xml", "views/project_views.xml", "views/hr_employee.xml", diff --git a/account_budget_forecast/models/__init__.py b/account_budget_forecast/models/__init__.py index 8863cd4..8f4db78 100644 --- a/account_budget_forecast/models/__init__.py +++ b/account_budget_forecast/models/__init__.py @@ -4,6 +4,7 @@ from . import account_analytic_account from . import account_analytic_line from . import account_move from . import budget_forecast +from . import budget_forecast_model from . import sale_order from . import product from . import project diff --git a/account_budget_forecast/models/budget_forecast.py b/account_budget_forecast/models/budget_forecast.py index 20daede..896178d 100644 --- a/account_budget_forecast/models/budget_forecast.py +++ b/account_budget_forecast/models/budget_forecast.py @@ -16,7 +16,6 @@ class BudgetForecast(models.Model): "account.analytic.account", "Analytic Account", required=True, - ondelete="restrict", index=True, copy=True, ) @@ -138,25 +137,24 @@ class BudgetForecast(models.Model): parent_ids = self.mapped("parent_id") if not child_unlink: for record in self: - if not record.is_summary and ( - record.display_type - in [ - "line_section", - "line_subsection", - ] - ): - # find similar section/sub_section lines - lines = record.env["budget.forecast"].search( - [ + if record.display_type in [ + "line_section", + "line_subsection", + ]: + if record.is_summary: + domain = [("summary_id", "=", record.id)] + else: + domain = [ + ("id", "!=", record.id), "|", ("summary_id", "=", record.summary_id.id), ("id", "=", record.summary_id.id), ] - ) + # find similar section/sub_section lines + lines = record.env["budget.forecast"].search(domain) for line in lines: line.unlink(True) res = super(BudgetForecast, self).unlink() - parent_ids.exists()._calc_plan() return res @api.onchange("product_id") diff --git a/account_budget_forecast/models/budget_forecast_model.py b/account_budget_forecast/models/budget_forecast_model.py new file mode 100644 index 0000000..d267cf6 --- /dev/null +++ b/account_budget_forecast/models/budget_forecast_model.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- + +from odoo import models, fields, api, _ + + +class BudgetForecastModel(models.Model): + _name = "budget.forecast.model" + _description = _name + + name = fields.Char("Name", copy=False) + + +class BudgetForecastModelLine(models.Model): + _name = "budget.forecast.model.line" + _description = _name + + budget_model = fields.Many2one("budget.forecast.model", copy=True) + + name = fields.Char("Name", copy=True) + + display_type = fields.Selection( + [ + ("line_section", "Section"), + ("line_subsection", "Sub-Section"), + ], + copy=True, + store=True, + ) + product_id = fields.Many2one( + "product.product", copy=True, domain="[('budget_level', '=', display_type)]" + ) + parent_id = fields.Many2one( + "budget.forecast.model.line", + store=True, + copy=False, + ) + child_ids = fields.One2many("budget.forecast.model.line", "parent_id", copy=False) diff --git a/account_budget_forecast/security/ir.model.access.csv b/account_budget_forecast/security/ir.model.access.csv index 60a888d..adccaf2 100644 --- a/account_budget_forecast/security/ir.model.access.csv +++ b/account_budget_forecast/security/ir.model.access.csv @@ -1,4 +1,7 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_budget_forecast_project_user,access_budget_forecast_project_user,model_budget_forecast,project.group_project_user,1,1,1,1 access_budget_coefficient,budget_coefficient,model_budget_coefficient,base.group_user,1,1,1,1 -access_budget_coefficient_model,budget_coefficient_model,model_budget_coefficient_model,base.group_user,1,1,1,1 \ No newline at end of file +access_budget_coefficient_model,budget_coefficient_model,model_budget_coefficient_model,base.group_user,1,1,1,1 +access_budget_forecast_model,budget_forecast_model,model_budget_forecast_model,base.group_user,1,1,1,1 +access_budget_forecast_model_line,budget_forecast_model_line,model_budget_forecast_model_line,base.group_user,1,1,1,1 +access_budget_forecast_model_choice,budget_forecast_model_choice,model_budget_forecast_model_choice,base.group_user,1,1,1,1 \ No newline at end of file diff --git a/account_budget_forecast/views/account_analytic_account.xml b/account_budget_forecast/views/account_analytic_account.xml index a849024..79da595 100644 --- a/account_budget_forecast/views/account_analytic_account.xml +++ b/account_budget_forecast/views/account_analytic_account.xml @@ -17,6 +17,7 @@ + diff --git a/account_budget_forecast/views/budget_forecast_model.xml b/account_budget_forecast/views/budget_forecast_model.xml new file mode 100644 index 0000000..03ce18f --- /dev/null +++ b/account_budget_forecast/views/budget_forecast_model.xml @@ -0,0 +1,37 @@ + + + + budget.forecast.model.tree + budget.forecast.model + + + + + + + + + budget.forecast.model.line.tree + budget.forecast.model.line + + + + + + + + + + + + + Budget Forecast Model + budget.forecast.model + tree + + + Budget Forecast Model Lines + budget.forecast.model.line + tree + + \ No newline at end of file diff --git a/account_budget_forecast/views/menu.xml b/account_budget_forecast/views/menu.xml index 1dedcc1..acc4adc 100644 --- a/account_budget_forecast/views/menu.xml +++ b/account_budget_forecast/views/menu.xml @@ -5,4 +5,8 @@ + + + + \ No newline at end of file diff --git a/account_budget_forecast/wizard/__init__.py b/account_budget_forecast/wizard/__init__.py new file mode 100644 index 0000000..6f9d6a4 --- /dev/null +++ b/account_budget_forecast/wizard/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import budget_forecast_model_choice diff --git a/account_budget_forecast/wizard/budget_forecast_model_choice.py b/account_budget_forecast/wizard/budget_forecast_model_choice.py new file mode 100644 index 0000000..1221c9e --- /dev/null +++ b/account_budget_forecast/wizard/budget_forecast_model_choice.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +import logging + +from bdb import set_trace +from odoo import models, fields, _ + +_logger = logging.getLogger(__name__) + + +class BudgetForecastModelChoice(models.Model): + _name = "budget.forecast.model.choice" + _description = _name + + budget_forecast_model = fields.Many2one("budget.forecast.model") + + def create_budget_forecast_lines(self): + analytic_account = self.env["account.analytic.account"].browse( + self._context.get("active_ids") + ) + # Budget line deletion must be done in a precise order to avoid trying to unlink already deleted lines. + # 1. Delete summary lines to remove all the linked section and subsection lines + for line in analytic_account.budget_forecast_ids.filtered( + lambda r: r.is_summary + ): + _logger.debug("SUMMARY BUDGET LINE = %s", line.name) + line.unlink() + + # 2. Delete article and note lines + for line in analytic_account.budget_forecast_ids.filtered( + lambda r: r.display_type in ["line_article", "line_note"] + ): + _logger.debug("OTHER BUDGET LINE = %s", line.name) + line.unlink() + + if self.budget_forecast_model: + # Create new summary lines + section_model_lines = self.env["budget.forecast.model.line"].search( + [ + ("budget_model", "=", self.budget_forecast_model.id), + ("display_type", "=", "line_section"), + ] + ) + sequence = 0 + for section in section_model_lines: + vals = { + "analytic_id": self.env["account.analytic.account"] + .browse(self._context.get("active_ids")) + .id, + "display_type": "line_section", + "product_id": section.product_id.id, + "description": section.name, + "is_summary": True, + "sequence": sequence, + } + section_line = self.env["budget.forecast"].create(vals) + sequence += 1 + if section.child_ids: + for sub_section in section.child_ids: + vals = { + "analytic_id": self.env["account.analytic.account"] + .browse(self._context.get("active_ids")) + .id, + "display_type": "line_subsection", + "product_id": sub_section.product_id.id, + "description": sub_section.name, + "is_summary": True, + "parent_id": section_line.id, + "sequence": sequence, + } + self.env["budget.forecast"].create(vals) + sequence += 1 diff --git a/account_budget_forecast/wizard/budget_forecast_model_choice.xml b/account_budget_forecast/wizard/budget_forecast_model_choice.xml new file mode 100644 index 0000000..9124076 --- /dev/null +++ b/account_budget_forecast/wizard/budget_forecast_model_choice.xml @@ -0,0 +1,31 @@ + + + + + budget.forecast.model.wizard + budget.forecast.model.choice + + + + + Caution: all current budget lines will be deleted! + + + + + + + + + + + Reset Budget + budget.forecast.model.choice + form + + new + + \ No newline at end of file