Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions budget_control/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"data": [
"data/budget_data.xml",
"data/sequence_data.xml",
"security/analytic_security.xml",
"security/budget_control_security_groups.xml",
"security/budget_control_rules.xml",
"security/ir.model.access.csv",
Expand Down
28 changes: 28 additions & 0 deletions budget_control/models/analytic_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ class AccountAnalyticAccount(models.Model):
tracking=True,
help="Budget commit date must conform with this date",
)
budget_company_ids = fields.Many2many(
comodel_name="res.company",
compute="_compute_budget_company",
store=True,
readonly=False,
string="Allowed Budget Companies",
help="Companies that this analytic account is allowed to use",
)
auto_adjust_date_commit = fields.Boolean(
string="Auto Adjust Commit Date",
default=True,
Expand Down Expand Up @@ -79,6 +87,26 @@ class AccountAnalyticAccount(models.Model):
help="Initial Balance from carry forward commitment",
)

@api.depends("company_id")
def _compute_budget_company(self):
for rec in self:
rec.budget_company_ids = rec.company_id

@api.constrains("company_id", "budget_company_ids")
def _check_budget_company(self):
"""
If analytic account is in company,
then it must be in Allowed Budget Companies only
"""
for rec in self:
if not rec.company_id:
continue

if rec.company_id and rec.company_id != rec.budget_company_ids:
raise UserError(
_("Analytic Account Company must be in Allowed Budget Companies")
)

@api.depends("name", "budget_period_id")
def _compute_name_with_budget_period(self):
for rec in self:
Expand Down
2 changes: 1 addition & 1 deletion budget_control/models/base_budget_move.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ def _update_budget_commitment(self, budget_vals, reverse=False):
"amount_currency": budget_vals["amount_currency"],
"debit": not reverse and amount or 0,
"credit": reverse and amount or 0,
"company_id": company.id,
"company_id": self[self._doc_rel].company_id.id, # Document company
}
if sum([res["debit"], res["credit"]]) < 0:
res["debit"], res["credit"] = abs(res["credit"]), abs(res["debit"])
Expand Down
21 changes: 13 additions & 8 deletions budget_control/models/budget_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,23 +86,28 @@ class BudgetControl(models.Model):
help="If checked, the newly created budget control sheet will has "
"initial budget equal to current budget commitment of its year.",
)
company_id = fields.Many2one(
company_ids = fields.Many2many(
comodel_name="res.company",
string="Company",
default=lambda self: self.env.company,
required=True,
readonly=True,
states={"draft": [("readonly", False)]},
related="analytic_account_id.budget_company_ids",
relation="budget_control_company_rel",
column1="budget_control_id",
column2="company_id",
store=True,
string="Companies",
tracking=True,
)
currency_id = fields.Many2one(
comodel_name="res.currency", related="company_id.currency_id"
comodel_name="res.currency",
required=True,
tracking=True,
readonly=True,
)
allocated_amount = fields.Monetary(
string="Allocated",
help="Initial total amount for plan",
tracking=True,
readonly=True,
states={"draft": [("readonly", False)]},
help="Initial total amount for plan",
)
released_amount = fields.Monetary(
string="Released",
Expand Down
52 changes: 48 additions & 4 deletions budget_control/report/budget_monitor_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class BudgetMonitorReport(models.Model):
],
)
fwd_commit = fields.Boolean()
companies = fields.Char()
active = fields.Boolean()

@property
Expand Down Expand Up @@ -109,6 +110,7 @@ def _get_select_amount_types(self):
a.source_document as source_document,
null::char as budget_state,
a.fwd_commit,
c.name::text AS companies,
1::boolean as active
"""
% (amount_type[:2], res_model, res_field, amount_type)
Expand All @@ -127,6 +129,7 @@ def _get_from_amount_types(self):
] = """
from {} a
left outer join {} b on a.{} = b.id
left outer join res_company c on b.company_id = c.id
""".format(
budget_table,
doc_table,
Expand All @@ -151,15 +154,46 @@ def _select_budget(self):
null::char as source_document,
b.state as budget_state,
0::boolean as fwd_commit,
string_agg(d.name::text, ', ') AS companies,
a.active as active
"""
}

