forked from OCA/account-invoicing
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge commit 'refs/pull/1051/head' of github.com:OCA/account-invoicin…
…g into merge-branch-2879-BSGZT_180-cc5f9ce1
- Loading branch information
Showing
16 changed files
with
396 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import models |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Copyright 2021 Camptocamp SA | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) | ||
{ | ||
"name": "Acccount Invoice Section Picking", | ||
"version": "14.0.1.0.0", | ||
"summary": "Extension of Acccount Invoice Section Sale Order to allow " | ||
"grouping of invoice lines according to delivery picking.", | ||
"author": "Camptocamp, Odoo Community Association (OCA)", | ||
"website": "https://github.com/OCA/account-invoicing", | ||
"license": "AGPL-3", | ||
"category": "Accounting & Finance", | ||
"depends": ["account_invoice_section_sale_order", "stock"], | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from . import account_move_line | ||
from . import res_company | ||
from . import stock_picking |
48 changes: 48 additions & 0 deletions
48
account_invoice_section_picking/models/account_move_line.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# Copyright 2021 Camptocamp SA | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) | ||
from odoo import models | ||
|
||
|
||
class AccountMoveLine(models.Model): | ||
|
||
_inherit = "account.move.line" | ||
|
||
def _get_section_group(self): | ||
"""Group invoice lines according to uninvoiced delivery pickings""" | ||
group = super()._get_section_group() | ||
# If product is invoiced by delivered quantities: | ||
# - filter on done pickings to avoid displaying backorders not yet | ||
# processed | ||
# - Remove pickings linked with same sale order lines if an invoice | ||
# was created after its date_done | ||
invoice_section_grouping = self.company_id.invoice_section_grouping | ||
if ( | ||
invoice_section_grouping == "delivery_picking" | ||
and self.product_id.invoice_policy == "delivery" | ||
): | ||
last_invoice_line = self.search( | ||
[ | ||
("sale_line_ids", "in", self.sale_line_ids.ids), | ||
("parent_state", "!=", "cancel"), | ||
("id", "!=", self.id), | ||
], | ||
order="create_date", | ||
limit=1, | ||
) | ||
pickings_already_invoiced = self.env["stock.picking"].search( | ||
[ | ||
("date_done", "<=", last_invoice_line.create_date), | ||
("id", "in", self.sale_line_ids.mapped("order_id.picking_ids").ids), | ||
] | ||
) | ||
group = group.filtered( | ||
lambda p: p.state == "done" | ||
and p.id not in pickings_already_invoiced.ids | ||
) | ||
return group | ||
|
||
def _get_section_grouping(self): | ||
invoice_section_grouping = self.company_id.invoice_section_grouping | ||
if invoice_section_grouping == "delivery_picking": | ||
return "sale_line_ids.move_ids.picking_id" | ||
return super()._get_section_grouping() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# Copyright 2021 Camptocamp SA | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) | ||
from odoo import fields, models | ||
|
||
|
||
class ResCompany(models.Model): | ||
_inherit = "res.company" | ||
|
||
invoice_section_grouping = fields.Selection( | ||
selection_add=[("delivery_picking", "Group by delivery picking")], | ||
ondelete={"delivery_picking": "set default"}, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Copyright 2021 Camptocamp SA | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) | ||
from odoo import models | ||
from odoo.tools.safe_eval import safe_eval, time | ||
|
||
|
||
class StockPicking(models.Model): | ||
|
||
_inherit = "stock.picking" | ||
|
||
def _get_invoice_section_name(self): | ||
"""Returns the text for the section name.""" | ||
section_names = [] | ||
for pick in self: | ||
naming_scheme = ( | ||
pick.partner_id.invoice_section_name_scheme | ||
or pick.company_id.invoice_section_name_scheme | ||
) | ||
if naming_scheme: | ||
section_names.append( | ||
safe_eval(naming_scheme, {"object": pick, "time": time}) | ||
) | ||
else: | ||
section_names.append(pick.name) | ||
return ", ".join(section_names) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
* Akim Juillerat <[email protected]> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
This module extends `account_invoice_section_sale_order` to allow using pickings | ||
linked to the sale order line for the grouping invoice lines when invoicing sale | ||
orders. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
* The selection of pickings for the section name relies on the last invoice | ||
that was created and is linked to the sale order line. In such case, there's | ||
no guarantee the selection is correct if the quantity is reduced on prior | ||
invoice lines. | ||
* Moreover, as Odoo considers the draft invoices for the computation of | ||
`qty_invoiced` on sales order line, we couldn't base the selection of the last | ||
invoice on another field than the `create_date` although it would have been | ||
cleaner to rely on a `date` field, but this one is only set on the posting. | ||
Finally, defining another field for the generation of invoices wouldn't have | ||
helped solve these issues. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from . import test_account_invoice_section_picking | ||
from . import test_account_invoice_section_picking_backorder |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Copyright 2021 Camptocamp SA | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) | ||
from odoo.tests.common import Form, SavepointCase | ||
|
||
|
||
class TestAccountInvoiceSectionPickingCommon(SavepointCase): | ||
@classmethod | ||
def setUpClass(cls): | ||
super().setUpClass() | ||
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) | ||
cls.env.company.invoice_section_grouping = "delivery_picking" | ||
cls.partner_1 = cls.env.ref("base.res_partner_1") | ||
cls.product_1 = cls.env.ref("product.product_delivery_01") | ||
stock = cls.env.ref("stock.stock_location_stock") | ||
cls.env["stock.quant"]._update_available_quantity(cls.product_1, stock, 1000) | ||
cls.product_1.invoice_policy = "order" | ||
cls.order_1 = cls._create_order() | ||
cls.order_2 = cls._create_order(order_line_name=cls.product_1.name) | ||
|
||
@classmethod | ||
def _create_order(cls, order_line_name=None): | ||
order_form = Form(cls.env["sale.order"]) | ||
order_form.partner_id = cls.partner_1 | ||
with order_form: | ||
with order_form.order_line.new() as line_form: | ||
line_form.product_id = cls.product_1 | ||
line_form.product_uom_qty = 5 | ||
if order_line_name is not None: | ||
line_form.name = order_line_name | ||
return order_form.save() |
72 changes: 72 additions & 0 deletions
72
account_invoice_section_picking/tests/test_account_invoice_section_picking.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
# Copyright 2021 Camptocamp SA | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) | ||
|
||
from .common import TestAccountInvoiceSectionPickingCommon | ||
|
||
|
||
class TestAccountInvoiceSectionPicking(TestAccountInvoiceSectionPickingCommon): | ||
def test_group_by_delivery_picking(self): | ||
self.order_1.action_confirm() | ||
self.order_2.action_confirm() | ||
|
||
invoice = (self.order_1 + self.order_2)._create_invoices() | ||
self.assertEqual(len(invoice), 1) | ||
result = { | ||
10: (self.order_1.picking_ids.name, "line_section"), | ||
20: (self.order_1.order_line.name, False), | ||
30: (self.order_2.picking_ids.name, "line_section"), | ||
40: (self.order_2.order_line.name, False), | ||
} | ||
for line in invoice.invoice_line_ids.sorted("sequence"): | ||
self.assertEqual(line.name, result[line.sequence][0]) | ||
self.assertEqual(line.display_type, result[line.sequence][1]) | ||
|
||
def test_group_by_delivery_picking_multi_steps(self): | ||
warehouse = self.env.ref("stock.warehouse0") | ||
warehouse.write({"delivery_steps": "pick_pack_ship"}) | ||
|
||
self.order_1.action_confirm() | ||
self.order_2.action_confirm() | ||
|
||
invoice = (self.order_1 + self.order_2)._create_invoices() | ||
self.assertEqual(len(invoice), 1) | ||
result = { | ||
10: (self.order_1.order_line.move_ids.picking_id.name, "line_section"), | ||
20: (self.order_1.order_line.name, False), | ||
30: (self.order_2.order_line.move_ids.picking_id.name, "line_section"), | ||
40: (self.order_2.order_line.name, False), | ||
} | ||
for line in invoice.invoice_line_ids.sorted("sequence"): | ||
self.assertEqual(line.name, result[line.sequence][0]) | ||
self.assertEqual(line.display_type, result[line.sequence][1]) | ||
|
||
def test_group_by_delivery_picking_backorder(self): | ||
self.order_1.action_confirm() | ||
self.order_2.action_confirm() | ||
|
||
delivery_1_move = self.order_1.order_line.move_ids | ||
delivery_1_move.move_line_ids.qty_done = 2.0 | ||
delivery_1 = delivery_1_move.picking_id | ||
backorder_wiz_action = delivery_1.button_validate() | ||
backorder_wiz = ( | ||
self.env["stock.backorder.confirmation"] | ||
.with_context(**backorder_wiz_action.get("context")) | ||
.create({}) | ||
) | ||
backorder_wiz.process() | ||
delivery_1_backorder_move = self.order_1.order_line.move_ids - delivery_1_move | ||
delivery_1_backorder = delivery_1_backorder_move.picking_id | ||
delivery_2 = self.order_2.order_line.move_ids.picking_id | ||
invoice = (self.order_1 + self.order_2)._create_invoices() | ||
result = { | ||
10: ( | ||
", ".join([delivery_1.name, delivery_1_backorder.name]), | ||
"line_section", | ||
), | ||
20: (self.order_1.order_line.name, False), | ||
30: (delivery_2.name, "line_section"), | ||
40: (self.order_2.order_line.name, False), | ||
} | ||
for line in invoice.invoice_line_ids.sorted("sequence"): | ||
self.assertEqual(line.name, result[line.sequence][0]) | ||
self.assertEqual(line.display_type, result[line.sequence][1]) |
Oops, something went wrong.