[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:
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import models
|
||||
from . import wizard
|
||||
|
@@ -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",
|
||||
|
@@ -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
|
||||
|
@@ -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")
|
||||
|
37
account_budget_forecast/models/budget_forecast_model.py
Normal file
37
account_budget_forecast/models/budget_forecast_model.py
Normal 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)
|
@@ -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
|
|
@@ -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>
|
||||
|
37
account_budget_forecast/views/budget_forecast_model.xml
Normal file
37
account_budget_forecast/views/budget_forecast_model.xml
Normal 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>
|
@@ -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>
|
3
account_budget_forecast/wizard/__init__.py
Normal file
3
account_budget_forecast/wizard/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import budget_forecast_model_choice
|
@@ -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
|
@@ -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>
|
Reference in New Issue
Block a user