From 0e6335c5a91b4fcbbee5a337073a71041d7d4ab9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roc=C3=ADo=20Vega?= Date: Tue, 17 Dec 2024 13:02:49 -0300 Subject: [PATCH 1/2] [IMP] new module: account_currency_reports_ux --- account_currency_reports_ux/__init__.py | 4 + account_currency_reports_ux/__manifest__.py | 43 ++++++++++ .../report/__init__.py | 4 + .../report/account_invoice_report.py | 86 +++++++++++++++++++ 4 files changed, 137 insertions(+) create mode 100644 account_currency_reports_ux/__init__.py create mode 100644 account_currency_reports_ux/__manifest__.py create mode 100644 account_currency_reports_ux/report/__init__.py create mode 100644 account_currency_reports_ux/report/account_invoice_report.py diff --git a/account_currency_reports_ux/__init__.py b/account_currency_reports_ux/__init__.py new file mode 100644 index 00000000..abbf32ce --- /dev/null +++ b/account_currency_reports_ux/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import report diff --git a/account_currency_reports_ux/__manifest__.py b/account_currency_reports_ux/__manifest__.py new file mode 100644 index 00000000..23fe6295 --- /dev/null +++ b/account_currency_reports_ux/__manifest__.py @@ -0,0 +1,43 @@ +############################################################################## +# +# Copyright (C) 2024 ADHOC SA (http://www.adhoc.com.ar) +# All Rights Reserved. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## +{ + 'name': 'Account Currency Reports UX', + 'version': "16.0.1.0.0", + 'category': 'Accounting', + 'sequence': 14, + 'summary': 'Restrict the use of certain journals to certain users', + 'author': 'ADHOC SA', + 'website': 'www.adhoc.com.ar', + 'license': 'AGPL-3', + 'images': [ + ], + 'depends': [ + 'account', + ], + 'data': [ + ], + 'demo': [ + ], + 'test': [ + ], + 'installable': True, + 'auto_install': False, + 'application': False, +} diff --git a/account_currency_reports_ux/report/__init__.py b/account_currency_reports_ux/report/__init__.py new file mode 100644 index 00000000..a04d063d --- /dev/null +++ b/account_currency_reports_ux/report/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import account_invoice_report diff --git a/account_currency_reports_ux/report/account_invoice_report.py b/account_currency_reports_ux/report/account_invoice_report.py new file mode 100644 index 00000000..24d25659 --- /dev/null +++ b/account_currency_reports_ux/report/account_invoice_report.py @@ -0,0 +1,86 @@ +from odoo import models, api + +class AccountInvoiceReport(models.Model): + _inherit = "account.invoice.report" + + @api.model + def _select(self): + return ''' + WITH currency_rate AS MATERIALIZED ( + SELECT + r.currency_id, + COALESCE(r.company_id, c.id) as company_id, + 1/r.rate as rate, + r.name AS date_start, + (SELECT name FROM res_currency_rate r2 + WHERE r2.name > r.name AND + r2.currency_id = r.currency_id AND + (r2.company_id is null or r2.company_id = c.id) + ORDER BY r2.name ASC + LIMIT 1) AS date_end + FROM res_currency_rate r + JOIN res_company c ON (r.company_id is null or r.company_id = c.id) + WHERE c.id = %s + ) + SELECT + line.id, + line.move_id, + line.product_id, + line.account_id, + line.journal_id, + line.company_id, + line.company_currency_id, + line.partner_id AS commercial_partner_id, + account.account_type AS user_type, + move.state, + move.move_type, + move.partner_id, + move.invoice_user_id, + move.fiscal_position_id, + move.payment_state, + move.invoice_date, + move.invoice_date_due, + uom_template.id AS product_uom_id, + template.categ_id AS product_categ_id, + line.quantity / NULLIF(COALESCE(uom_line.factor, 1) / COALESCE(uom_template.factor, 1), 0.0) * (CASE WHEN move.move_type IN ('in_invoice','out_refund','in_receipt') THEN -1 ELSE 1 END) + AS quantity, + CASE WHEN line.currency_id <> rc.currency_id THEN -line.balance * currency_table.rate ELSE -line.balance END AS price_subtotal, + line.price_total * (CASE WHEN move.move_type IN ('in_invoice','out_refund','in_receipt') THEN -1 ELSE 1 END) + AS price_total, + CASE WHEN line.currency_id <> rc.currency_id THEN + -COALESCE( + -- Average line price + (line.balance / NULLIF(line.quantity, 0.0)) * (CASE WHEN move.move_type IN ('in_invoice','out_refund','in_receipt') THEN -1 ELSE 1 END) + -- convert to template uom + * (NULLIF(COALESCE(uom_line.factor, 1), 0.0) / NULLIF(COALESCE(uom_template.factor, 1), 0.0)), + 0.0) * currency_table.rate + ELSE -COALESCE( + -- Average line price + (line.balance / NULLIF(line.quantity, 0.0)) * (CASE WHEN move.move_type IN ('in_invoice','out_refund','in_receipt') THEN -1 ELSE 1 END) + -- convert to template uom + * (NULLIF(COALESCE(uom_line.factor, 1), 0.0) / NULLIF(COALESCE(uom_template.factor, 1), 0.0)), + 0.0) END + AS price_average, + COALESCE(partner.country_id, commercial_partner.country_id) AS country_id, + line.currency_id AS currency_id + ''' % self.env.company.id + + @api.model + def _from(self): + return ''' + FROM account_move_line line + LEFT JOIN res_partner partner ON partner.id = line.partner_id + LEFT JOIN product_product product ON product.id = line.product_id + LEFT JOIN account_account account ON account.id = line.account_id + LEFT JOIN product_template template ON template.id = product.product_tmpl_id + LEFT JOIN uom_uom uom_line ON uom_line.id = line.product_uom_id + LEFT JOIN uom_uom uom_template ON uom_template.id = template.uom_id + INNER JOIN account_move move ON move.id = line.move_id + LEFT JOIN res_partner commercial_partner ON commercial_partner.id = move.commercial_partner_id + lEFT JOIN currency_rate currency_table on + (currency_table.company_id = line.company_id and + currency_table.currency_id = line.currency_id and + currency_table.date_start <= COALESCE(line.date, NOW()) and + (currency_table.date_end IS NULL OR currency_table.date_end > COALESCE(line.date, NOW()))) + LEFT JOIN res_company rc on rc.id=line.company_id + ''' From 042354f03bfcd2d938e4a776f1f229f4181c4d59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roc=C3=ADo=20Vega?= Date: Wed, 18 Dec 2024 10:07:55 -0300 Subject: [PATCH 2/2] [FIX] account_currency_report_ux: approach of using monkey_patches --- account_currency_reports_ux/__init__.py | 3 ++- account_currency_reports_ux/__manifest__.py | 2 ++ account_currency_reports_ux/hooks.py | 17 ++++++++++++ ...nt_invoice_report.py => monkey_patches.py} | 27 +++++++++++++------ .../report/__init__.py | 4 --- 5 files changed, 40 insertions(+), 13 deletions(-) create mode 100644 account_currency_reports_ux/hooks.py rename account_currency_reports_ux/{report/account_invoice_report.py => monkey_patches.py} (85%) delete mode 100644 account_currency_reports_ux/report/__init__.py diff --git a/account_currency_reports_ux/__init__.py b/account_currency_reports_ux/__init__.py index abbf32ce..8a3896d1 100644 --- a/account_currency_reports_ux/__init__.py +++ b/account_currency_reports_ux/__init__.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from . import report +from .hooks import uninstall_hook +from .monkey_patches import * diff --git a/account_currency_reports_ux/__manifest__.py b/account_currency_reports_ux/__manifest__.py index 23fe6295..14d7b0f5 100644 --- a/account_currency_reports_ux/__manifest__.py +++ b/account_currency_reports_ux/__manifest__.py @@ -40,4 +40,6 @@ 'installable': True, 'auto_install': False, 'application': False, + 'post_load': 'monkey_patches', + 'uninstall_hook': 'uninstall_hook' } diff --git a/account_currency_reports_ux/hooks.py b/account_currency_reports_ux/hooks.py new file mode 100644 index 00000000..e72478f2 --- /dev/null +++ b/account_currency_reports_ux/hooks.py @@ -0,0 +1,17 @@ +############################################################################## +# For copyright and license notices, see __manifest__.py file in module root +# directory +############################################################################## +from odoo.addons.account.report.account_invoice_report import AccountInvoiceReport + +def _revert_method(cls, name): + """ Revert the original method called ``name`` in the given class. + See :meth:`~._patch_method`. + """ + method = getattr(cls, name) + setattr(cls, name, method.origin) + + +def uninstall_hook(cr, registry): + _revert_method(AccountInvoiceReport, '_select') + _revert_method(AccountInvoiceReport, '_from') diff --git a/account_currency_reports_ux/report/account_invoice_report.py b/account_currency_reports_ux/monkey_patches.py similarity index 85% rename from account_currency_reports_ux/report/account_invoice_report.py rename to account_currency_reports_ux/monkey_patches.py index 24d25659..36bd5aee 100644 --- a/account_currency_reports_ux/report/account_invoice_report.py +++ b/account_currency_reports_ux/monkey_patches.py @@ -1,10 +1,11 @@ -from odoo import models, api +from odoo import api +from odoo.addons.account.report.account_invoice_report import AccountInvoiceReport -class AccountInvoiceReport(models.Model): - _inherit = "account.invoice.report" +def monkey_patches(): + # monkey patch @api.model - def _select(self): + def _select_patch(self): return ''' WITH currency_rate AS MATERIALIZED ( SELECT @@ -66,7 +67,7 @@ def _select(self): ''' % self.env.company.id @api.model - def _from(self): + def _from_patch(self): return ''' FROM account_move_line line LEFT JOIN res_partner partner ON partner.id = line.partner_id @@ -78,9 +79,19 @@ def _from(self): INNER JOIN account_move move ON move.id = line.move_id LEFT JOIN res_partner commercial_partner ON commercial_partner.id = move.commercial_partner_id lEFT JOIN currency_rate currency_table on - (currency_table.company_id = line.company_id and - currency_table.currency_id = line.currency_id and + (currency_table.currency_id = line.currency_id and currency_table.date_start <= COALESCE(line.date, NOW()) and (currency_table.date_end IS NULL OR currency_table.date_end > COALESCE(line.date, NOW()))) - LEFT JOIN res_company rc on rc.id=line.company_id + LEFT JOIN res_company rc on rc.id=currency_table.company_id ''' + + def _patch_method(cls, name, method): + origin = getattr(cls, name) + method.origin = origin + # propagate decorators from origin to method, and apply api decorator + wrapped = api.propagate(origin, method) + wrapped.origin = origin + setattr(cls, name, wrapped) + + _patch_method(AccountInvoiceReport, '_select', _select_patch) + _patch_method(AccountInvoiceReport, '_from', _from_patch) diff --git a/account_currency_reports_ux/report/__init__.py b/account_currency_reports_ux/report/__init__.py deleted file mode 100644 index a04d063d..00000000 --- a/account_currency_reports_ux/report/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from . import account_invoice_report