def _from_budget(self):
return """
from budget_control_line a
join budget_control b on a.budget_control_id = b.id
and b.active = true
join budget_control b
on a.budget_control_id = b.id
left join budget_control_company_rel c
on b.id = c.budget_control_id
left join res_company d on d.id = c.company_id
"""

def _where_budget(self):
visible_company = self.env.context.get("allowed_company_ids")
if not visible_company:
return "where b.active = true"

if len(visible_company) > 1:
companies = tuple(visible_company)
else:
companies = "({})".format(tuple(visible_company)[0])
return "where b.active = true and (c.company_id in {} or c.company_id is null)".format(
companies
)

def _groupby_budget(self):
return """
group by
a.id,
a.kpi_id,
a.analytic_account_id,
b.analytic_group,
a.date_to,
a.amount,
b.name,
b.state,
a.active
"""

def _select_statement(self, amount_type):
Expand All @@ -169,7 +203,15 @@ def _from_statement(self, amount_type):
return self._get_from_amount_types()[amount_type]

def _where_actual(self):
return ""
visible_company = self.env.context.get("allowed_company_ids")
if not visible_company:
return ""

if len(visible_company) > 1:
companies = tuple(visible_company)
else:
companies = "({})".format(tuple(visible_company)[0])
return "where a.company_id in {}".format(companies)

