Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[17.0][FIX] account_invoice_section_sale_order: FWD port and fix test-case #1871

Open
wants to merge 5 commits into
base: 17.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions account_invoice_section_sale_order/models/sale_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@ def _create_invoices(self, grouped=False, final=False, date=None):
the group name.
Only do this for invoices targetting multiple groups
"""
invoice_ids = super()._create_invoices(grouped=grouped, final=final, date=date)
for invoice in invoice_ids:
if (
invoices = super()._create_invoices(grouped=grouped, final=final, date=date)
for invoice in invoices.sudo():
if invoice.line_ids and (
len(invoice.line_ids.mapped(invoice.line_ids._get_section_grouping()))
== 1
):
continue
sequence = 10
# Because invoices are already created, this would require
# an extra read access in order to read order fields.
move_lines = invoice._get_ordered_invoice_lines()
# Group move lines according to their sale order
section_grouping_matrix = OrderedDict()
Expand Down Expand Up @@ -55,19 +57,17 @@ def _create_invoices(self, grouped=False, final=False, date=None):
)
)
sequence += 10
for move_line in self.env["account.move.line"].browse(move_line_ids):
if move_line.display_type == "line_section":
# add extra indent for existing SO Sections
move_line.name = f"- {move_line.name}"
for move_line in (
self.env["account.move.line"].sudo().browse(move_line_ids)
):
# Because invoices are already created, this would require
# an extra write access in order to read order fields.
move_line.sequence = sequence
sequence += 10
# Because invoices are already created, this would require
# an extra write access in order to read order fields.
invoice.line_ids = section_lines
return invoice_ids

def _get_ordered_invoice_lines(self, invoice):
return invoice.invoice_line_ids.sorted(
key=lambda r: r.sale_line_ids.order_id.id
)
return invoices

def _get_invoice_section_name(self):
"""Returns the text for the section name."""
Expand Down
1 change: 1 addition & 0 deletions account_invoice_section_sale_order/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from . import test_invoice_group_by_sale_order
from . import test_access_rights
84 changes: 84 additions & 0 deletions account_invoice_section_sale_order/tests/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
from odoo.tests import tagged
from odoo.tests.common import TransactionCase


@tagged("-at_install", "post_install")
class Common(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
cls.setUpClassOrder()

@classmethod
def setUpClassOrder(cls):
cls.partner_1 = cls.env.ref("base.res_partner_1")
cls.product_1 = cls.env.ref("product.product_product_1")
cls.product_2 = cls.env.ref("product.product_product_2")
cls.product_1.invoice_policy = "order"
cls.product_2.invoice_policy = "order"
cls.order1_p1 = cls.env["sale.order"].create(
{
"partner_id": cls.partner_1.id,
"partner_shipping_id": cls.partner_1.id,
"partner_invoice_id": cls.partner_1.id,
"client_order_ref": "ref123",
"order_line": [
(
0,
0,
{
"name": "order 1 line 1",
"product_id": cls.product_1.id,
"price_unit": 20,
"product_uom_qty": 1,
"product_uom": cls.product_1.uom_id.id,
},
),
(
0,
0,
{
"name": "order 1 line 2",
"product_id": cls.product_2.id,
"price_unit": 20,
"product_uom_qty": 1,
"product_uom": cls.product_1.uom_id.id,
},
),
],
}
)
cls.order1_p1.action_confirm()
cls.order2_p1 = cls.env["sale.order"].create(
{
"partner_id": cls.partner_1.id,
"partner_shipping_id": cls.partner_1.id,
"partner_invoice_id": cls.partner_1.id,
"order_line": [
(
0,
0,
{
"name": "order 2 line 1",
"product_id": cls.product_1.id,
"price_unit": 20,
"product_uom_qty": 1,
"product_uom": cls.product_1.uom_id.id,
},
),
(
0,
0,
{
"name": "order 2 line 2",
"product_id": cls.product_2.id,
"price_unit": 20,
"product_uom_qty": 1,
"product_uom": cls.product_1.uom_id.id,
},
),
],
}
)
cls.order2_p1.action_confirm()
60 changes: 60 additions & 0 deletions account_invoice_section_sale_order/tests/test_access_rights.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Copyright 2024 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

from odoo.tests import tagged

from .common import Common


@tagged("-at_install", "post_install")
class TestAccessRights(Common):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
cls.setUpClassUser()

@classmethod
def setUpClassUser(cls):
cls.create_only_group = cls.env["res.groups"].create(
{"name": "Create Only Group"}
)
cls.sale_manager_group = cls.env.ref("sales_team.group_sale_manager")
cls.env["ir.model.access"].create(
[
{
"name": "invoice_create_only",
"model_id": cls.env.ref("account.model_account_move").id,
"group_id": cls.create_only_group.id,
"perm_read": 0,
"perm_write": 0,
"perm_create": 1,
"perm_unlink": 0,
},
{
"name": "invoice_line_create_only",
"model_id": cls.env.ref("account.model_account_move_line").id,
"group_id": cls.create_only_group.id,
"perm_read": 0,
"perm_write": 0,
"perm_create": 1,
"perm_unlink": 0,
},
]
)
cls.create_only_user = cls.env["res.users"].create(
{
"name": "Create Only User",
"login": "[email protected]",
"groups_id": [
(6, 0, (cls.create_only_group | cls.sale_manager_group).ids),
],
}
)

def test_access_rights(self):
orders = self.order1_p1 + self.order2_p1
# We're testing that no exception is raised while creating invoices
# with a user having only create access on the invoices models
invoice_ids = orders.with_user(self.create_only_user)._create_invoices()
self.assertTrue(bool(invoice_ids))
Original file line number Diff line number Diff line change
Expand Up @@ -3,111 +3,16 @@
from unittest import mock

from odoo.exceptions import UserError
from odoo.tests.common import TransactionCase

from .common import Common

SECTION_GROUPING_FUNCTION = "odoo.addons.account_invoice_section_sale_order.models.account_move.AccountMoveLine._get_section_grouping" # noqa
SECTION_NAME_FUNCTION = (
"odoo.addons.base.models.res_users.Users._get_invoice_section_name"
)


class TestInvoiceGroupBySaleOrder(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.partner_1 = cls.env.ref("base.res_partner_1")
cls.product_1 = cls.env.ref("product.product_product_1")
cls.product_2 = cls.env.ref("product.product_product_2")
cls.product_1.invoice_policy = "order"
cls.product_2.invoice_policy = "order"
eur = cls.env.ref("base.EUR")
cls.pricelist = cls.env["product.pricelist"].create(
{"name": "Europe pricelist", "currency_id": eur.id}
)
cls.order1_p1 = cls.env["sale.order"].create(
{
"partner_id": cls.partner_1.id,
"partner_shipping_id": cls.partner_1.id,
"partner_invoice_id": cls.partner_1.id,
"pricelist_id": cls.pricelist.id,
"client_order_ref": "ref123",
"order_line": [
(
0,
0,
{
"name": "order 1 line 1",
"product_id": cls.product_1.id,
"price_unit": 20,
"product_uom_qty": 1,
"product_uom": cls.product_1.uom_id.id,
},
),
(
0,
0,
{
"name": "order 1 line 2",
"product_id": cls.product_2.id,
"price_unit": 20,
"product_uom_qty": 1,
"product_uom": cls.product_1.uom_id.id,
},
),
],
}
)
cls.order1_p1.action_confirm()
cls.order2_p1 = cls.env["sale.order"].create(
{
"partner_id": cls.partner_1.id,
"partner_shipping_id": cls.partner_1.id,
"partner_invoice_id": cls.partner_1.id,
"pricelist_id": cls.pricelist.id,
"order_line": [
(
0,
0,
{
"name": "order 2 section 1",
"display_type": "line_section",
},
),
(
0,
0,
{
"name": "order 2 line 1",
"product_id": cls.product_1.id,
"price_unit": 20,
"product_uom_qty": 1,
"product_uom": cls.product_1.uom_id.id,
},
),
(
0,
0,
{
"name": "order 2 section 2",
"display_type": "line_section",
},
),
(
0,
0,
{
"name": "order 2 line 2",
"product_id": cls.product_2.id,
"price_unit": 20,
"product_uom_qty": 1,
"product_uom": cls.product_1.uom_id.id,
},
),
],
}
)
cls.order2_p1.action_confirm()

class TestInvoiceGroupBySaleOrder(Common):
def test_create_invoice(self):
"""Check invoice is generated with sale order sections."""
result = {
Expand All @@ -118,10 +23,8 @@ def test_create_invoice(self):
20: ("order 1 line 1", "product"),
30: ("order 1 line 2", "product"),
40: (self.order2_p1.name, "line_section"),
50: ("- order 2 section 1", "line_section"),
60: ("order 2 line 1", "product"),
70: ("- order 2 section 2", "line_section"),
80: ("order 2 line 2", "product"),
50: ("order 2 line 1", "product"),
60: ("order 2 line 2", "product"),
}
invoice_ids = (self.order1_p1 + self.order2_p1)._create_invoices()
lines = invoice_ids[0].invoice_line_ids.sorted("sequence")
Expand All @@ -135,7 +38,7 @@ def test_create_invoice_with_currency(self):
"""Check invoice is generated with a correct total amount"""
orders = self.order1_p1 | self.order2_p1
invoices = orders._create_invoices()
self.assertEqual(invoices.amount_total, 80)
self.assertEqual(invoices.amount_untaxed, 80)

def test_create_invoice_with_default_journal(self):
"""Using a specific journal for the invoice should not be broken"""
Expand Down Expand Up @@ -197,13 +100,11 @@ def test_custom_grouping_by_sale_order_user(self):
10: ("Mocked value from ResUsers", "line_section"),
20: ("order 1 line 1", "product"),
30: ("order 1 line 2", "product"),
40: ("- order 2 section 1", "line_section"),
50: ("order 2 line 1", "product"),
60: ("- order 2 section 2", "line_section"),
70: ("order 2 line 2", "product"),
80: ("Mocked value from ResUsers", "line_section"),
90: ("order 3 line 1", "product"),
100: ("order 3 line 2", "product"),
40: ("order 2 line 1", "product"),
50: ("order 2 line 2", "product"),
60: ("Mocked value from ResUsers", "line_section"),
70: ("order 3 line 1", "product"),
80: ("order 3 line 2", "product"),
}
for line in invoice.invoice_line_ids.sorted("sequence"):
if line.sequence not in result:
Expand Down
Loading