-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[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.
- Loading branch information
Showing
14 changed files
with
405 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from . import models | ||
from . import wizards |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"name": "Budget Management", | ||
"version": "1.0", | ||
"depends": ["base", "account"], | ||
"author": "djip-odoo", | ||
"description": """ | ||
Part of technical training | ||
Creating Budget Management module as review task | ||
""", | ||
"data": [ | ||
"security/ir.model.access.csv", | ||
"views/budget_line_views.xml", | ||
"wizards/actions_wizard.xml", | ||
"views/actions_menu_and_button.xml", | ||
"views/menu_views.xml", | ||
"views/budget_views.xml", | ||
"wizards/wizard_add_budgets_view.xml", | ||
], | ||
"application": True, | ||
"installable": True, | ||
"auto_install": False, | ||
"license": "LGPL-3", | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from . import budget | ||
from . import budget_line |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
from odoo import models, fields, api | ||
from datetime import date | ||
|
||
|
||
class Budget(models.Model): | ||
_name = "budget.budget" | ||
_inherit = ["mail.thread", "mail.activity.mixin"] | ||
|
||
name = fields.Char(compute="_compute_budget_name", store=True, readonly=True) | ||
active = fields.Boolean(default=True) | ||
is_favorite = fields.Boolean(default=False) | ||
state = fields.Selection( | ||
selection=[ | ||
("draft", "Draft"), | ||
("confirmed", "Confirmed"), | ||
("revised", "Revised"), | ||
("done", "Done"), | ||
], | ||
required=True, | ||
default="draft", | ||
tracking=True, | ||
) | ||
on_over_budget = fields.Selection( | ||
selection=[("warning", "Warning"), ("restriction", "Restriction")], | ||
tracking=True, | ||
) | ||
responsible = fields.Many2one( | ||
comodel_name="res.users", # Assuming you want a link to Odoo users | ||
string="Responsible", | ||
tracking=True, | ||
) | ||
revision_id = fields.Many2one( | ||
comodel_name="res.users", # Assuming you want a link to Odoo users | ||
tracking=True, | ||
readonly=True, | ||
) | ||
date_start = fields.Date(string="Start Date", required=True) | ||
date_end = fields.Date(string="Expiration Date", required=True, index=True) | ||
company_id = fields.Many2one( | ||
"res.company", | ||
string="Company", | ||
default=lambda self: self.env.company, | ||
) | ||
|
||
budget_line_ids = fields.One2many( | ||
comodel_name="budget.management.budget.lines", inverse_name="budget_id" | ||
) | ||
|
||
@api.depends("date_start", "date_end") | ||
def _compute_budget_name(self): | ||
for record in self: | ||
if record.date_start and record.date_end: | ||
start_date = record.date_start.strftime("%Y-%m") | ||
end_date = record.date_end.strftime("%Y-%m") | ||
record.name = f"Budget {start_date} to {end_date}" | ||
else: | ||
record.name = "Unknown Budget" | ||
|
||
def onclick_reset_to_draft(self): | ||
for record in self: | ||
if record.state != "draft": | ||
record.state = "draft" | ||
|
||
def onclick_revise(self): | ||
for record in self: | ||
if record.state in ["confirmed", "draft"]: | ||
record.revision_id = lambda self: self.env.user | ||
record.state = "revised" | ||
|
||
def onclick_done(self): | ||
for record in self: | ||
if record.state in ["confirmed", "revised"]: | ||
record.state = "done" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
from odoo import models, fields, api | ||
|
||
class BudgetLine(models.Model): | ||
_name = "budget.management.budget.lines" | ||
|
||
name = fields.Char() | ||
budget_id = fields.Many2one(comodel_name="budget.budget", string="Budget") | ||
budget_amount = fields.Float(default=0.0) | ||
achieved_amount = fields.Float(default=0.0) | ||
achieved_percentage = fields.Float( | ||
default=0.0, | ||
compute="_compute_achieved_percentage", | ||
store=True | ||
) | ||
analytic_account_id = fields.Many2one('account.analytic.account', string='Analytic Account') | ||
# analytic_line_ids = fields.One2many('account.analytic.line', string='Analytic Account') | ||
|
||
@api.depends("budget_amount", "achieved_amount") | ||
def _compute_achieved_percentage(self): | ||
for record in self: | ||
if record.budget_amount: | ||
record.achieved_percentage = (record.achieved_amount / record.budget_amount) * 100 | ||
else: | ||
record.achieved_percentage = 0.0 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink | ||
budget_management.access_budget_budget,access_budget_budget,budget_management.model_budget_budget,base.group_user,1,1,1,1 | ||
budget_management.access_add_budget_wizard,access_add_budget_wizard,budget_management.model_add_budget_wizard,base.group_user,1,1,1,0 | ||
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<odoo> | ||
<record id="action_budget_management_menu_budget" model="ir.actions.act_window"> | ||
<field name="name">Budgets</field> | ||
<field name="res_model">budget.budget</field> | ||
<field name="view_mode">kanban,form</field> | ||
<field name="help" type="html"> | ||
<p class="o_view_nocontent_smiling_face"> | ||
No records available. | ||
</p> | ||
<p> | ||
Please check your filters or create new records. | ||
</p> | ||
</field> | ||
</record> | ||
|
||
<record id="action_budget_management_budget_line" model="ir.actions.act_window"> | ||
<field name="name">Budgets Lines</field> | ||
<field name="res_model">budget.management.budget.lines</field> | ||
<field name="view_mode">list</field> | ||
<field name="view_id" ref="budget_management.view_budget_management_budget_line_tree" /> | ||
<field name="context">{'default_budget_id': active_id}</field> | ||
<field name="domain">[('budget_id', '=', context.get('default_budget_id'))]</field> | ||
</record> | ||
</odoo> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<odoo> | ||
<record id="view_budget_management_budget_line_tree" model="ir.ui.view"> | ||
<field name="name">budget.line.tree</field> | ||
<field name="model">budget.management.budget.lines</field> | ||
<field name="arch" type="xml"> | ||
<list string="Budget Lines" | ||
default_order="id desc" | ||
sample="1" | ||
editable="bottom" | ||
> | ||
<field string="Budget" name="name" /> | ||
<field string="Analytic Account" name="analytic_account_id" /> | ||
<field string="Budget Amount" name="budget_amount" /> | ||
<field string="Archived Amount" name="achieved_amount" /> | ||
</list> | ||
</field> | ||
</record> | ||
</odoo> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
<odoo> | ||
<record id="view_budget_management_kanban" model="ir.ui.view"> | ||
<field name="name">budget.budget.kanban</field> | ||
<field name="model">budget.budget</field> | ||
<field name="arch" type="xml"> | ||
<kanban sample="1" | ||
can_open="0" | ||
type="action" | ||
action="%(action_budget_management_budget_line)d" | ||
on_create="budget_management.open_create_multiple_budget" | ||
> | ||
<templates> | ||
<t t-name="menu"> | ||
<div class="container"> | ||
<div class="row"> | ||
<div name="card_menu_view"> | ||
<div role="menuitem" aria-haspopup="true"> | ||
<a class="dropdown-item" role="menuitem" | ||
name="action_budget_management_menu_budget" type="open"> | ||
Configuration</a> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</t> | ||
<t t-name="card"> | ||
<div | ||
style="display:flex;justify-content:space-between;flex-direction:column"> | ||
<div style="display:flex;"> | ||
<field name="is_favorite" widget="project_is_favorite" nolabel="1" /> | ||
<h3> | ||
<field name="name" /> | ||
</h3> | ||
</div> | ||
<div style="display:flex;"> | ||
<div t-if="record.date_end.raw_value or record.date_start.raw_value" | ||
class="text-muted"> | ||
<span class="fa fa-clock-o me-2" title="Dates"></span> | ||
<field name="date_start" /> | ||
<i | ||
t-if="record.date_end.raw_value and record.date_start.raw_value" | ||
class="fa fa-long-arrow-right mx-2 oe_read_only" | ||
aria-label="Arrow icon" title="Arrow" /> | ||
<field name="date_end" /> | ||
</div> | ||
</div> | ||
</div> | ||
<footer class="mt-auto pt-0 ms-1"> | ||
<div class="d-flex align-items-center"> | ||
|
||
</div> | ||
<div class="d-flex ms-auto align-items-center"> | ||
<field name="responsible" widget="many2one_avatar_user" | ||
domain="[('share', '=', False)]" class="me-1" /> | ||
</div> | ||
</footer> | ||
</t> | ||
</templates> | ||
</kanban> | ||
</field> | ||
</record> | ||
|
||
|
||
<record id="view_estate_property_form" model="ir.ui.view"> | ||
<field name="name">budget.budget.form</field> | ||
<field name="model">budget.budget</field> | ||
<field name="arch" type="xml"> | ||
<form string="Test"> | ||
<header> | ||
<button name="onclick_reset_to_draft" type="object" string="Reset to Draft" | ||
invisible="state in ['draft']" | ||
/> | ||
<button name="onclick_revise" type="object" string="Revise" | ||
invisible="state in ['revise','done']" | ||
/> | ||
<button name="onclick_done" type="object" string="Done" | ||
invisible="state in ['done']" | ||
/> | ||
<field name="state" widget="statusbar" | ||
statusbar_visible="draft,confirmed,revised,done" /> | ||
</header> | ||
<sheet> | ||
<h1> | ||
<field name="name" /> | ||
</h1> | ||
<field name="active" invisible="True" /> | ||
<group> | ||
<group> | ||
<field name="responsible" /> | ||
</group> | ||
<group> | ||
<field name="date_start" string="Period" widget="daterange" | ||
options="{'end_date_field': 'date_end', 'always_range': '1'}" | ||
optional="hide" /> | ||
</group> | ||
</group> | ||
<group> | ||
<group> | ||
<field name="company_id" /> | ||
</group> | ||
<group> | ||
<field name="on_over_budget" /> | ||
</group> | ||
</group> | ||
<group> | ||
<group> | ||
<field name="revision_id" /> | ||
</group> | ||
</group> | ||
<notebook> | ||
<page name="Budget Lines"> | ||
<field name="budget_line_ids"> | ||
<list> | ||
<field name="name" string="Analytic Account" /> | ||
<field name="budget_amount" string="Budget Amount" /> | ||
<field name="achieved_amount" string="Archived Amount" /> | ||
<field name="achieved_percentage" string="Archived (%)" | ||
widget="progressbar" options="{'max_value': 100}" /> | ||
</list> | ||
</field> | ||
</page> | ||
</notebook> | ||
</sheet> | ||
<chatter /> | ||
</form> | ||
</field> | ||
</record> | ||
|
||
</odoo> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<odoo> | ||
<!-- Define the Root Menu --> | ||
<menuitem | ||
id="budget_management_menu" | ||
name="Budget" | ||
/> | ||
|
||
<menuitem | ||
id="budget_management_menu_budget" | ||
name="Budgets" | ||
parent="budget_management_menu" | ||
action="action_budget_management_menu_budget" | ||
/> | ||
</odoo> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import add_budget_wizard |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<odoo> | ||
|
||
</odoo> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
from odoo import models, fields | ||
from datetime import timedelta | ||
from dateutil.relativedelta import relativedelta | ||
|
||
|
||
class AddBudgetWizard(models.TransientModel): | ||
_name = "add.budget.wizard" | ||
|
||
date_start = fields.Date(required=True, string="Start Date") | ||
date_end = fields.Date( | ||
string="Expiration Date", | ||
required=True, | ||
index=True, | ||
) | ||
|
||
periods = fields.Selection( | ||
selection=[("monthly", "Monthly"), ("quarterly", "Quarterly")], | ||
required=True, | ||
default="monthly", | ||
) | ||
|
||
# analytic_account = fields.Many2many(comodel_name="account.analytic.account") | ||
def action_add_budget(self): | ||
"""Creates budget records based on the selected periods.""" | ||
if self.date_start >= self.date_end: | ||
raise ValueError("Start Date must be before Expiration Date.") | ||
|
||
# Calculate the periods and create budgets | ||
current_date = self.date_start | ||
budget_entries = [] | ||
|
||
while current_date <= self.date_end: | ||
next_date = ( | ||
current_date + relativedelta(months=1) | ||
if self.periods == "monthly" | ||
else current_date + relativedelta(months=3) | ||
) | ||
end_date = min(next_date - timedelta(days=1), self.date_end) | ||
|
||
budget_entries.append( | ||
{ | ||
"name": f"Budget {current_date.strftime('%Y-%m')} to {end_date.strftime('%Y-%m')}", | ||
"date_start": current_date, | ||
"date_end": end_date, | ||
} | ||
) | ||
|
||
current_date = next_date | ||
print(budget_entries) | ||
self.env["budget.budget"].create(budget_entries) | ||
|
||
# Return a window close action | ||
return {"type": "ir.actions.act_window_close"} |
Oops, something went wrong.