From 9ddd1b1b02415c3ca7476d62dc69b8649507f0da Mon Sep 17 00:00:00 2001 From: Saran440 Date: Fri, 20 Dec 2024 12:04:34 +0700 Subject: [PATCH 1/9] [IMP] budget_control: budget commit multi company --- budget_control/models/base_budget_move.py | 2 +- budget_control/models/budget_control.py | 10 ++++++---- .../report/budget_monitor_report.py | 5 +++++ .../report/budget_monitor_report_view.xml | 6 ++++++ .../security/budget_control_rules.xml | 8 ++++++++ budget_control/views/budget_control_view.xml | 12 ++++++++++++ .../wizards/generate_budget_control.py | 19 ++++++++++++++++++- .../wizards/generate_budget_control_view.xml | 1 + 8 files changed, 57 insertions(+), 6 deletions(-) diff --git a/budget_control/models/base_budget_move.py b/budget_control/models/base_budget_move.py index 6774762f..d5ccc190 100644 --- a/budget_control/models/base_budget_move.py +++ b/budget_control/models/base_budget_move.py @@ -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"]) diff --git a/budget_control/models/budget_control.py b/budget_control/models/budget_control.py index b0162139..15b2a0bc 100644 --- a/budget_control/models/budget_control.py +++ b/budget_control/models/budget_control.py @@ -89,20 +89,22 @@ class BudgetControl(models.Model): company_id = fields.Many2one( comodel_name="res.company", string="Company", - default=lambda self: self.env.company, - required=True, + tracking=True, readonly=True, states={"draft": [("readonly", False)]}, ) 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", diff --git a/budget_control/report/budget_monitor_report.py b/budget_control/report/budget_monitor_report.py index b6dd4230..5f439b01 100644 --- a/budget_control/report/budget_monitor_report.py +++ b/budget_control/report/budget_monitor_report.py @@ -53,6 +53,9 @@ class BudgetMonitorReport(models.Model): ], ) fwd_commit = fields.Boolean() + company_id = fields.Many2one( + comodel_name="res.company", + ) active = fields.Boolean() @property @@ -109,6 +112,7 @@ def _get_select_amount_types(self): a.source_document as source_document, null::char as budget_state, a.fwd_commit, + b.company_id as company_id, 1::boolean as active """ % (amount_type[:1], res_model, res_field, amount_type) @@ -151,6 +155,7 @@ def _select_budget(self): null::char as source_document, b.state as budget_state, 0::boolean as fwd_commit, + b.company_id as company_id, a.active as active """ } diff --git a/budget_control/report/budget_monitor_report_view.xml b/budget_control/report/budget_monitor_report_view.xml index 8b79481b..7f02c048 100644 --- a/budget_control/report/budget_monitor_report_view.xml +++ b/budget_control/report/budget_monitor_report_view.xml @@ -106,6 +106,12 @@ name="group_by_date" context="{'group_by':'date'}" /> + + diff --git a/budget_control/security/budget_control_rules.xml b/budget_control/security/budget_control_rules.xml index 746fddea..e4da0a54 100644 --- a/budget_control/security/budget_control_rules.xml +++ b/budget_control/security/budget_control_rules.xml @@ -28,4 +28,12 @@ + + Budget Control multi-company + + + + ['|',('company_id','=',False),('company_id','in',company_ids)] + + diff --git a/budget_control/views/budget_control_view.xml b/budget_control/views/budget_control_view.xml index 6b0ba836..4be46cb9 100644 --- a/budget_control/views/budget_control_view.xml +++ b/budget_control/views/budget_control_view.xml @@ -45,6 +45,11 @@ + + + diff --git a/budget_control/wizards/generate_budget_control.py b/budget_control/wizards/generate_budget_control.py index 14202489..e79b8030 100644 --- a/budget_control/wizards/generate_budget_control.py +++ b/budget_control/wizards/generate_budget_control.py @@ -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): @@ -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, @@ -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) @@ -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: { @@ -146,6 +161,8 @@ def _prepare_value_duplicate(self, vals): or l["analytic_account_id"].name ), "analytic_account_id": l["analytic_account_id"].id, + "company_id": l["analytic_account_id"].company_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, diff --git a/budget_control/wizards/generate_budget_control_view.xml b/budget_control/wizards/generate_budget_control_view.xml index 014b0679..c5ab8d09 100644 --- a/budget_control/wizards/generate_budget_control_view.xml +++ b/budget_control/wizards/generate_budget_control_view.xml @@ -17,6 +17,7 @@ + From 58cbd4ec307ce4462844dc97e6d8a79794f6b256 Mon Sep 17 00:00:00 2001 From: Saran440 Date: Tue, 24 Dec 2024 18:09:54 +0700 Subject: [PATCH 2/9] [IMP] multi company report --- budget_control/__manifest__.py | 1 + budget_control/models/analytic_account.py | 28 ++++++++++++++ budget_control/models/budget_control.py | 11 ++++-- .../report/budget_monitor_report.py | 37 +++++++++++++++---- .../report/budget_monitor_report_view.xml | 2 +- budget_control/security/analytic_security.xml | 9 +++++ .../security/budget_control_rules.xml | 8 +++- .../views/analytic_account_views.xml | 13 +++++++ budget_control/views/budget_control_view.xml | 8 ++-- .../wizards/generate_budget_control.py | 1 - 10 files changed, 99 insertions(+), 19 deletions(-) create mode 100644 budget_control/security/analytic_security.xml diff --git a/budget_control/__manifest__.py b/budget_control/__manifest__.py index 6728d923..0061906f 100644 --- a/budget_control/__manifest__.py +++ b/budget_control/__manifest__.py @@ -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", diff --git a/budget_control/models/analytic_account.py b/budget_control/models/analytic_account.py index ba5259e4..b6c9a4c6 100644 --- a/budget_control/models/analytic_account.py +++ b/budget_control/models/analytic_account.py @@ -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, @@ -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: diff --git a/budget_control/models/budget_control.py b/budget_control/models/budget_control.py index 15b2a0bc..25205751 100644 --- a/budget_control/models/budget_control.py +++ b/budget_control/models/budget_control.py @@ -86,12 +86,15 @@ 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", + 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, - readonly=True, - states={"draft": [("readonly", False)]}, ) currency_id = fields.Many2one( comodel_name="res.currency", diff --git a/budget_control/report/budget_monitor_report.py b/budget_control/report/budget_monitor_report.py index 5f439b01..88756118 100644 --- a/budget_control/report/budget_monitor_report.py +++ b/budget_control/report/budget_monitor_report.py @@ -53,9 +53,7 @@ class BudgetMonitorReport(models.Model): ], ) fwd_commit = fields.Boolean() - company_id = fields.Many2one( - comodel_name="res.company", - ) + companies = fields.Char() active = fields.Boolean() @property @@ -112,7 +110,7 @@ def _get_select_amount_types(self): a.source_document as source_document, null::char as budget_state, a.fwd_commit, - b.company_id as company_id, + c.name::text AS companies, 1::boolean as active """ % (amount_type[:1], res_model, res_field, amount_type) @@ -131,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, @@ -155,7 +154,7 @@ def _select_budget(self): null::char as source_document, b.state as budget_state, 0::boolean as fwd_commit, - b.company_id as company_id, + string_agg(d.name::text, ', ') AS companies, a.active as active """ } @@ -163,8 +162,28 @@ def _select_budget(self): 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): + return "where b.active = true" + + 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): @@ -187,9 +206,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("8_actual"), self._where_actual(), diff --git a/budget_control/report/budget_monitor_report_view.xml b/budget_control/report/budget_monitor_report_view.xml index 7f02c048..372d9214 100644 --- a/budget_control/report/budget_monitor_report_view.xml +++ b/budget_control/report/budget_monitor_report_view.xml @@ -110,7 +110,7 @@ diff --git a/budget_control/security/analytic_security.xml b/budget_control/security/analytic_security.xml new file mode 100644 index 00000000..0d9b9aac --- /dev/null +++ b/budget_control/security/analytic_security.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/budget_control/security/budget_control_rules.xml b/budget_control/security/budget_control_rules.xml index e4da0a54..909fb3b6 100644 --- a/budget_control/security/budget_control_rules.xml +++ b/budget_control/security/budget_control_rules.xml @@ -33,7 +33,11 @@ - ['|',('company_id','=',False),('company_id','in',company_ids)] - + [ + '|', + ('company_ids', '=', False), + ('company_ids', 'in', company_ids) + ] + diff --git a/budget_control/views/analytic_account_views.xml b/budget_control/views/analytic_account_views.xml index 3ffe6ad4..ea7540b4 100644 --- a/budget_control/views/analytic_account_views.xml +++ b/budget_control/views/analytic_account_views.xml @@ -49,6 +49,13 @@ + + +