Skip to content

Commit ee354fb

Browse files
committed
[ADD] budget_management: new module created
Created models for Budget and Budget Line. Created wizard (transient model, views, and action) for adding new budgets based on a selected time period. Developed Kanban and form views for the budget model & list view for budget line. Updated actions to allow opening budget lines directly from Kanban boxes. Implemented views and menu items for the Budget and Budget Line models.
1 parent 18cdf11 commit ee354fb

14 files changed

+405
-0
lines changed

budget_management/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from . import models
2+
from . import wizards

budget_management/__manifest__.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "Budget Management",
3+
"version": "1.0",
4+
"depends": ["base", "account"],
5+
"author": "djip-odoo",
6+
"description": """
7+
Part of technical training
8+
Creating Budget Management module as review task
9+
""",
10+
"data": [
11+
"security/ir.model.access.csv",
12+
"views/budget_line_views.xml",
13+
"wizards/actions_wizard.xml",
14+
"views/actions_menu_and_button.xml",
15+
"views/menu_views.xml",
16+
"views/budget_views.xml",
17+
"wizards/wizard_add_budgets_view.xml",
18+
],
19+
"application": True,
20+
"installable": True,
21+
"auto_install": False,
22+
"license": "LGPL-3",
23+
}

budget_management/models/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from . import budget
2+
from . import budget_line

