[PATCH] Upstream patch - 24122022

This commit is contained in:
Parthiv Patel
2022-12-24 08:35:18 +00:00
parent 73c4bf4443
commit 78c610c08c
6 changed files with 220 additions and 14 deletions
+125
View File
@@ -6,6 +6,8 @@ from flectra import SUPERUSER_ID
from flectra.exceptions import UserError, ValidationError
from flectra.http import request
from flectra.addons.account.models.account_tax import TYPE_TAX_USE
from flectra.tools import html_escape
import logging
@@ -30,6 +32,129 @@ def preserve_existing_tags_on_taxes(cr, registry, module):
if xml_records:
cr.execute("update ir_model_data set noupdate = 't' where id in %s", [tuple(xml_records.ids)])
def update_taxes_from_templates(cr, chart_template_xmlid):
def _create_tax_from_template(company, template, old_tax=None):
"""
Create a new tax from template with template xmlid, if there was already an old tax with that xmlid we
remove the xmlid from it but don't modify anything else.
"""
def _remove_xml_id(xml_id):
module, name = xml_id.split(".", 1)
env['ir.model.data'].search([('module', '=', module), ('name', '=', name)]).unlink()
template_vals = template._get_tax_vals_complete(company)
chart_template = env["account.chart.template"].with_context(default_company_id=company.id)
if old_tax:
xml_id = old_tax.get_xml_id().get(old_tax.id)
if xml_id:
_remove_xml_id(xml_id)
chart_template.create_record_with_xmlid(company, template, "account.tax", template_vals)
def _update_tax_from_template(template, tax):
# -> update the tax : we only updates tax tags
tax_rep_lines = tax.invoice_repartition_line_ids + tax.refund_repartition_line_ids
template_rep_lines = template.invoice_repartition_line_ids + template.refund_repartition_line_ids
for tax_line, template_line in zip(tax_rep_lines, template_rep_lines):
tags_to_add = template_line._get_tags_to_add()
tags_to_unlink = tax_line.tag_ids
if tags_to_add != tags_to_unlink:
tax_line.write({"tag_ids": [(6, 0, tags_to_add.ids)]})
_cleanup_tags(tags_to_unlink)
def _get_template_to_tax_xmlid_mapping(company):
"""
This function uses ir_model_data to return a mapping between the tax templates and the taxes, using their xmlid
:returns: {
account.tax.template.id: account.tax.id
}
"""
env['ir.model.data'].flush()
env.cr.execute(
"""
SELECT template.res_id AS template_res_id,
tax.res_id AS tax_res_id
FROM ir_model_data tax
JOIN ir_model_data template
ON template.name = substr(tax.name, strpos(tax.name, '_') + 1)
WHERE tax.model = 'account.tax'
AND tax.name LIKE %s
-- tax.name is of the form: {company_id}_{account.tax.template.name}
""",
[r"%s\_%%" % company.id],
)
tuples = env.cr.fetchall()
return dict(tuples)
def _is_tax_and_template_same(template, tax):
"""
This function compares account.tax and account.tax.template repartition lines.
A tax is considered the same as the template if they have the same:
- amount_type
- amount
- repartition lines percentages in the same order
"""
tax_rep_lines = tax.invoice_repartition_line_ids + tax.refund_repartition_line_ids
template_rep_lines = template.invoice_repartition_line_ids + template.refund_repartition_line_ids
return (
tax.amount_type == template.amount_type
and tax.amount == template.amount
and len(tax_rep_lines) == len(template_rep_lines)
and all(
rep_line_tax.factor_percent == rep_line_template.factor_percent
for rep_line_tax, rep_line_template in zip(tax_rep_lines, template_rep_lines)
)
)
def _cleanup_tags(tags):
"""
Checks if the tags are still used in taxes or move lines. If not we delete it.
"""
for tag in tags:
tax_using_tag = env['account.tax.repartition.line'].sudo().search([('tag_ids', 'in', tag.id)], limit=1)
aml_using_tag = env['account.move.line'].sudo().search([('tax_tag_ids', 'in', tag.id)], limit=1)
report_line_using_tag = env['account.tax.report.line'].sudo().search([('tag_ids', 'in', tag.id)], limit=1)
if not (aml_using_tag or tax_using_tag or report_line_using_tag):
tag.unlink()
def _notify_accountant_managers(taxes_to_check):
accountant_manager_group = env.ref("account.group_account_manager")
partner_managers_ids = accountant_manager_group.users.mapped('partner_id')
flectrabot = env.ref('base.partner_root')
message_body = _(
"Please check these taxes. They might be outdated. We did not update them. "
"Indeed, they do not exactly match the taxes of the original version of the localization module.<br/>"
"You might want to archive or adapt them.<br/><ul>"
)
for account_tax in taxes_to_check:
message_body += f"<li>{html_escape(account_tax.name)}</li>"
message_body += "</ul>"
partner_managers_ids.message_post(
subject=_('Your taxes have been updated !'),
author_id=flectrabot.id,
body=message_body,
message_type='notification',
subtype_xmlid='mail.mt_comment',
partner_ids=[partner.id for partner in partner_managers_ids],
)
env = api.Environment(cr, SUPERUSER_ID, {})
chart_template_id = env['ir.model.data'].xmlid_to_res_id(chart_template_xmlid)
companies = env['res.company'].search([('chart_template_id', '=', chart_template_id)])
outdated_taxes = []
for company in companies:
template_to_tax = _get_template_to_tax_xmlid_mapping(company)
templates = env['account.tax.template'].search([("chart_template_id", "=", chart_template_id)])
for template in templates:
tax = env["account.tax"].browse(template_to_tax.get(template.id))
if not tax or not _is_tax_and_template_same(template, tax):
_create_tax_from_template(company, template, old_tax=tax)
if tax:
outdated_taxes.append(tax)
else:
_update_tax_from_template(template, tax)
if outdated_taxes:
_notify_accountant_managers(outdated_taxes)
# ---------------------------------------------------------------
# Account Templates: Account, Tax, Tax Code and chart. + Wizard
# ---------------------------------------------------------------
+1 -1
View File
@@ -7,7 +7,7 @@
{
'name': 'Luxembourg - Accounting',
'version': '2.0',
'version': '2.1',
'category': 'Accounting/Localizations/Account Charts',
'description': """
This is the base module to manage the accounting chart for Luxembourg.
@@ -0,0 +1,6 @@
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from flectra.addons.account.models.chart_template import update_taxes_from_templates
def migrate(cr, version):
update_taxes_from_templates(cr, 'l10n_lu.lu_2011_chart_1')
+12 -12
View File
@@ -53,22 +53,21 @@ class AccountMove(models.Model):
debit_pdiff_account = move.fiscal_position_id.map_account(debit_pdiff_account)
if not debit_pdiff_account:
continue
# Retrieve stock valuation moves.
valuation_stock_moves = self.env['stock.move'].search([
('purchase_line_id', '=', line.purchase_line_id.id),
('state', '=', 'done'),
('product_qty', '!=', 0.0),
]) if line.purchase_line_id else self.env['stock.move']
if move.move_type == 'in_refund':
valuation_stock_moves = valuation_stock_moves.filtered(lambda stock_move: stock_move._is_out())
else:
valuation_stock_moves = valuation_stock_moves.filtered(lambda stock_move: stock_move._is_in())
if line.product_id.cost_method != 'standard' and line.purchase_line_id:
po_currency = line.purchase_line_id.currency_id
po_company = line.purchase_line_id.company_id
# Retrieve stock valuation moves.
valuation_stock_moves = self.env['stock.move'].search([
('purchase_line_id', '=', line.purchase_line_id.id),
('state', '=', 'done'),
('product_qty', '!=', 0.0),
])
if move.move_type == 'in_refund':
valuation_stock_moves = valuation_stock_moves.filtered(lambda stock_move: stock_move._is_out())
else:
valuation_stock_moves = valuation_stock_moves.filtered(lambda stock_move: stock_move._is_in())
if valuation_stock_moves:
valuation_price_unit_total, valuation_total_qty = valuation_stock_moves._get_valuation_price_and_qty(line, move.currency_id)
valuation_price_unit = valuation_price_unit_total / valuation_total_qty
@@ -91,9 +90,10 @@ class AccountMove(models.Model):
else:
# Valuation_price unit is always expressed in invoice currency, so that it can always be computed with the good rate
price_unit = line.product_id.uom_id._compute_price(line.product_id.standard_price, line.product_uom_id)
valuation_date = valuation_stock_moves and max(valuation_stock_moves.mapped('date')) or move.date
valuation_price_unit = line.company_currency_id._convert(
price_unit, move.currency_id,
move.company_id, fields.Date.today(), round=False
move.company_id, valuation_date, round=False
)
@@ -2,6 +2,7 @@
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from flectra.addons.stock_account.tests.test_anglo_saxon_valuation_reconciliation_common import ValuationReconciliationTestCommon
from flectra.tests.common import Form, tagged
from flectra import fields
from freezegun import freeze_time
@@ -256,6 +257,80 @@ class TestValuationReconciliation(ValuationReconciliationTestCommon):
picking = self.env['stock.picking'].search([('purchase_id', '=', purchase_order.id)])
self.check_reconciliation(invoice, picking)
@freeze_time('2021-01-03')
def test_price_difference_exchange_difference_accounting_date(self):
test_product = self.test_product_delivery
test_product.categ_id.write({"property_cost_method": "standard"})
test_product.write({'standard_price': 100.0})
date_po_receipt = '2021-01-02'
rate_po_receipt = 25.0
date_bill = '2021-01-01'
rate_bill = 30.0
date_accounting = '2021-01-03'
rate_accounting = 26.0
foreign_currency = self.currency_data['currency']
company_currency = self.env.company.currency_id
self.env['res.currency.rate'].create([
{
'name': date_po_receipt,
'rate': rate_po_receipt,
'currency_id': foreign_currency.id,
'company_id': self.env.company.id,
}, {
'name': date_bill,
'rate': rate_bill,
'currency_id': foreign_currency.id,
'company_id': self.env.company.id,
}, {
'name': date_accounting,
'rate': rate_accounting,
'currency_id': foreign_currency.id,
'company_id': self.env.company.id,
}, {
'name': date_po_receipt,
'rate': 1.0,
'currency_id': company_currency.id,
'company_id': self.env.company.id,
}, {
'name': date_accounting,
'rate': 1.0,
'currency_id': company_currency.id,
'company_id': self.env.company.id,
}, {
'name': date_bill,
'rate': 1.0,
'currency_id': company_currency.id,
'company_id': self.env.company.id,
}])
#purchase order created in foreign currency
purchase_order = self._create_purchase(test_product, date_po_receipt, quantity=10, price_unit=3000)
with freeze_time(date_po_receipt):
self._process_pickings(purchase_order.picking_ids)
invoice = self._create_invoice_for_po(purchase_order, date_bill)
with Form(invoice) as move_form:
move_form.invoice_date = fields.Date.from_string(date_bill)
move_form.date = fields.Date.from_string(date_accounting)
invoice.action_post()
price_diff_line = invoice.line_ids.filtered(lambda l: l.account_id == self.stock_account_product_categ.property_account_creditor_price_difference_categ)
self.assertTrue(len(price_diff_line) == 1, "A price difference line should be created")
self.assertAlmostEqual(price_diff_line.balance, 192.31)
self.assertAlmostEqual(price_diff_line.price_total, 5000.0)
picking = self.env['stock.picking'].search([('purchase_id', '=', purchase_order.id)])
self.check_reconciliation(invoice, picking)
interim_account_id = self.company_data['default_account_stock_in'].id
valuation_line = picking.move_lines.mapped('account_move_ids.line_ids').filtered(lambda x: x.account_id.id == interim_account_id)
self.assertTrue(valuation_line.full_reconcile_id, "The reconciliation should be total at that point.")
exchange_move = valuation_line.full_reconcile_id.exchange_move_id
self.assertTrue(exchange_move, "An exchange move should exists.")
exchange_difference = exchange_move.line_ids.filtered(lambda l: l.account_id.id == interim_account_id).balance
self.assertAlmostEqual(exchange_difference, 38.46, "Exchange amount is incorrect")
def test_reconcile_cash_basis_bill(self):
''' Test the generation of the CABA move after bill payment
'''
+1 -1
View File
@@ -269,7 +269,7 @@ var Dialog = Widget.extend({
this.$modal.remove();
}
var modals = $('body > .modal').filter(':visible');
const modals = $('body .modal').filter(':visible');
if (modals.length) {
if (!isFocusSet) {
modals.last().focus();