mirror of
https://github.com/bringout/oca-financial.git
synced 2026-04-26 18:02:08 +02:00
Initial commit: OCA Financial packages (186 packages)
This commit is contained in:
commit
3e0e8473fb
8757 changed files with 947473 additions and 0 deletions
|
|
@ -0,0 +1 @@
|
|||
from . import test_ecotax
|
||||
|
|
@ -0,0 +1,423 @@
|
|||
# Copyright 2016-2023 Akretion France
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# Copyright 2021 Camptocamp
|
||||
# @author Silvio Gregorini <silvio.gregorini@camptocamp.com>
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from random import choice
|
||||
|
||||
from odoo import Command
|
||||
from odoo.tests.common import Form, TransactionCase
|
||||
|
||||
|
||||
class TestInvoiceEcotaxCommon(TransactionCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
|
||||
|
||||
# ACCOUNTING STUFF
|
||||
# 1- Tax account
|
||||
cls.invoice_tax_account = cls.env["account.account"].create(
|
||||
{
|
||||
"code": "47590",
|
||||
"name": "Invoice Tax Account",
|
||||
"account_type": "liability_current",
|
||||
"company_id": cls.env.user.company_id.id,
|
||||
}
|
||||
)
|
||||
# 2- Invoice tax with included price to avoid unwanted amounts in tests
|
||||
cls.invoice_tax = cls.env["account.tax"].create(
|
||||
{
|
||||
"name": "Tax 10%",
|
||||
"price_include": True,
|
||||
"type_tax_use": "sale",
|
||||
"company_id": cls.env.user.company_id.id,
|
||||
"amount": 10,
|
||||
"tax_exigibility": "on_invoice",
|
||||
"invoice_repartition_line_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"factor_percent": 100,
|
||||
"repartition_type": "base",
|
||||
},
|
||||
),
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"factor_percent": 100,
|
||||
"repartition_type": "tax",
|
||||
"account_id": cls.invoice_tax_account.id,
|
||||
},
|
||||
),
|
||||
],
|
||||
"refund_repartition_line_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"factor_percent": 100,
|
||||
"repartition_type": "base",
|
||||
},
|
||||
),
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"factor_percent": 100,
|
||||
"repartition_type": "tax",
|
||||
"account_id": cls.invoice_tax_account.id,
|
||||
},
|
||||
),
|
||||
],
|
||||
}
|
||||
)
|
||||
# ECOTAXES
|
||||
# 1- Fixed ecotax
|
||||
cls.ecotax_fixed = cls.env["account.ecotax.classification"].create(
|
||||
{
|
||||
"name": "Fixed Ecotax",
|
||||
"ecotax_type": "fixed",
|
||||
"default_fixed_ecotax": 5.0,
|
||||
"product_status": "M",
|
||||
"supplier_status": "MAN",
|
||||
}
|
||||
)
|
||||
# 2- Weight-based ecotax
|
||||
cls.ecotax_weight = cls.env["account.ecotax.classification"].create(
|
||||
{
|
||||
"name": "Weight Based Ecotax",
|
||||
"ecotax_type": "weight_based",
|
||||
"ecotax_coef": 0.04,
|
||||
"product_status": "P",
|
||||
"supplier_status": "MAN",
|
||||
}
|
||||
)
|
||||
# MISC
|
||||
# 1- Invoice partner
|
||||
cls.invoice_partner = cls.env["res.partner"].create({"name": "Test"})
|
||||
|
||||
@classmethod
|
||||
def _make_invoice(cls, products):
|
||||
"""Creates a new customer invoice with given products and returns it"""
|
||||
move_form = Form(
|
||||
cls.env["account.move"].with_context(default_move_type="out_invoice")
|
||||
)
|
||||
move_form.partner_id = cls.invoice_partner
|
||||
|
||||
for product in products or []:
|
||||
with move_form.invoice_line_ids.new() as line_form:
|
||||
line_form.product_id = product
|
||||
|
||||
invoice = move_form.save()
|
||||
return invoice
|
||||
|
||||
@classmethod
|
||||
def _make_product(cls, ecotax_classification):
|
||||
"""Creates a product template with given ecotax classification
|
||||
|
||||
Returns the newly created template variant
|
||||
"""
|
||||
tmpl = cls.env["product.template"].create(
|
||||
{
|
||||
"name": " - ".join(["Product", ecotax_classification.name]),
|
||||
"ecotax_line_product_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"classification_id": ecotax_classification.id,
|
||||
},
|
||||
)
|
||||
],
|
||||
# For the sake of simplicity, every product will have a price
|
||||
# and weight of 100
|
||||
"list_price": 100.00,
|
||||
"weight": 100.00,
|
||||
"taxes_id": [Command.set(cls.invoice_tax.ids)],
|
||||
}
|
||||
)
|
||||
return tmpl.product_variant_ids[0]
|
||||
|
||||
@classmethod
|
||||
def _make_product_variants(cls, ecotax_classification):
|
||||
"""Creates a product variants with given ecotax classification
|
||||
Returns the newly created template variants
|
||||
"""
|
||||
size_attr = cls.env["product.attribute"].create(
|
||||
{
|
||||
"name": "Size",
|
||||
"create_variant": "always",
|
||||
"value_ids": [(0, 0, {"name": "S"}), (0, 0, {"name": "M"})],
|
||||
}
|
||||
)
|
||||
|
||||
tmpl = cls.env["product.template"].create(
|
||||
{
|
||||
"name": " - ".join(["Product", ecotax_classification.name]),
|
||||
"ecotax_line_product_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"classification_id": ecotax_classification.id,
|
||||
},
|
||||
)
|
||||
],
|
||||
# For the sake of simplicity, every product will have a price
|
||||
# and weight of 100
|
||||
"list_price": 100.00,
|
||||
"weight": 100.00,
|
||||
"attribute_line_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"attribute_id": size_attr.id,
|
||||
"value_ids": [(6, 0, size_attr.value_ids.ids)],
|
||||
},
|
||||
)
|
||||
],
|
||||
}
|
||||
)
|
||||
return tmpl.product_variant_ids
|
||||
|
||||
@staticmethod
|
||||
def _set_invoice_lines_random_quantities(invoice) -> list:
|
||||
"""For each invoice line, sets a random qty between 1 and 10
|
||||
|
||||
Returns the list of new quantities as a list
|
||||
"""
|
||||
new_qtys = []
|
||||
with Form(invoice) as invoice_form:
|
||||
for index in range(len(invoice.invoice_line_ids)):
|
||||
with invoice_form.invoice_line_ids.edit(index) as line_form:
|
||||
new_qty = choice([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
||||
line_form.quantity = new_qty
|
||||
new_qtys.insert(index, new_qty)
|
||||
line_form.save()
|
||||
invoice_form.save()
|
||||
return new_qtys
|
||||
|
||||
def _run_checks(self, inv, inv_expected_amounts, inv_lines_expected_amounts):
|
||||
self.assertAlmostEqual(inv.amount_ecotax, inv_expected_amounts["amount_ecotax"])
|
||||
self.assertAlmostEqual(inv.amount_total, inv_expected_amounts["amount_total"])
|
||||
self.assertEqual(len(inv.invoice_line_ids), len(inv_lines_expected_amounts))
|
||||
for inv_line, inv_line_expected_amounts in zip(
|
||||
inv.invoice_line_ids, inv_lines_expected_amounts
|
||||
):
|
||||
self.assertEqual(
|
||||
inv_line.ecotax_amount_unit,
|
||||
inv_line_expected_amounts["ecotax_amount_unit"],
|
||||
)
|
||||
self.assertEqual(
|
||||
inv_line.subtotal_ecotax, inv_line_expected_amounts["subtotal_ecotax"]
|
||||
)
|
||||
|
||||
def _test_01_default_fixed_ecotax(self):
|
||||
"""Test default fixed ecotax
|
||||
|
||||
Ecotax classification data for this test:
|
||||
- fixed type
|
||||
- default amount: 5.0
|
||||
Product data for this test:
|
||||
- list price: 100
|
||||
- fixed ecotax
|
||||
- no manual amount
|
||||
|
||||
Expected results (with 1 line and qty = 1):
|
||||
- invoice ecotax amount: 5.0
|
||||
- invoice total amount: 100.0
|
||||
- line ecotax unit amount: 5.0
|
||||
- line ecotax total amount: 5.0
|
||||
"""
|
||||
invoice = self._make_invoice(products=self._make_product(self.ecotax_fixed))
|
||||
self._run_checks(
|
||||
invoice,
|
||||
{"amount_ecotax": 5.0, "amount_total": 100.0},
|
||||
[{"ecotax_amount_unit": 5.0, "subtotal_ecotax": 5.0}],
|
||||
)
|
||||
new_qty = self._set_invoice_lines_random_quantities(invoice)[0]
|
||||
self._run_checks(
|
||||
invoice,
|
||||
{"amount_ecotax": 5.0 * new_qty, "amount_total": 100.0 * new_qty},
|
||||
[{"ecotax_amount_unit": 5.0, "subtotal_ecotax": 5.0 * new_qty}],
|
||||
)
|
||||
|
||||
def _test_02_force_fixed_ecotax_on_product(self):
|
||||
"""Test manual fixed ecotax
|
||||
|
||||
Ecotax classification data for this test:
|
||||
- fixed type
|
||||
- default amount: 5.0
|
||||
Product data for this test:
|
||||
- list price: 100
|
||||
- fixed ecotax
|
||||
- Force ecotax amount: 10
|
||||
|
||||
Expected results (with 1 line and qty = 1):
|
||||
- invoice ecotax amount: 10.0
|
||||
- invoice total amount: 100.0
|
||||
- line ecotax unit amount: 10.0
|
||||
- line ecotax total amount: 10.0
|
||||
"""
|
||||
product = self._make_product(self.ecotax_fixed)
|
||||
product.ecotax_line_product_ids[0].force_amount = 10
|
||||
invoice = self._make_invoice(products=product)
|
||||
self._run_checks(
|
||||
invoice,
|
||||
{"amount_ecotax": 10.0, "amount_total": 100.0},
|
||||
[{"ecotax_amount_unit": 10.0, "subtotal_ecotax": 10.0}],
|
||||
)
|
||||
new_qty = self._set_invoice_lines_random_quantities(invoice)[0]
|
||||
self._run_checks(
|
||||
invoice,
|
||||
{"amount_ecotax": 10.0 * new_qty, "amount_total": 100.0 * new_qty},
|
||||
[{"ecotax_amount_unit": 10.0, "subtotal_ecotax": 10.0 * new_qty}],
|
||||
)
|
||||
|
||||
def _test_03_weight_based_ecotax(self):
|
||||
"""Test weight based ecotax
|
||||
|
||||
Ecotax classification data for this test:
|
||||
- weight based type
|
||||
- coefficient: 0.04
|
||||
Product data for this test:
|
||||
- list price: 100
|
||||
- weight based ecotax
|
||||
- weight: 100
|
||||
|
||||
Expected results (with 1 line and qty = 1):
|
||||
- invoice ecotax amount: 4.0
|
||||
- invoice total amount: 100.0
|
||||
- line ecotax unit amount: 4.0
|
||||
- line ecotax total amount: 4.0
|
||||
"""
|
||||
invoice = self._make_invoice(products=self._make_product(self.ecotax_weight))
|
||||
self._run_checks(
|
||||
invoice,
|
||||
{"amount_ecotax": 4.0, "amount_total": 100.0},
|
||||
[{"ecotax_amount_unit": 4.0, "subtotal_ecotax": 4.0}],
|
||||
)
|
||||
new_qty = self._set_invoice_lines_random_quantities(invoice)[0]
|
||||
self._run_checks(
|
||||
invoice,
|
||||
{"amount_ecotax": 4.0 * new_qty, "amount_total": 100.0 * new_qty},
|
||||
[{"ecotax_amount_unit": 4.0, "subtotal_ecotax": 4.0 * new_qty}],
|
||||
)
|
||||
|
||||
def _test_04_mixed_ecotax(self):
|
||||
"""Test mixed ecotax within the same invoice
|
||||
|
||||
Creating an invoice with 3 lines (one per type with types tested above)
|
||||
|
||||
Expected results (with 3 lines and qty = 1):
|
||||
- invoice ecotax amount: 19.0
|
||||
- invoice total amount: 300.0
|
||||
- line ecotax unit amount (fixed ecotax): 5.0
|
||||
- line ecotax total amount (fixed ecotax): 5.0
|
||||
- line ecotax unit amount (manual ecotax): 10.0
|
||||
- line ecotax total amount (manual ecotax): 10.0
|
||||
- line ecotax unit amount (weight based ecotax): 4.0
|
||||
- line ecotax total amount (weight based ecotax): 4.0
|
||||
"""
|
||||
default_fixed_product = self._make_product(self.ecotax_fixed)
|
||||
manual_fixed_product = self._make_product(self.ecotax_fixed)
|
||||
manual_fixed_product.ecotax_line_product_ids[0].force_amount = 10
|
||||
weight_based_product = self._make_product(self.ecotax_weight)
|
||||
invoice = self._make_invoice(
|
||||
products=default_fixed_product | manual_fixed_product | weight_based_product
|
||||
)
|
||||
self._run_checks(
|
||||
invoice,
|
||||
{"amount_ecotax": 19.0, "amount_total": 300.0},
|
||||
[
|
||||
{"ecotax_amount_unit": 5.0, "subtotal_ecotax": 5.0},
|
||||
{"ecotax_amount_unit": 10.0, "subtotal_ecotax": 10.0},
|
||||
{"ecotax_amount_unit": 4.0, "subtotal_ecotax": 4.0},
|
||||
],
|
||||
)
|
||||
new_qtys = self._set_invoice_lines_random_quantities(invoice)
|
||||
self._run_checks(
|
||||
invoice,
|
||||
{
|
||||
"amount_ecotax": 5.0 * new_qtys[0]
|
||||
+ 10.0 * new_qtys[1]
|
||||
+ 4.0 * new_qtys[2],
|
||||
"amount_total": 100.0 * sum(new_qtys),
|
||||
},
|
||||
[
|
||||
{"ecotax_amount_unit": 5.0, "subtotal_ecotax": 5.0 * new_qtys[0]},
|
||||
{"ecotax_amount_unit": 10.0, "subtotal_ecotax": 10.0 * new_qtys[1]},
|
||||
{"ecotax_amount_unit": 4.0, "subtotal_ecotax": 4.0 * new_qtys[2]},
|
||||
],
|
||||
)
|
||||
|
||||
def _test_05_product_variants(self):
|
||||
"""
|
||||
Data:
|
||||
A product template with two variants
|
||||
Test Case:
|
||||
Add additional ecotax line to one variant
|
||||
Expected result:
|
||||
The additional ecotax line is not associated to second variant
|
||||
the all ecotax lines of the variant contains both the ecotax
|
||||
line of the product template and the additional ecotax line
|
||||
"""
|
||||
variants = self._make_product_variants(self.ecotax_fixed)
|
||||
self.assertEqual(len(variants), 2)
|
||||
variant_1 = variants[0]
|
||||
variant_2 = variants[1]
|
||||
self.assertEqual(
|
||||
variant_1.all_ecotax_line_product_ids,
|
||||
variant_2.all_ecotax_line_product_ids,
|
||||
)
|
||||
variant_1.additional_ecotax_line_product_ids = [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"classification_id": self.ecotax_weight.id,
|
||||
},
|
||||
)
|
||||
]
|
||||
all_additional_ecotax = (
|
||||
variant_1.additional_ecotax_line_product_ids
|
||||
| variant_1.product_tmpl_id.ecotax_line_product_ids
|
||||
)
|
||||
self.assertEqual(
|
||||
len(variant_1.all_ecotax_line_product_ids),
|
||||
2,
|
||||
)
|
||||
self.assertEqual(
|
||||
len(variant_2.all_ecotax_line_product_ids),
|
||||
1,
|
||||
)
|
||||
self.assertEqual(
|
||||
variant_1.all_ecotax_line_product_ids,
|
||||
all_additional_ecotax,
|
||||
)
|
||||
self.assertEqual(
|
||||
variant_2.all_ecotax_line_product_ids,
|
||||
variant_2.product_tmpl_id.ecotax_line_product_ids,
|
||||
)
|
||||
|
||||
|
||||
class TestInvoiceEcotax(TestInvoiceEcotaxCommon):
|
||||
def test_01_default_fixed_ecotax(self):
|
||||
self._test_01_default_fixed_ecotax()
|
||||
|
||||
def test_02_force_fixed_ecotax_on_product(self):
|
||||
self._test_02_force_fixed_ecotax_on_product()
|
||||
|
||||
def test_03_weight_based_ecotax(self):
|
||||
self._test_03_weight_based_ecotax()
|
||||
|
||||
def test_04_mixed_ecotax(self):
|
||||
self._test_04_mixed_ecotax()
|
||||
|
||||
def test_05_product_variants(self):
|
||||
self._test_05_product_variants()
|
||||
Loading…
Add table
Add a link
Reference in a new issue