19.0 vanilla

This commit is contained in:
Ernad Husremovic 2026-03-09 09:30:07 +01:00
parent ba20ce7443
commit 768b70e05e
2357 changed files with 1057103 additions and 712486 deletions

View file

@ -1,29 +1,32 @@
# -*- coding: utf-8 -*-
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
from odoo.tests import tagged
from odoo import fields
from odoo import Command, fields
@tagged('post_install', '-at_install')
class TestAccountInvoiceReport(AccountTestInvoicingCommon):
@classmethod
def setUpClass(cls, chart_template_ref=None):
super().setUpClass(chart_template_ref=chart_template_ref)
def setUpClass(cls):
super().setUpClass()
cls.other_currency = cls.setup_other_currency('EUR')
cls.company_data_2 = cls.setup_other_company()
pack_of_six = cls.env['uom.uom'].search([('name', '=', 'Pack of 6')])
cls.invoices = cls.env['account.move'].create([
{
'move_type': 'out_invoice',
'partner_id': cls.partner_a.id,
'invoice_date': fields.Date.from_string('2016-01-01'),
'currency_id': cls.currency_data['currency'].id,
'currency_id': cls.other_currency.id,
'invoice_line_ids': [
(0, None, {
Command.create({
'product_id': cls.product_a.id,
'quantity': 3,
'price_unit': 750,
'price_unit': 4500,
'product_uom_id': pack_of_six.id,
}),
(0, None, {
Command.create({
'product_id': cls.product_a.id,
'quantity': 1,
'price_unit': 3000,
@ -33,9 +36,9 @@ class TestAccountInvoiceReport(AccountTestInvoicingCommon):
{
'move_type': 'out_receipt',
'invoice_date': fields.Date.from_string('2016-01-01'),
'currency_id': cls.currency_data['currency'].id,
'currency_id': cls.other_currency.id,
'invoice_line_ids': [
(0, None, {
Command.create({
'product_id': cls.product_a.id,
'quantity': 1,
'price_unit': 6000,
@ -46,22 +49,28 @@ class TestAccountInvoiceReport(AccountTestInvoicingCommon):
'move_type': 'out_refund',
'partner_id': cls.partner_a.id,
'invoice_date': fields.Date.from_string('2017-01-01'),
'currency_id': cls.currency_data['currency'].id,
'currency_id': cls.other_currency.id,
'invoice_line_ids': [
(0, None, {
Command.create({
'product_id': cls.product_a.id,
'quantity': 1,
'price_unit': 1200,
}),
Command.create({
'product_id': cls.product_a.id,
'quantity': 3,
'price_unit': 4500,
'product_uom_id': pack_of_six.id,
}),
]
},
{
'move_type': 'in_invoice',
'partner_id': cls.partner_a.id,
'invoice_date': fields.Date.from_string('2016-01-01'),
'currency_id': cls.currency_data['currency'].id,
'currency_id': cls.other_currency.id,
'invoice_line_ids': [
(0, None, {
Command.create({
'product_id': cls.product_a.id,
'quantity': 1,
'price_unit': 60,
@ -72,9 +81,9 @@ class TestAccountInvoiceReport(AccountTestInvoicingCommon):
'move_type': 'in_receipt',
'partner_id': cls.partner_a.id,
'invoice_date': fields.Date.from_string('2016-01-01'),
'currency_id': cls.currency_data['currency'].id,
'currency_id': cls.other_currency.id,
'invoice_line_ids': [
(0, None, {
Command.create({
'product_id': cls.product_a.id,
'quantity': 1,
'price_unit': 60,
@ -85,15 +94,28 @@ class TestAccountInvoiceReport(AccountTestInvoicingCommon):
'move_type': 'in_refund',
'partner_id': cls.partner_a.id,
'invoice_date': fields.Date.from_string('2017-01-01'),
'currency_id': cls.currency_data['currency'].id,
'currency_id': cls.other_currency.id,
'invoice_line_ids': [
(0, None, {
Command.create({
'product_id': cls.product_a.id,
'quantity': 1,
'price_unit': 12,
}),
]
},
{
'move_type': 'out_refund',
'partner_id': cls.partner_a.id,
'invoice_date': fields.Date.from_string('2017-01-01'),
'currency_id': cls.other_currency.id,
'invoice_line_ids': [
Command.create({
'product_id': cls.product_a.id,
'quantity': 1,
'price_unit': 2400,
}),
]
},
])
def assertInvoiceReportValues(self, expected_values_list):
@ -102,20 +124,66 @@ class TestAccountInvoiceReport(AccountTestInvoicingCommon):
'price_average': vals[0],
'price_subtotal': vals[1],
'quantity': vals[2],
'price_margin': vals[3],
'inventory_value': vals[4],
} for vals in expected_values_list]
self.assertRecordValues(reports, expected_values_dict)
def test_invoice_report_multiple_types(self):
"""
Each line represent an invoice line
First and last lines use Packagings. Quantity and price from the invoice are adapted
to the standard UoM of the product.
quantity is quantity in product_uom
price_subtotal = Price_unit * Number_of_packages / currency_rate
price_average = price_subtotal / quantity
inventory_value = quantity * standard_price * (-1 OR 1 depending of move_type)
price_margin = (price_average - standard_price) * quantity
E.g. first line:
quantity : 6 * 3 = 18
price_subtotal = 4500 * 3 / 3 = 4500
price_average = 4500 / 18 = 250
inventory_value = 800*18*-1 = -14400
price_margin = (250 - 800) * 18 = -9900
"""
self.assertInvoiceReportValues([
#price_average price_subtotal quantity
[2000, 2000, 1],
[1000, 1000, 1],
[250, 750, 3],
[6, 6, 1],
[20, -20, -1],
[20, -20, -1],
[600, -600, -1],
# pylint: disable=bad-whitespace
# price_average, price_subtotal, quantity, price_margin, inventory_value
[ 250, 4500, 18, -9900, -14400], # price_unit = 4500, currency.rate = 3.0
[ 2000, 2000, 1, 1200, -800], # price_unit = 6000, currency.rate = 3.0
[ 1000, 1000, 1, 200, -800], # price_unit = 3000, currency.rate = 3.0
[ 6, 6, 1, 0, -800], # price_unit = 12, currency.rate = 2.0
[ 20, -20, -1, 0, 800], # price_unit = 60, currency.rate = 3.0
[ 20, -20, -1, 0, 800], # price_unit = 60, currency.rate = 3.0
[ 600, -600, -1, 200, 800], # price_unit = 1200, currency.rate = 2.0
[ 1200, -1200, -1, -400, 800], # price_unit = 2400, currency.rate = 2.0
[ 375, -6750, -18, 7650, 14400], # price_unit = 4500, currency.rate = 2.0
])
def test_invoice_report_multicompany_product_cost(self):
"""
In a multicompany environment, if you define one product with different standard price per company
the invoice analysis report should only display the product from the company
Standard Price in Company A: 800 (default setup)
Standard Price in Company B: 700
-> invoice report for Company A should remain the same
"""
self.product_a.with_company(self.company_data_2.get('company')).write({'standard_price': 700.0})
self.assertInvoiceReportValues([
# pylint: disable=bad-whitespace
# price_average, price_subtotal, quantity, price_margin, inventory_value
[ 250, 4500, 18, -9900, -14400], # price_unit = 4500, currency.rate = 3.0
[ 2000, 2000, 1, 1200, -800], # price_unit = 6000, currency.rate = 3.0
[ 1000, 1000, 1, 200, -800], # price_unit = 3000, currency.rate = 3.0
[ 6, 6, 1, 0, -800], # price_unit = 12, currency.rate = 2.0
[ 20, -20, -1, 0, 800], # price_unit = 60, currency.rate = 3.0
[ 20, -20, -1, 0, 800], # price_unit = 60, currency.rate = 3.0
[ 600, -600, -1, 200, 800], # price_unit = 1200, currency.rate = 2.0
[ 1200, -1200, -1, -400, 800], # price_unit = 2400, currency.rate = 2.0
[ 375, -6750, -18, 7650, 14400], # price_unit = 4500, currency.rate = 2.0
])
def test_avg_price_calculation(self):
@ -155,19 +223,125 @@ class TestAccountInvoiceReport(AccountTestInvoicingCommon):
})
invoice.action_post()
report = self.env['account.invoice.report'].read_group(
report = self.env['account.invoice.report'].formatted_read_group(
[('product_id', '=', product.id)],
[],
['price_subtotal:sum', 'quantity:sum', 'price_average:avg'],
[],
)
self.assertEqual(report[0]['quantity'], 35)
self.assertEqual(report[0]['price_subtotal'], 165)
self.assertEqual(round(report[0]['price_average'], 2), 4.71)
self.assertEqual(report[0]['quantity:sum'], 35)
self.assertEqual(report[0]['price_subtotal:sum'], 165)
self.assertEqual(round(report[0]['price_average:avg'], 2), 4.71)
# ensure that it works with only 'price_average:avg' in fields
report = self.env['account.invoice.report'].read_group(
# ensure that it works with only 'price_average:avg' in aggregates
report = self.env['account.invoice.report'].formatted_read_group(
[('product_id', '=', product.id)],
['price_average:avg'],
[],
['price_average:avg'],
)
self.assertEqual(round(report[0]['price_average'], 2), 4.71)
self.assertEqual(round(report[0]['price_average:avg'], 2), 4.71)
def test_avg_price_group_by_month(self):
"""
Check that the average is correctly calculated based on the total price and quantity
with multiple invoices and group by month:
Invoice 1:
2 lines:
- 10 units * 10$
- 5 units * 5$
Total quantity: 15
Total price: 125$
Average: 125 / 15 = 8.33
Invoice 2:
1 line:
- 0 units * 5$
Total quantity: 0
Total price: 0$
Average: 0.00
"""
self.env['account.move'].search([]).unlink()
invoices = self.env["account.move"].create([
{
'move_type': 'out_invoice',
'partner_id': self.partner_a.id,
'invoice_date': fields.Date.from_string('2025-01-01'),
'currency_id': self.env.company.currency_id.id,
'invoice_line_ids': [
Command.create({
'product_id': self.product_a.id,
'quantity': 10,
'price_unit': 10,
}),
Command.create({
'product_id': self.product_a.id,
'quantity': 5,
'price_unit': 5,
}),
]
},
{
'move_type': 'out_invoice',
'partner_id': self.partner_a.id,
'invoice_date': fields.Date.from_string('2025-02-01'),
'currency_id': self.env.company.currency_id.id,
'invoice_line_ids': [
Command.create({
'product_id': self.product_a.id,
'quantity': 0,
'price_unit': 5,
}),
]
},
])
invoices.action_post()
report = self.env['account.invoice.report'].formatted_read_group(
[('product_id', '=', self.product_a.id)],
['invoice_date:month'],
['__count', 'price_subtotal:sum', 'quantity:sum', 'price_average:avg'],
)
self.assertEqual(report[0]['__count'], 2)
self.assertEqual(report[0]['quantity:sum'], 15.0)
self.assertEqual(report[0]['price_subtotal:sum'], 125.0)
self.assertEqual(round(report[0]['price_average:avg'], 2), 8.33)
self.assertEqual(report[1]['__count'], 1)
self.assertEqual(report[1]['quantity:sum'], 0.0)
self.assertEqual(report[1]['price_subtotal:sum'], 0.0)
self.assertEqual(report[1]['price_average:avg'], 0.00)
def test_inventory_margin_currency(self):
invoice = self.env['account.move'].create({
'move_type': 'out_invoice',
'invoice_line_ids': [
Command.create({
'product_id': self.product_a.id,
'quantity': 1,
'price_unit': 750,
}),
],
})
egy_company = self.env['res.company'].create({
'name': 'Egyptian Company',
'currency_id': self.env.ref('base.EGP').id,
'user_ids': [Command.set(self.env.user.ids)],
})
orig_company = self.env.company
report = self.env['account.invoice.report'].search(
[('move_id', '=', invoice.id)],
)
self.assertEqual(report.inventory_value, -800)
self.assertEqual(report.price_margin, -50)
self.env.user.company_id = egy_company
self.env['res.currency.rate'].create({
'name': '2017-11-03',
'rate': 0.5,
'currency_id': orig_company.currency_id.id,
})
self.env.flush_all()
self.env['account.invoice.report'].invalidate_model()
report = self.env['account.invoice.report'].search(
[('move_id', '=', invoice.id)],
)
self.assertEqual(report.inventory_value, -1600)
self.assertEqual(report.price_margin, -100)