budget_management/models/budget.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
from odoo import models, fields, api
2+
from datetime import date
3+
4+
5+
class Budget(models.Model):
6+
_name = "budget.budget"
7+
_inherit = ["mail.thread", "mail.activity.mixin"]
8+
9+
name = fields.Char(compute="_compute_budget_name", store=True, readonly=True)
10+
active = fields.Boolean(default=True)
11+
is_favorite = fields.Boolean(default=False)
12+
state = fields.Selection(
13+
selection=[
14+
("draft", "Draft"),
15+
("confirmed", "Confirmed"),
16+
("revised", "Revised"),
17+
("done", "Done"),
18+
],
19+
required=True,
20+
default="draft",
21+
tracking=True,
22+
)
23+
on_over_budget = fields.Selection(
24+
selection=[("warning", "Warning"), ("restriction", "Restriction")],
25+
tracking=True,
26+
)
27+
responsible = fields.Many2one(
28+
comodel_name="res.users", # Assuming you want a link to Odoo users
29+
string="Responsible",
30+
tracking=True,
31+
)
32+
revision_id = fields.Many2one(
33+
comodel_name="res.users", # Assuming you want a link to Odoo users
34+
tracking=True,
35+
readonly=True,
36+
)
37+
date_start = fields.Date(string="Start Date", required=True)
38+
date_end = fields.Date(string="Expiration Date", required=True, index=True)
39+
company_id = fields.Many2one(
40+
"res.company",
41+
string="Company",
42+
default=lambda self: self.env.company,
43+
)
44+
45+
budget_line_ids = fields.One2many(
46+
comodel_name="budget.management.budget.lines", inverse_name="budget_id"
47+
)
48+
49+
@api.depends("date_start", "date_end")
50+
def _compute_budget_name(self):
51+
for record in self:
52+
if record.date_start and record.date_end:
53+
start_date = record.date_start.strftime("%Y-%m")
54+
end_date = record.date_end.strftime("%Y-%m")
55+
record.name = f"Budget {start_date} to {end_date}"
56+
else:
57+
record.name = "Unknown Budget"
58+
59+
def onclick_reset_to_draft(self):
60+
for record in self:
61+
if record.state != "draft":
62+
record.state = "draft"
63+
64+
def onclick_revise(self):
65+
for record in self:
66+
if record.state in ["confirmed", "draft"]:
67+
record.revision_id = lambda self: self.env.user
68+
record.state = "revised"
69+
70+
def onclick_done(self):
71+
for record in self:
72+
if record.state in ["confirmed", "revised"]:
73+
record.state = "done"
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from odoo import models, fields, api
2+
3+
class BudgetLine(models.Model):
4+
_name = "budget.management.budget.lines"
5+
6+
name = fields.Char()
7+
budget_id = fields.Many2one(comodel_name="budget.budget", string="Budget")
8+
budget_amount = fields.Float(default=0.0)
9+
achieved_amount = fields.Float(default=0.0)
10+
achieved_percentage = fields.Float(
11+
default=0.0,
12+
compute="_compute_achieved_percentage",
13+
store=True
14+
)
15+
analytic_account_id = fields.Many2one('account.analytic.account', string='Analytic Account')
16+
# analytic_line_ids = fields.One2many('account.analytic.line', string='Analytic Account')
17+
18+
@api.depends("budget_amount", "achieved_amount")
19+
def _compute_achieved_percentage(self):
20+
for record in self:
21+
if record.budget_amount:
22+
record.achieved_percentage = (record.achieved_amount / record.budget_amount) * 100
23+
else:
24+
record.achieved_percentage = 0.0
25+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
2+
budget_management.access_budget_budget,access_budget_budget,budget_management.model_budget_budget,base.group_user,1,1,1,1
3+
budget_management.access_add_budget_wizard,access_add_budget_wizard,budget_management.model_add_budget_wizard,base.group_user,1,1,1,0
4+
budget_management.access_budget_management_budget_lines,access_budget_management_budget_lines,budget_management.model_budget_management_budget_lines,base.group_user,1,1,1,1
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<odoo>
2+
<record id="action_budget_management_menu_budget" model="ir.actions.act_window">
3+
<field name="name">Budgets</field>
4+
<field name="res_model">budget.budget</field>
5+
<field name="view_mode">kanban,form</field>
6+
<field name="help" type="html">
7+
<p class="o_view_nocontent_smiling_face">
8+
No records available.
9+
</p>
10+
<p>
11+
Please check your filters or create new records.
12+
</p>
13+
</field>
14+
</record>
15+
16+
<record id="action_budget_management_budget_line" model="ir.actions.act_window">
17+
<field name="name">Budgets Lines</field>
18+
<field name="res_model">budget.management.budget.lines</field>
19+
<field name="view_mode">list</field>
20+
<field name="view_id" ref="budget_management.view_budget_management_budget_line_tree" />
21+
<field name="context">{'default_budget_id': active_id}</field>
22+
<field name="domain">[('budget_id', '=', context.get('default_budget_id'))]</field>
23+
</record>
24+
</odoo>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<odoo>
2+
<record id="view_budget_management_budget_line_tree" model="ir.ui.view">
3+
<field name="name">budget.line.tree</field>
4+
<field name="model">budget.management.budget.lines</field>
5+
<field name="arch" type="xml">
6+
<list string="Budget Lines"
7+
default_order="id desc"
8+
sample="1"
9+
editable="bottom"
10+
>
11+
<field string="Budget" name="name" />
12+
<field string="Analytic Account" name="analytic_account_id" />
13+
<field string="Budget Amount" name="budget_amount" />
14+
<field string="Archived Amount" name="achieved_amount" />
15+
</list>
16+
</field>
17+
</record>
18+
</odoo>
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
<odoo>
2+
<record id="view_budget_management_kanban" model="ir.ui.view">
3+
<field name="name">budget.budget.kanban</field>
4+
<field name="model">budget.budget</field>
5+
<field name="arch" type="xml">
6+
<kanban sample="1"
7+
can_open="0"
8+
type="action"
9+
action="%(action_budget_management_budget_line)d"
10+
on_create="budget_management.open_create_multiple_budget"
11+
>
12+
<templates>
13+
<t t-name="menu">
14+
<div class="container">
15+
<div class="row">
16+
<div name="card_menu_view">
17+
<div role="menuitem" aria-haspopup="true">
18+
<a class="dropdown-item" role="menuitem"
19+
name="action_budget_management_menu_budget" type="open">
20+
Configuration</a>
21+
</div>
22+
</div>
23+
</div>
24+
</div>
25+
</t>
26+
<t t-name="card">
27+
<div
28+
style="display:flex;justify-content:space-between;flex-direction:column">
29+
<div style="display:flex;">
30+
<field name="is_favorite" widget="project_is_favorite" nolabel="1" />
31+
<h3>
32+
<field name="name" />
33+
</h3>
34+
</div>
35+
<div style="display:flex;">
36+
<div t-if="record.date_end.raw_value or record.date_start.raw_value"
37+
class="text-muted">
38+
<span class="fa fa-clock-o me-2" title="Dates"></span>
39+
<field name="date_start" />
40+
<i
41+
t-if="record.date_end.raw_value and record.date_start.raw_value"
42+
class="fa fa-long-arrow-right mx-2 oe_read_only"
43+
aria-label="Arrow icon" title="Arrow" />
44+
<field name="date_end" />
45+
</div>
46+
</div>
47+
</div>
48+
<footer class="mt-auto pt-0 ms-1">
49+
<div class="d-flex align-items-center">
50+
51+
</div>
52+
<div class="d-flex ms-auto align-items-center">
53+
<field name="responsible" widget="many2one_avatar_user"
54+
domain="[('share', '=', False)]" class="me-1" />
55+
</div>
56+
</footer>
57+
</t>
58+
</templates>
59+
</kanban>
60+
</field>
61+
</record>
62+
63+
64+
<record id="view_estate_property_form" model="ir.ui.view">
65+
<field name="name">budget.budget.form</field>
66+
<field name="model">budget.budget</field>
67+
<field name="arch" type="xml">
68+
<form string="Test">
69+
<header>
70+
<button name="onclick_reset_to_draft" type="object" string="Reset to Draft"
71+
invisible="state in ['draft']"
72+
/>
73+
<button name="onclick_revise" type="object" string="Revise"
74+
invisible="state in ['revise','done']"
75+
/>
76+
<button name="onclick_done" type="object" string="Done"
77+
invisible="state in ['done']"
78+
/>
79+
<field name="state" widget="statusbar"
80+
statusbar_visible="draft,confirmed,revised,done" />
81+
</header>
82+
<sheet>
83+
<h1>
84+
<field name="name" />
85+
</h1>
86+
<field name="active" invisible="True" />
87+
<group>
88+
<group>
89+
<field name="responsible" />
90+
</group>
91+
<group>
92+
<field name="date_start" string="Period" widget="daterange"
93+
options="{'end_date_field': 'date_end', 'always_range': '1'}"
94+
optional="hide" />
95+
</group>
96+
</group>
97+
<group>
98+
<group>
99+
<field name="company_id" />
100+
</group>
101+
<group>
102+
<field name="on_over_budget" />
103+
</group>
104+
</group>
105+
<group>
106+
<group>
107+
<field name="revision_id" />
108+
</group>
109+
</group>
110+
<notebook>
111+
<page name="Budget Lines">
112+
<field name="budget_line_ids">
113+
<list>
114+
<field name="name" string="Analytic Account" />
115+
<field name="budget_amount" string="Budget Amount" />
116+
<field name="achieved_amount" string="Archived Amount" />
117+
<field name="achieved_percentage" string="Archived (%)"
118+
widget="progressbar" options="{'max_value': 100}" />
119+
</list>
120+
</field>
121+
</page>
122+
</notebook>
123+
</sheet>
124+
<chatter />
125+
</form>
126+
</field>
127+
</record>
128+
129+
</odoo>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<odoo>
2+
<!-- Define the Root Menu -->
3+
<menuitem
4+
id="budget_management_menu"
5+
name="Budget"
6+
/>
7+
8+
<menuitem
9+
id="budget_management_menu_budget"
10+
name="Budgets"
11+
parent="budget_management_menu"
12+
action="action_budget_management_menu_budget"
13+
/>
14+
</odoo>

0 commit comments

Comments
 (0)