Skip to content

Commit

Permalink
[IMP] new module: account_currency_reports_ux
Browse files Browse the repository at this point in the history
  • Loading branch information
rov-adhoc committed Feb 3, 2025
1 parent 3eed9e8 commit 9768801
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 0 deletions.
5 changes: 5 additions & 0 deletions account_currency_reports_ux/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from .hooks import uninstall_hook
from .monkey_patches import *
45 changes: 45 additions & 0 deletions account_currency_reports_ux/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
##############################################################################
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name': 'Account Currency Reports UX',
'version': "18.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,
'post_load': 'monkey_patches',
'uninstall_hook': 'uninstall_hook'
}
17 changes: 17 additions & 0 deletions account_currency_reports_ux/hooks.py
Original file line number Diff line number Diff line change
@@ -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')
115 changes: 115 additions & 0 deletions account_currency_reports_ux/monkey_patches.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
from odoo import api
from odoo.tools import SQL
from odoo.addons.account.report.account_invoice_report import AccountInvoiceReport

def monkey_patches():

# monkey patch
@api.model
def _select_patch(self) -> SQL:
return SQL(
'''
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 = 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 = 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,
line.price_subtotal * (CASE WHEN move.move_type IN ('in_invoice','out_refund','in_receipt') THEN -1 ELSE 1 END)
AS price_subtotal_currency,
CASE WHEN rc.currency_id <> line.company_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 rc.currency_id <> line.company_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,
CASE
WHEN move.move_type NOT IN ('out_invoice', 'out_receipt', 'out_refund') THEN 0.0
WHEN move.move_type = 'out_refund' AND rc.currency_id <> line.company_currency_id THEN -line.balance * currency_table.rate + (line.quantity / NULLIF(COALESCE(uom_line.factor, 1) / COALESCE(uom_template.factor, 1), 0.0)) * COALESCE(product.standard_price -> line.company_id::text, to_jsonb(0.0))::float
WHEN move.move_type = 'out_refund' AND rc.currency_id = line.company_currency_id THEN -line.balance * 1.0 + (line.quantity / NULLIF(COALESCE(uom_line.factor, 1) / COALESCE(uom_template.factor, 1), 0.0)) * COALESCE(product.standard_price -> line.company_id::text, to_jsonb(0.0))::float
WHEN move.move_type IN ('out_invoice', 'out_receipt') AND rc.currency_id <> line.company_currency_id THEN -line.balance * currency_table.rate - (line.quantity / NULLIF(COALESCE(uom_line.factor, 1) / COALESCE(uom_template.factor, 1), 0.0)) * COALESCE(product.standard_price -> line.company_id::text, to_jsonb(0.0))::float
ELSE -line.balance * 1.0 + (line.quantity / NULLIF(COALESCE(uom_line.factor, 1) / COALESCE(uom_template.factor, 1), 0.0)) * COALESCE(product.standard_price -> line.company_id::text, to_jsonb(0.0))::float
END
AS price_margin,
line.quantity / NULLIF(COALESCE(uom_line.factor, 1) / COALESCE(uom_template.factor, 1), 0.0) * (CASE WHEN move.move_type IN ('out_invoice','in_refund','out_receipt') THEN -1 ELSE 1 END)
* COALESCE(product.standard_price -> line.company_id::text, to_jsonb(0.0))::float AS inventory_value,
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_patch(self) -> SQL:
return SQL(
'''
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.currency_id = line.currency_id or currency_table.company_id = %s)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=currency_table.company_id
''', self.env.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)

0 comments on commit 9768801

Please sign in to comment.