def _get_sql(self):
select_budget_query = self._select_budget()
Expand All @@ -182,9 +224,11 @@ def _get_sql(self):
select_actual = ", ".join(
select_actual_query[x] for x in key_select_actual_list
)
return "(select {} {}) union (select {} {} {})".format(
return "(select {} {} {} {}) union (select {} {} {})".format(
select_budget,
self._from_budget(),
self._where_budget(),
self._groupby_budget(),
select_actual,
self._from_statement("80_actual"),
self._where_actual(),
Expand Down
6 changes: 6 additions & 0 deletions budget_control/report/budget_monitor_report_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,12 @@
name="group_by_date"
context="{'group_by':'date'}"
/>
<separator orientation="company_groupby" />
<filter
string="Company"
name="group_by_company"
context="{'group_by':'companies'}"
/>
</group>
</search>
</field>
Expand Down
9 changes: 9 additions & 0 deletions budget_control/security/analytic_security.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<function model="ir.rule" name="write">
<value eval="[ref('analytic.analytic_comp_rule')]" />
<value
eval="{'domain_force': &quot;['|', ('budget_company_ids', 'in', company_ids), ('budget_company_ids', '=', False)]&quot;}"
/>
</function>
</odoo>
12 changes: 12 additions & 0 deletions budget_control/security/budget_control_rules.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,16 @@
<field eval="1" name="perm_read" />
<field eval="1" name="perm_create" />
</record>
<record id="rule_budget_control_budget_multi_company" model="ir.rule">
<field name="name">Budget Control multi-company</field>
<field name="model_id" ref="budget_control.model_budget_control" />
<field eval="True" name="global" />
<field name="domain_force">
[
'|',
('company_ids', '=', False),
('company_ids', 'in', company_ids)
]
</field>
</record>
</odoo>
13 changes: 13 additions & 0 deletions budget_control/views/analytic_account_views.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@
<field name="bm_date_to" />
<field name="budget_control_ids" widget="many2many_tags" />
</field>
<xpath expr="//field[@name='company_id']" position="after">
<field
name="budget_company_ids"
widget="many2many_tags"
groups="base.group_multi_company"
/>
</xpath>
<xpath expr="//group[@name='main']/group[2]" position="inside">
<field name="auto_adjust_date_commit" />
<label for="initial_available" />
Expand Down Expand Up @@ -89,6 +96,12 @@
groups="base.group_multi_company"
optional="show"
/>
<field
name="budget_company_ids"
widget="many2many_tags"
groups="base.group_multi_company"
optional="show"
/>
<field
name="currency_id"
groups="base.group_multi_currency"
Expand Down
16 changes: 15 additions & 1 deletion budget_control/views/budget_control_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@
<field name="amount_actual" optional="hide" />
<field name="amount_consumed" optional="show" />
<field name="amount_balance" optional="show" />
<field
name="company_ids"
optional="show"
groups="base.group_multi_company"
widget="many2many_tags"
/>
<field
name="state"
widget='badge'
Expand Down Expand Up @@ -95,6 +101,13 @@
string="Analytic Group"
context="{'group_by': 'analytic_group'}"
/>
<separator />
<filter
string="Company"
name="groupby_company"
context="{'group_by': 'company_ids'}"
groups="base.group_multi_company"
/>
</group>
</search>
</field>
Expand Down Expand Up @@ -212,8 +225,9 @@
<field name="plan_date_range_type_id" />
<field name="template_id" />
<field
name="company_id"
name="company_ids"
groups="base.group_multi_company"
widget="many2many_tags"
/>
<field
name="currency_id"
Expand Down
18 changes: 17 additions & 1 deletion budget_control/wizards/generate_budget_control.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Copyright 2020 Ecosoft Co., Ltd. (http://ecosoft.co.th)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models

from odoo import _, api, fields, models
from odoo.exceptions import UserError


class GenerateBudgetControl(models.TransientModel):
Expand Down Expand Up @@ -47,6 +49,12 @@ class GenerateBudgetControl(models.TransientModel):
"with Intial KPIs",
)
use_all_kpis = fields.Boolean(string="Use All KPIs")
budget_currency_id = fields.Many2one(
comodel_name="res.currency",
default=lambda self: self.env.company.currency_id,
readonly=True,
required=True,
)
template_id = fields.Many2one(
comodel_name="budget.template",
required=True,
Expand Down Expand Up @@ -78,6 +86,12 @@ class GenerateBudgetControl(models.TransientModel):

@api.model
def default_get(self, default_fields):
all_companies = self.env["res.company"].sudo().search([])
if len(all_companies.currency_id) > 1:
raise UserError(
_("All companies must have the same currency for budgeting.")
)

values = super().default_get(default_fields)
period_id = self.env.context.get("active_id")
period = self.env["budget.period"].browse(period_id)
Expand Down Expand Up @@ -137,6 +151,7 @@ def _prepare_value_duplicate(self, vals):
use_all_kpis = self.use_all_kpis
budget_period_id = self.budget_period_id.id
template_lines = self.template_line_ids.ids
currency_id = self.budget_currency_id.id
return list(
map(
lambda l: {
Expand All @@ -146,6 +161,7 @@ def _prepare_value_duplicate(self, vals):
or l["analytic_account_id"].name
),
"analytic_account_id": l["analytic_account_id"].id,
"currency_id": currency_id,
"plan_date_range_type_id": plan_date_range_id,
"use_all_kpis": use_all_kpis,
"template_line_ids": template_lines,
Expand Down
1 change: 1 addition & 0 deletions budget_control/wizards/generate_budget_control_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<group string="Options">
<field name="init_kpis" />
<field name="init_budget_commit" />
<field name="budget_currency_id" />
</group>
</group>
<notebook>
Expand Down
10 changes: 9 additions & 1 deletion budget_control_advance_clearing/report/budget_monitor_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,15 @@ def _get_consumed_sources(self):
]

def _where_advance_clearing(self):
return ""
visible_company = self.env.context.get("allowed_company_ids")
if not visible_company:
return ""

if len(visible_company) > 1:
companies = tuple(visible_company)
else:
companies = "({})".format(tuple(visible_company)[0])
return "where a.company_id in {}".format(companies)

def _get_sql(self):
select_av_query = self._select_statement("40_av_commit")
Expand Down
10 changes: 9 additions & 1 deletion budget_control_contract/report/budget_monitor_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,15 @@ def _get_consumed_sources(self):
]

def _where_contract(self):
return ""
visible_company = self.env.context.get("allowed_company_ids")
if not visible_company:
return ""

if len(visible_company) > 1:
companies = tuple(visible_company)
else:
companies = "({})".format(tuple(visible_company)[0])
return "where a.company_id in {}".format(companies)

def _get_sql(self):
select_ct_query = self._select_statement("60_ct_commit")
Expand Down
Loading