[NEW] Add budget model funcitonnalities

User is able to generate budget model and model lines
User can reset a budget and generate one using an existing model
This commit is contained in:
Stéphan Sainléger
2022-05-22 18:36:48 +02:00
parent cc9101429a
commit 33521aef9b
12 changed files with 203 additions and 14 deletions

View File

@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
from . import models
from . import wizard

View File

@@ -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",

View File

@@ -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

View File

@@ -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")

View File

@@ -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)

View File

@@ -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
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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_budget_forecast_project_user access_budget_forecast_project_user model_budget_forecast project.group_project_user 1 1 1 1
3 access_budget_coefficient budget_coefficient model_budget_coefficient base.group_user 1 1 1 1
4 access_budget_coefficient_model budget_coefficient_model model_budget_coefficient_model base.group_user 1 1 1 1
5 access_budget_forecast_model budget_forecast_model model_budget_forecast_model base.group_user 1 1 1 1
6 access_budget_forecast_model_line budget_forecast_model_line model_budget_forecast_model_line base.group_user 1 1 1 1
7 access_budget_forecast_model_choice budget_forecast_model_choice model_budget_forecast_model_choice base.group_user 1 1 1 1

View File

@@ -17,6 +17,7 @@
<button type="object" class="oe_stat_button" icon="fa-eye" name="displayActualAmounts" string="Hide Actual amounts" attrs="{'invisible' : [('display_actual_amounts', '=', False)]}">
<field name="display_actual_amounts" widget="boolean_toggle" />
</button>
<button type="action" class="oe_stat_button" icon="fa-refresh" name="%(action_budget_forecast_model_choice)d" string="Reset Budget" />
</header>
<sheet string="Project Budget">
<group>

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_budget_forecast_model_tree" model="ir.ui.view">
<field name="name">budget.forecast.model.tree</field>
<field name="model">budget.forecast.model</field>
<field name="arch" type="xml">
<tree editable="top">
<field name="name" />
</tree>
</field>
</record>
<record id="view_budget_forecast_model_line_tree" model="ir.ui.view">
<field name="name">budget.forecast.model.line.tree</field>
<field name="model">budget.forecast.model.line</field>
<field name="arch" type="xml">
<tree editable="top">
<field name="budget_model" />
<field name="display_type" />
<field name="product_id" />
<field name="name" />
<field name="parent_id" />
</tree>
</field>
</record>
<record id="act_budget_forecast_models" model="ir.actions.act_window">
<field name="name">Budget Forecast Model</field>
<field name="res_model">budget.forecast.model</field>
<field name="view_mode">tree</field>
</record>
<record id="act_budget_forecast_model_lines" model="ir.actions.act_window">
<field name="name">Budget Forecast Model Lines</field>
<field name="res_model">budget.forecast.model.line</field>
<field name="view_mode">tree</field>
</record>
</odoo>

View File

@@ -5,4 +5,8 @@
<menuitem id="menu_budget_forecast_coeff_models" action="act_budget_forecast_coeff_models" parent="project.menu_project_config" sequence="20" />
<menuitem id="menu_budget_forecast_models" action="act_budget_forecast_models" parent="project.menu_project_config" sequence="20" />
<menuitem id="menu_budget_forecast_model_lines" action="act_budget_forecast_model_lines" parent="project.menu_project_config" sequence="20" />
</odoo>

View File

@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import budget_forecast_model_choice

View File

@@ -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

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="budget_forecast_model_wizard" model="ir.ui.view">
<field name="name">budget.forecast.model.wizard</field>
<field name="model">budget.forecast.model.choice</field>
<field name="arch" type="xml">
<form string="Reset : choose the Budget Forecast Model">
<div class="alert alert-warning">
<span class="fa fa-info-circle" />
Caution: all current budget lines will be deleted!
</div>
<group>
<field name="budget_forecast_model" widget="selection" placeholder="Empty budget" />
</group>
<footer>
<button string="Select" name="create_budget_forecast_lines" type="object" class="btn-primary" />
<button string="Cancel" class="btn-secondary" special="cancel" />
</footer>
</form>
</field>
</record>
<record id="action_budget_forecast_model_choice" model="ir.actions.act_window">
<field name="name">Reset Budget</field>
<field name="res_model">budget.forecast.model.choice</field>
<field name="view_mode">form</field>
<field name="view_id" ref="budget_forecast_model_wizard" />
<field name="target">new</field>
</record>
</odoo>