From d3ecf5463727a180c31dcbb77abf1fe6ed275931 Mon Sep 17 00:00:00 2001
From: Mmequignon <matthieu@fwzte.xyz>
Date: Fri, 9 Aug 2024 12:38:50 +0200
Subject: [PATCH 01/32] account_invoice_section_sale_order: Fix read/write
 access

the `sale.order._create_invoices() method does not only requires
`create` access to the `account.move` and `account.move.line` models.

Because we're actually sorting lines after the creating, it requires
`read` access to sort, and `write` access to modify their sequence.

This is problematic when interracting with other modules like
`invoice_mode_at_shipping` where stock users are the ones to create
invoices.

This commit adds a few `sudo()` in the code, in order to avoid granting
`read` and `write` access to users that shouldn't be allowed to read and write invoices.
---
 .../models/sale_order.py                      |  20 ++-
 .../tests/common.py                           |  84 ++++++++++++
 .../tests/test_access_rights.py               |  60 +++++++++
 .../tests/test_invoice_group_by_sale_order.py | 127 ++----------------
 4 files changed, 167 insertions(+), 124 deletions(-)
 create mode 100644 account_invoice_section_sale_order/tests/common.py
 create mode 100644 account_invoice_section_sale_order/tests/test_access_rights.py

diff --git a/account_invoice_section_sale_order/models/sale_order.py b/account_invoice_section_sale_order/models/sale_order.py
index 5965efcf8c7..5180873ee56 100644
--- a/account_invoice_section_sale_order/models/sale_order.py
+++ b/account_invoice_section_sale_order/models/sale_order.py
@@ -16,8 +16,8 @@ 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:
+        invoices = super()._create_invoices(grouped=grouped, final=final, date=date)
+        for invoice in invoices.sudo():
             if (
                 not invoice.company_id.always_create_invoice_section
                 and len(
@@ -27,6 +27,8 @@ def _create_invoices(self, grouped=False, final=False, date=None):
             ):
                 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()
@@ -59,18 +61,14 @@ 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}"
+                    # 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."""
diff --git a/account_invoice_section_sale_order/tests/common.py b/account_invoice_section_sale_order/tests/common.py
new file mode 100644
index 00000000000..24991186231
--- /dev/null
+++ b/account_invoice_section_sale_order/tests/common.py
@@ -0,0 +1,84 @@
+from odoo.tests import tagged
+from odoo.tests.common import SavepointCase
+
+
+@tagged("-at_install", "post_install")
+class Common(SavepointCase):
+    @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()
diff --git a/account_invoice_section_sale_order/tests/test_access_rights.py b/account_invoice_section_sale_order/tests/test_access_rights.py
new file mode 100644
index 00000000000..f1afd39d1f1
--- /dev/null
+++ b/account_invoice_section_sale_order/tests/test_access_rights.py
@@ -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": "createonlyuser@example.com",
+                "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))
diff --git a/account_invoice_section_sale_order/tests/test_invoice_group_by_sale_order.py b/account_invoice_section_sale_order/tests/test_invoice_group_by_sale_order.py
index 3ee311371e4..f8aa73816cf 100644
--- a/account_invoice_section_sale_order/tests/test_invoice_group_by_sale_order.py
+++ b/account_invoice_section_sale_order/tests/test_invoice_group_by_sale_order.py
@@ -3,7 +3,8 @@
 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 = (
@@ -11,103 +12,7 @@
 )
 
 
-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 = {
@@ -115,13 +20,11 @@ def test_create_invoice(self):
                 "".join([self.order1_p1.name, " - ", self.order1_p1.client_order_ref]),
                 "line_section",
             ),
-            20: ("order 1 line 1", "product"),
-            30: ("order 1 line 2", "product"),
+            20: ("order 1 line 1", False),
+            30: ("order 1 line 2", False),
             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", False),
+            60: ("order 2 line 2", False),
         }
         invoice_ids = (self.order1_p1 + self.order2_p1)._create_invoices()
         lines = invoice_ids[0].invoice_line_ids.sorted("sequence")
@@ -195,15 +98,13 @@ def test_custom_grouping_by_sale_order_user(self):
             invoice = (orders + sale_order_3)._create_invoices()
             result = {
                 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"),
+                20: ("order 1 line 1", False),
+                30: ("order 1 line 2", False),
+                40: ("order 2 line 1", False),
+                50: ("order 2 line 2", False),
+                60: ("Mocked value from ResUsers", "line_section"),
+                70: ("order 3 line 1", False),
+                80: ("order 3 line 2", False),
             }
             for line in invoice.invoice_line_ids.sorted("sequence"):
                 if line.sequence not in result:

From 36d8c17ab70c2c1d7d2db543b4dfce9c499fb1be Mon Sep 17 00:00:00 2001
From: Simone Orsi <simahawk@gmail.com>
Date: Mon, 9 Dec 2024 11:48:25 +0100
Subject: [PATCH 02/32] account_invoice_section_sale_order: fix access right
 tests not running

---
 account_invoice_section_sale_order/tests/__init__.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/account_invoice_section_sale_order/tests/__init__.py b/account_invoice_section_sale_order/tests/__init__.py
index 20dcf91002a..ca02ec06eca 100644
--- a/account_invoice_section_sale_order/tests/__init__.py
+++ b/account_invoice_section_sale_order/tests/__init__.py
@@ -1 +1,2 @@
 from . import test_invoice_group_by_sale_order
+from . import test_access_rights

From 3128497ce92207da014768af26762089096bfc6c Mon Sep 17 00:00:00 2001
From: Simone Orsi <simahawk@gmail.com>
Date: Mon, 9 Dec 2024 11:48:54 +0100
Subject: [PATCH 03/32] account_invoice_section_sale_order: fix access right on
 move line write

---
 account_invoice_section_sale_order/models/sale_order.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/account_invoice_section_sale_order/models/sale_order.py b/account_invoice_section_sale_order/models/sale_order.py
index 5180873ee56..96bcdb420b3 100644
--- a/account_invoice_section_sale_order/models/sale_order.py
+++ b/account_invoice_section_sale_order/models/sale_order.py
@@ -60,7 +60,9 @@ 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):
+                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

From d3d08a5e128ca5e3607a898680827de18caaead3 Mon Sep 17 00:00:00 2001
From: sergiocorato <sergiocorato@gmail.com>
Date: Thu, 1 Aug 2024 10:06:42 +0200
Subject: [PATCH 04/32] [FIX] account_invoice_section_sale_order check line_ids
 exists

---
 account_invoice_section_sale_order/models/sale_order.py | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/account_invoice_section_sale_order/models/sale_order.py b/account_invoice_section_sale_order/models/sale_order.py
index 96bcdb420b3..ea215455284 100644
--- a/account_invoice_section_sale_order/models/sale_order.py
+++ b/account_invoice_section_sale_order/models/sale_order.py
@@ -18,11 +18,8 @@ def _create_invoices(self, grouped=False, final=False, date=None):
         """
         invoices = super()._create_invoices(grouped=grouped, final=final, date=date)
         for invoice in invoices.sudo():
-            if (
-                not invoice.company_id.always_create_invoice_section
-                and len(
-                    invoice.line_ids.mapped(invoice.line_ids._get_section_grouping())
-                )
+            if invoice.line_ids and (
+                len(invoice.line_ids.mapped(invoice.line_ids._get_section_grouping()))
                 == 1
             ):
                 continue

From a599acbfa3b9fcd3d1c938494f7329e6d917df3e Mon Sep 17 00:00:00 2001
From: Lukas Tran <nhant@trobz.com>
Date: Tue, 31 Dec 2024 16:50:54 +0700
Subject: [PATCH 05/32] [FIX] account_invoice_section_sale_order: fix test-case
 test_create_invoice_with_currency

---
 .../tests/common.py                           |  4 ++--
 .../tests/test_invoice_group_by_sale_order.py | 20 +++++++++----------
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/account_invoice_section_sale_order/tests/common.py b/account_invoice_section_sale_order/tests/common.py
index 24991186231..a8d3a372275 100644
--- a/account_invoice_section_sale_order/tests/common.py
+++ b/account_invoice_section_sale_order/tests/common.py
@@ -1,9 +1,9 @@
 from odoo.tests import tagged
-from odoo.tests.common import SavepointCase
+from odoo.tests.common import TransactionCase
 
 
 @tagged("-at_install", "post_install")
-class Common(SavepointCase):
+class Common(TransactionCase):
     @classmethod
     def setUpClass(cls):
         super().setUpClass()
diff --git a/account_invoice_section_sale_order/tests/test_invoice_group_by_sale_order.py b/account_invoice_section_sale_order/tests/test_invoice_group_by_sale_order.py
index f8aa73816cf..2a3369cdb60 100644
--- a/account_invoice_section_sale_order/tests/test_invoice_group_by_sale_order.py
+++ b/account_invoice_section_sale_order/tests/test_invoice_group_by_sale_order.py
@@ -20,11 +20,11 @@ def test_create_invoice(self):
                 "".join([self.order1_p1.name, " - ", self.order1_p1.client_order_ref]),
                 "line_section",
             ),
-            20: ("order 1 line 1", False),
-            30: ("order 1 line 2", False),
+            20: ("order 1 line 1", "product"),
+            30: ("order 1 line 2", "product"),
             40: (self.order2_p1.name, "line_section"),
-            50: ("order 2 line 1", False),
-            60: ("order 2 line 2", False),
+            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")
@@ -98,13 +98,13 @@ def test_custom_grouping_by_sale_order_user(self):
             invoice = (orders + sale_order_3)._create_invoices()
             result = {
                 10: ("Mocked value from ResUsers", "line_section"),
-                20: ("order 1 line 1", False),
-                30: ("order 1 line 2", False),
-                40: ("order 2 line 1", False),
-                50: ("order 2 line 2", False),
+                20: ("order 1 line 1", "product"),
+                30: ("order 1 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", False),
-                80: ("order 3 line 2", False),
+                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:

From 2f79521946bc12cb66f7c982f6457325bc9ebd42 Mon Sep 17 00:00:00 2001
From: Thierry Ducrest <thierry@ducrest.net>
Date: Tue, 27 Sep 2022 15:12:33 +0200
Subject: [PATCH 06/32] [MIG] rename account_invoice_mode_at_shipping

---
 partner_invoicing_mode_at_shipping/README.rst |   0
 .../__init__.py                               |   2 +
 .../__manifest__.py                           |  15 +
 .../data/queue_job_data.xml                   |  15 +
 .../models/__init__.py                        |   3 +
 .../models/res_partner.py                     |  13 +
 .../models/stock_move.py                      |  19 +
 .../models/stock_picking.py                   |  49 ++
 .../readme/CONTRIBUTORS.rst                   |   5 +
 .../readme/CREDITS.rst                        |   3 +
 .../readme/DESCRIPTION.rst                    |   4 +
 .../static/description/icon.png               | Bin 0 -> 9455 bytes
 .../static/description/index.html             | 438 ++++++++++++++++++
 .../tests/__init__.py                         |   1 +
 .../tests/test_invoice_mode_at_shipping.py    |  57 +++
 15 files changed, 624 insertions(+)
 create mode 100644 partner_invoicing_mode_at_shipping/README.rst
 create mode 100644 partner_invoicing_mode_at_shipping/__init__.py
 create mode 100644 partner_invoicing_mode_at_shipping/__manifest__.py
 create mode 100644 partner_invoicing_mode_at_shipping/data/queue_job_data.xml
 create mode 100644 partner_invoicing_mode_at_shipping/models/__init__.py
 create mode 100644 partner_invoicing_mode_at_shipping/models/res_partner.py
 create mode 100644 partner_invoicing_mode_at_shipping/models/stock_move.py
 create mode 100644 partner_invoicing_mode_at_shipping/models/stock_picking.py
 create mode 100644 partner_invoicing_mode_at_shipping/readme/CONTRIBUTORS.rst
 create mode 100644 partner_invoicing_mode_at_shipping/readme/CREDITS.rst
 create mode 100644 partner_invoicing_mode_at_shipping/readme/DESCRIPTION.rst
 create mode 100644 partner_invoicing_mode_at_shipping/static/description/icon.png
 create mode 100644 partner_invoicing_mode_at_shipping/static/description/index.html
 create mode 100644 partner_invoicing_mode_at_shipping/tests/__init__.py
 create mode 100644 partner_invoicing_mode_at_shipping/tests/test_invoice_mode_at_shipping.py

diff --git a/partner_invoicing_mode_at_shipping/README.rst b/partner_invoicing_mode_at_shipping/README.rst
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/partner_invoicing_mode_at_shipping/__init__.py b/partner_invoicing_mode_at_shipping/__init__.py
new file mode 100644
index 00000000000..0ee8b5073e2
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/__init__.py
@@ -0,0 +1,2 @@
+from . import models
+from . import tests
diff --git a/partner_invoicing_mode_at_shipping/__manifest__.py b/partner_invoicing_mode_at_shipping/__manifest__.py
new file mode 100644
index 00000000000..7815728e342
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/__manifest__.py
@@ -0,0 +1,15 @@
+# Copyright 2020 Camptocamp
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+{
+    "name": "Partner Invoicing Mode At Shipping",
+    "version": "15.0.1.0.0",
+    "summary": "Create invoices automatically when goods are shipped.",
+    "author": "Camptocamp, Odoo Community Association (OCA)",
+    "website": "https://github.com/OCA/account-invoicing",
+    "license": "AGPL-3",
+    "category": "Accounting & Finance",
+    "data": [
+        "data/queue_job_data.xml",
+    ],
+    "depends": ["account", "partner_invoicing_mode", "queue_job", "stock"],
+}
diff --git a/partner_invoicing_mode_at_shipping/data/queue_job_data.xml b/partner_invoicing_mode_at_shipping/data/queue_job_data.xml
new file mode 100644
index 00000000000..b5f70b53f5c
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/data/queue_job_data.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+    <!-- Queue Job Channel -->
+    <record id="invoice_at_shipping" model="queue.job.channel">
+        <field name="name">invoice_at_shipping</field>
+        <field name="parent_id" ref="queue_job.channel_root" />
+    </record>
+
+    <!-- Job Functions -->
+    <record id="job_function_invoicing_at_shipping" model="queue.job.function">
+        <field name="model_id" ref="stock.model_stock_picking" />
+        <field name="method">_invoicing_at_shipping</field>
+        <field name="channel_id" ref="invoice_at_shipping" />
+    </record>
+</odoo>
diff --git a/partner_invoicing_mode_at_shipping/models/__init__.py b/partner_invoicing_mode_at_shipping/models/__init__.py
new file mode 100644
index 00000000000..b87ddbd73f5
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/models/__init__.py
@@ -0,0 +1,3 @@
+from . import res_partner
+from . import stock_move
+from . import stock_picking
diff --git a/partner_invoicing_mode_at_shipping/models/res_partner.py b/partner_invoicing_mode_at_shipping/models/res_partner.py
new file mode 100644
index 00000000000..f9a1327e249
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/models/res_partner.py
@@ -0,0 +1,13 @@
+# Copyright 2020 Camptocamp SA
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
+
+from odoo import fields, models
+
+
+class ResPartner(models.Model):
+    _inherit = "res.partner"
+
+    invoicing_mode = fields.Selection(
+        selection_add=[("at_shipping", "At Shipping")],
+        ondelete={"at_shipping": "set default"},
+    )
diff --git a/partner_invoicing_mode_at_shipping/models/stock_move.py b/partner_invoicing_mode_at_shipping/models/stock_move.py
new file mode 100644
index 00000000000..3870a990091
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/models/stock_move.py
@@ -0,0 +1,19 @@
+# Copyright 2020 Camptocamp SA
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
+
+from odoo import models
+
+
+class StockMove(models.Model):
+    _inherit = "stock.move"
+
+    def _get_related_invoices(self):
+        """Overridden from stock_account to return the customer invoices
+        related to this stock move.
+        """
+        invoices = super()._get_related_invoices()
+        line_invoices = self.mapped("sale_line_id.order_id.invoice_ids").filtered(
+            lambda x: x.state == "posted"
+        )
+        invoices |= line_invoices
+        return invoices
diff --git a/partner_invoicing_mode_at_shipping/models/stock_picking.py b/partner_invoicing_mode_at_shipping/models/stock_picking.py
new file mode 100644
index 00000000000..1dd7e24ac40
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/models/stock_picking.py
@@ -0,0 +1,49 @@
+# Copyright 2020 Camptocamp SA
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
+
+from odoo import _, models
+
+
+class StockPicking(models.Model):
+    _inherit = "stock.picking"
+
+    def _action_done(self):
+        res = super()._action_done()
+        for picking in self:
+            if picking._invoice_at_shipping():
+                picking.with_delay()._invoicing_at_shipping()
+        return res
+
+    def _invoice_at_shipping(self):
+        """Check if picking must be invoiced at shipping."""
+        self.ensure_one()
+        return (
+            self.picking_type_code == "outgoing"
+            and self.sale_id.partner_invoice_id.invoicing_mode == "at_shipping"
+        )
+
+    def _invoicing_at_shipping(self):
+        self.ensure_one()
+        sales = self.env["sale.order"].browse()
+        # Filter out non invoicable sales order
+        for sale in self._get_sales_order_to_invoice():
+            if sale._get_invoiceable_lines():
+                sales |= sale
+        # Split invoice creation on partner sales grouping on invoice settings
+        sales_one_invoice_per_order = sales.filtered(
+            "partner_invoice_id.one_invoice_per_order"
+        )
+        invoices = self.env["account.move"].browse()
+        if sales_one_invoice_per_order:
+            invoices |= sales_one_invoice_per_order._create_invoices(grouped=True)
+        sales_many_invoice_per_order = sales - sales_one_invoice_per_order
+        if sales_many_invoice_per_order:
+            invoices |= sales_many_invoice_per_order._create_invoices(grouped=False)
+        for invoice in invoices:
+            invoice.with_delay()._validate_invoice()
+        return invoices or _("Nothing to invoice.")
+
+    def _get_sales_order_to_invoice(self):
+        return self.mapped("move_lines.sale_line_id.order_id").filtered(
+            lambda r: r._get_invoiceable_lines()
+        )
diff --git a/partner_invoicing_mode_at_shipping/readme/CONTRIBUTORS.rst b/partner_invoicing_mode_at_shipping/readme/CONTRIBUTORS.rst
new file mode 100644
index 00000000000..ecddfcde7f4
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/readme/CONTRIBUTORS.rst
@@ -0,0 +1,5 @@
+* `Camptocamp <https://www.camptocamp.com>`_:
+
+    * Thierry Ducrest <thierry.ducrest@camptocamp.com>
+
+* Phuc (Tran Thanh) <phuc@trobz.com>
diff --git a/partner_invoicing_mode_at_shipping/readme/CREDITS.rst b/partner_invoicing_mode_at_shipping/readme/CREDITS.rst
new file mode 100644
index 00000000000..f5cc070c78e
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/readme/CREDITS.rst
@@ -0,0 +1,3 @@
+The development of this module has been financially supported by:
+
+* Camptocamp
diff --git a/partner_invoicing_mode_at_shipping/readme/DESCRIPTION.rst b/partner_invoicing_mode_at_shipping/readme/DESCRIPTION.rst
new file mode 100644
index 00000000000..9a3d5a02e2d
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/readme/DESCRIPTION.rst
@@ -0,0 +1,4 @@
+This module allows to select a `At shipping` invoicing mode for a customer.
+It is based on `partner_invoicing_mode`.
+When this mode is selected the customer will be invoiced automatically on
+delivery of the goods.
diff --git a/partner_invoicing_mode_at_shipping/static/description/icon.png b/partner_invoicing_mode_at_shipping/static/description/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d
GIT binary patch
literal 9455
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
Xviia!U7SGha1wx#SCgwmn*{w2TRX*I

literal 0
HcmV?d00001

diff --git a/partner_invoicing_mode_at_shipping/static/description/index.html b/partner_invoicing_mode_at_shipping/static/description/index.html
new file mode 100644
index 00000000000..e5585743373
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/static/description/index.html
@@ -0,0 +1,438 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.15.1: http://docutils.sourceforge.net/" />
+<title>Account Invoice Mode At Shipping</title>
+<style type="text/css">
+
+/*
+:Author: David Goodger (goodger@python.org)
+:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
+:Copyright: This stylesheet has been placed in the public domain.
+
+Default cascading style sheet for the HTML output of Docutils.
+
+See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
+customize this style sheet.
+*/
+
+/* used to remove borders from tables and images */
+.borderless, table.borderless td, table.borderless th {
+  border: 0 }
+
+table.borderless td, table.borderless th {
+  /* Override padding for "table.docutils td" with "! important".
+     The right padding separates the table cells. */
+  padding: 0 0.5em 0 0 ! important }
+
+.first {
+  /* Override more specific margin styles with "! important". */
+  margin-top: 0 ! important }
+
+.last, .with-subtitle {
+  margin-bottom: 0 ! important }
+
+.hidden {
+  display: none }
+
+.subscript {
+  vertical-align: sub;
+  font-size: smaller }
+
+.superscript {
+  vertical-align: super;
+  font-size: smaller }
+
+a.toc-backref {
+  text-decoration: none ;
+  color: black }
+
+blockquote.epigraph {
+  margin: 2em 5em ; }
+
+dl.docutils dd {
+  margin-bottom: 0.5em }
+
+object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
+  overflow: hidden;
+}
+
+/* Uncomment (and remove this text!) to get bold-faced definition list terms
+dl.docutils dt {
+  font-weight: bold }
+*/
+
+div.abstract {
+  margin: 2em 5em }
+
+div.abstract p.topic-title {
+  font-weight: bold ;
+  text-align: center }
+
+div.admonition, div.attention, div.caution, div.danger, div.error,
+div.hint, div.important, div.note, div.tip, div.warning {
+  margin: 2em ;
+  border: medium outset ;
+  padding: 1em }
+
+div.admonition p.admonition-title, div.hint p.admonition-title,
+div.important p.admonition-title, div.note p.admonition-title,
+div.tip p.admonition-title {
+  font-weight: bold ;
+  font-family: sans-serif }
+
+div.attention p.admonition-title, div.caution p.admonition-title,
+div.danger p.admonition-title, div.error p.admonition-title,
+div.warning p.admonition-title, .code .error {
+  color: red ;
+  font-weight: bold ;
+  font-family: sans-serif }
+
+/* Uncomment (and remove this text!) to get reduced vertical space in
+   compound paragraphs.
+div.compound .compound-first, div.compound .compound-middle {
+  margin-bottom: 0.5em }
+
+div.compound .compound-last, div.compound .compound-middle {
+  margin-top: 0.5em }
+*/
+
+div.dedication {
+  margin: 2em 5em ;
+  text-align: center ;
+  font-style: italic }
+
+div.dedication p.topic-title {
+  font-weight: bold ;
+  font-style: normal }
+
+div.figure {
+  margin-left: 2em ;
+  margin-right: 2em }
+
+div.footer, div.header {
+  clear: both;
+  font-size: smaller }
+
+div.line-block {
+  display: block ;
+  margin-top: 1em ;
+  margin-bottom: 1em }
+
+div.line-block div.line-block {
+  margin-top: 0 ;
+  margin-bottom: 0 ;
+  margin-left: 1.5em }
+
+div.sidebar {
+  margin: 0 0 0.5em 1em ;
+  border: medium outset ;
+  padding: 1em ;
+  background-color: #ffffee ;
+  width: 40% ;
+  float: right ;
+  clear: right }
+
+div.sidebar p.rubric {
+  font-family: sans-serif ;
+  font-size: medium }
+
+div.system-messages {
+  margin: 5em }
+
+div.system-messages h1 {
+  color: red }
+
+div.system-message {
+  border: medium outset ;
+  padding: 1em }
+
+div.system-message p.system-message-title {
+  color: red ;
+  font-weight: bold }
+
+div.topic {
+  margin: 2em }
+
+h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
+h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
+  margin-top: 0.4em }
+
+h1.title {
+  text-align: center }
+
+h2.subtitle {
+  text-align: center }
+
+hr.docutils {
+  width: 75% }
+
+img.align-left, .figure.align-left, object.align-left, table.align-left {
+  clear: left ;
+  float: left ;
+  margin-right: 1em }
+
+img.align-right, .figure.align-right, object.align-right, table.align-right {
+  clear: right ;
+  float: right ;
+  margin-left: 1em }
+
+img.align-center, .figure.align-center, object.align-center {
+  display: block;
+  margin-left: auto;
+  margin-right: auto;
+}
+
+table.align-center {
+  margin-left: auto;
+  margin-right: auto;
+}
+
+.align-left {
+  text-align: left }
+
+.align-center {
+  clear: both ;
+  text-align: center }
+
+.align-right {
+  text-align: right }
+
+/* reset inner alignment in figures */
+div.align-right {
+  text-align: inherit }
+
+/* div.align-center * { */
+/*   text-align: left } */
+
+.align-top    {
+  vertical-align: top }
+
+.align-middle {
+  vertical-align: middle }
+
+.align-bottom {
+  vertical-align: bottom }
+
+ol.simple, ul.simple {
+  margin-bottom: 1em }
+
+ol.arabic {
+  list-style: decimal }
+
+ol.loweralpha {
+  list-style: lower-alpha }
+
+ol.upperalpha {
+  list-style: upper-alpha }
+
+ol.lowerroman {
+  list-style: lower-roman }
+
+ol.upperroman {
+  list-style: upper-roman }
+
+p.attribution {
+  text-align: right ;
+  margin-left: 50% }
+
+p.caption {
+  font-style: italic }
+
+p.credits {
+  font-style: italic ;
+  font-size: smaller }
+
+p.label {
+  white-space: nowrap }
+
+p.rubric {
+  font-weight: bold ;
+  font-size: larger ;
+  color: maroon ;
+  text-align: center }
+
+p.sidebar-title {
+  font-family: sans-serif ;
+  font-weight: bold ;
+  font-size: larger }
+
+p.sidebar-subtitle {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+p.topic-title {
+  font-weight: bold }
+
+pre.address {
+  margin-bottom: 0 ;
+  margin-top: 0 ;
+  font: inherit }
+
+pre.literal-block, pre.doctest-block, pre.math, pre.code {
+  margin-left: 2em ;
+  margin-right: 2em }
+
+pre.code .ln { color: grey; } /* line numbers */
+pre.code, code { background-color: #eeeeee }
+pre.code .comment, code .comment { color: #5C6576 }
+pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
+pre.code .literal.string, code .literal.string { color: #0C5404 }
+pre.code .name.builtin, code .name.builtin { color: #352B84 }
+pre.code .deleted, code .deleted { background-color: #DEB0A1}
+pre.code .inserted, code .inserted { background-color: #A3D289}
+
+span.classifier {
+  font-family: sans-serif ;
+  font-style: oblique }
+
+span.classifier-delimiter {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+span.interpreted {
+  font-family: sans-serif }
+
+span.option {
+  white-space: nowrap }
+
+span.pre {
+  white-space: pre }
+
+span.problematic {
+  color: red }
+
+span.section-subtitle {
+  /* font-size relative to parent (h1..h6 element) */
+  font-size: 80% }
+
+table.citation {
+  border-left: solid 1px gray;
+  margin-left: 1px }
+
+table.docinfo {
+  margin: 2em 4em }
+
+table.docutils {
+  margin-top: 0.5em ;
+  margin-bottom: 0.5em }
+
+table.footnote {
+  border-left: solid 1px black;
+  margin-left: 1px }
+
+table.docutils td, table.docutils th,
+table.docinfo td, table.docinfo th {
+  padding-left: 0.5em ;
+  padding-right: 0.5em ;
+  vertical-align: top }
+
+table.docutils th.field-name, table.docinfo th.docinfo-name {
+  font-weight: bold ;
+  text-align: left ;
+  white-space: nowrap ;
+  padding-left: 0 }
+
+/* "booktabs" style (no vertical lines) */
+table.docutils.booktabs {
+  border: 0px;
+  border-top: 2px solid;
+  border-bottom: 2px solid;
+  border-collapse: collapse;
+}
+table.docutils.booktabs * {
+  border: 0px;
+}
+table.docutils.booktabs th {
+  border-bottom: thin solid;
+  text-align: left;
+}
+
+h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
+h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
+  font-size: 100% }
+
+ul.auto-toc {
+  list-style-type: none }
+
+</style>
+</head>
+<body>
+<div class="document" id="account-invoice-mode-at-shipping">
+<h1 class="title">Account Invoice Mode At Shipping</h1>
+
+<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!! This file is generated by oca-gen-addon-readme !!
+!! changes will be overwritten.                   !!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
+<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/account-invoicing/tree/14.0/account_invoice_mode_at_shipping"><img alt="OCA/account-invoicing" src="https://img.shields.io/badge/github-OCA%2Faccount--invoicing-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/account-invoicing-14-0/account-invoicing-14-0-account_invoice_mode_at_shipping"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/95/14.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
+<p>This module allows to select a <cite>At shipping</cite> invoicing mode for a customer.
+It is based on <cite>account_invoice_base_invoicing_mode</cite>.
+When this mode is selected the customer will be invoiced automatically on
+delivery of the goods.</p>
+<p><strong>Table of contents</strong></p>
+<div class="contents local topic" id="contents">
+<ul class="simple">
+<li><a class="reference internal" href="#bug-tracker" id="id1">Bug Tracker</a></li>
+<li><a class="reference internal" href="#credits" id="id2">Credits</a><ul>
+<li><a class="reference internal" href="#authors" id="id3">Authors</a></li>
+<li><a class="reference internal" href="#contributors" id="id4">Contributors</a></li>
+<li><a class="reference internal" href="#other-credits" id="id5">Other credits</a></li>
+<li><a class="reference internal" href="#maintainers" id="id6">Maintainers</a></li>
+</ul>
+</li>
+</ul>
+</div>
+<div class="section" id="bug-tracker">
+<h1><a class="toc-backref" href="#id1">Bug Tracker</a></h1>
+<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/account-invoicing/issues">GitHub Issues</a>.
+In case of trouble, please check there if your issue has already been reported.
+If you spotted it first, help us smashing it by providing a detailed and welcomed
+<a class="reference external" href="https://github.com/OCA/account-invoicing/issues/new?body=module:%20account_invoice_mode_at_shipping%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
+<p>Do not contact contributors directly about support or help with technical issues.</p>
+</div>
+<div class="section" id="credits">
+<h1><a class="toc-backref" href="#id2">Credits</a></h1>
+<div class="section" id="authors">
+<h2><a class="toc-backref" href="#id3">Authors</a></h2>
+<ul class="simple">
+<li>Camptocamp</li>
+</ul>
+</div>
+<div class="section" id="contributors">
+<h2><a class="toc-backref" href="#id4">Contributors</a></h2>
+<ul>
+<li><p class="first"><a class="reference external" href="https://www.camptocamp.com">Camptocamp</a>:</p>
+<blockquote>
+<ul class="simple">
+<li>Thierry Ducrest &lt;<a class="reference external" href="mailto:thierry.ducrest&#64;camptocamp.com">thierry.ducrest&#64;camptocamp.com</a>&gt;</li>
+</ul>
+</blockquote>
+</li>
+<li><p class="first">Phuc (Tran Thanh) &lt;<a class="reference external" href="mailto:phuc&#64;trobz.com">phuc&#64;trobz.com</a>&gt;</p>
+</li>
+</ul>
+</div>
+<div class="section" id="other-credits">
+<h2><a class="toc-backref" href="#id5">Other credits</a></h2>
+<p>The development of this module has been financially supported by:</p>
+<ul class="simple">
+<li>Camptocamp</li>
+</ul>
+</div>
+<div class="section" id="maintainers">
+<h2><a class="toc-backref" href="#id6">Maintainers</a></h2>
+<p>This module is maintained by the OCA.</p>
+<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
+<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
+mission is to support the collaborative development of Odoo features and
+promote its widespread use.</p>
+<p>This module is part of the <a class="reference external" href="https://github.com/OCA/account-invoicing/tree/14.0/account_invoice_mode_at_shipping">OCA/account-invoicing</a> project on GitHub.</p>
+<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
+</div>
+</div>
+</div>
+</body>
+</html>
diff --git a/partner_invoicing_mode_at_shipping/tests/__init__.py b/partner_invoicing_mode_at_shipping/tests/__init__.py
new file mode 100644
index 00000000000..094b649436f
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/tests/__init__.py
@@ -0,0 +1 @@
+from . import test_invoice_mode_at_shipping
diff --git a/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_at_shipping.py b/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_at_shipping.py
new file mode 100644
index 00000000000..2caccae74f8
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_at_shipping.py
@@ -0,0 +1,57 @@
+# Copyright 2020 Camptocamp SA
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
+
+from odoo.tests.common import TransactionCase
+
+
+class TestInvoiceModeAtShipping(TransactionCase):
+    @classmethod
+    def setUpClass(cls):
+        super().setUpClass()
+        cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
+        cls.partner = cls.env.ref("base.res_partner_1")
+        cls.product = cls.env.ref("product.product_delivery_01")
+        cls.so1 = cls.env["sale.order"].create(
+            {
+                "partner_id": cls.partner.id,
+                "partner_invoice_id": cls.partner.id,
+                "partner_shipping_id": cls.partner.id,
+                "order_line": [
+                    (
+                        0,
+                        0,
+                        {
+                            "name": "Line one",
+                            "product_id": cls.product.id,
+                            "product_uom_qty": 4,
+                            "product_uom": cls.product.uom_id.id,
+                            "price_unit": 123,
+                        },
+                    )
+                ],
+                "pricelist_id": cls.env.ref("product.list0").id,
+            }
+        )
+
+    def test_invoice_created_at_shipping(self):
+        """Check that an invoice is created when goods are shipped."""
+        self.partner.invoicing_mode = "at_shipping"
+        self.so1.action_confirm()
+        for picking in self.so1.picking_ids:
+            for line in picking.move_lines:
+                line.quantity_done = line.product_uom_qty
+                picking.action_assign()
+                picking.with_context(test_queue_job_no_delay=True).button_validate()
+        self.assertEqual(len(self.so1.invoice_ids), 1)
+        self.assertEqual(self.so1.invoice_ids.state, "posted")
+
+    def test_invoice_not_created_at_shipping(self):
+        """Check that an invoice is not created when goods are shipped."""
+        self.partner.invoicing_mode = "standard"
+        self.so1.action_confirm()
+        for picking in self.so1.picking_ids:
+            for line in picking.move_lines:
+                line.quantity_done = line.product_uom_qty
+            picking.action_assign()
+            picking.button_validate()
+        self.assertEqual(len(self.so1.invoice_ids), 0)

From c00529fb10ef981a820727de4b5cc47392644b08 Mon Sep 17 00:00:00 2001
From: Stefan Rijnhart <stefan@opener.am>
Date: Wed, 30 Nov 2022 18:08:02 +0100
Subject: [PATCH 07/32] [MIG] partner_invoicing_mode_at_shipping: Migration to
 16.0

---
 partner_invoicing_mode_at_shipping/README.rst | 87 +++++++++++++++++++
 .../__init__.py                               |  1 -
 .../__manifest__.py                           |  2 +-
 .../models/stock_move.py                      |  2 +-
 .../models/stock_picking.py                   | 10 +--
 .../static/description/index.html             | 16 ++--
 .../tests/test_invoice_mode_at_shipping.py    | 81 +++++++++++++++--
 7 files changed, 175 insertions(+), 24 deletions(-)

diff --git a/partner_invoicing_mode_at_shipping/README.rst b/partner_invoicing_mode_at_shipping/README.rst
index e69de29bb2d..94f493a81d1 100644
--- a/partner_invoicing_mode_at_shipping/README.rst
+++ b/partner_invoicing_mode_at_shipping/README.rst
@@ -0,0 +1,87 @@
+==================================
+Partner Invoicing Mode At Shipping
+==================================
+
+.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   !! This file is generated by oca-gen-addon-readme !!
+   !! changes will be overwritten.                   !!
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
+    :target: https://odoo-community.org/page/development-status
+    :alt: Beta
+.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
+    :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
+    :alt: License: AGPL-3
+.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Faccount--invoicing-lightgray.png?logo=github
+    :target: https://github.com/OCA/account-invoicing/tree/16.0/partner_invoicing_mode_at_shipping
+    :alt: OCA/account-invoicing
+.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
+    :target: https://translation.odoo-community.org/projects/account-invoicing-16-0/account-invoicing-16-0-partner_invoicing_mode_at_shipping
+    :alt: Translate me on Weblate
+.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
+    :target: https://runbot.odoo-community.org/runbot/95/16.0
+    :alt: Try me on Runbot
+
+|badge1| |badge2| |badge3| |badge4| |badge5| 
+
+This module allows to select a `At shipping` invoicing mode for a customer.
+It is based on `partner_invoicing_mode`.
+When this mode is selected the customer will be invoiced automatically on
+delivery of the goods.
+
+**Table of contents**
+
+.. contents::
+   :local:
+
+Bug Tracker
+===========
+
+Bugs are tracked on `GitHub Issues <https://github.com/OCA/account-invoicing/issues>`_.
+In case of trouble, please check there if your issue has already been reported.
+If you spotted it first, help us smashing it by providing a detailed and welcomed
+`feedback <https://github.com/OCA/account-invoicing/issues/new?body=module:%20partner_invoicing_mode_at_shipping%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
+
+Do not contact contributors directly about support or help with technical issues.
+
+Credits
+=======
+
+Authors
+~~~~~~~
+
+* Camptocamp
+
+Contributors
+~~~~~~~~~~~~
+
+* `Camptocamp <https://www.camptocamp.com>`_:
+
+    * Thierry Ducrest <thierry.ducrest@camptocamp.com>
+
+* Phuc (Tran Thanh) <phuc@trobz.com>
+
+Other credits
+~~~~~~~~~~~~~
+
+The development of this module has been financially supported by:
+
+* Camptocamp
+
+Maintainers
+~~~~~~~~~~~
+
+This module is maintained by the OCA.
+
+.. image:: https://odoo-community.org/logo.png
+   :alt: Odoo Community Association
+   :target: https://odoo-community.org
+
+OCA, or the Odoo Community Association, is a nonprofit organization whose
+mission is to support the collaborative development of Odoo features and
+promote its widespread use.
+
+This module is part of the `OCA/account-invoicing <https://github.com/OCA/account-invoicing/tree/16.0/partner_invoicing_mode_at_shipping>`_ project on GitHub.
+
+You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/partner_invoicing_mode_at_shipping/__init__.py b/partner_invoicing_mode_at_shipping/__init__.py
index 0ee8b5073e2..0650744f6bc 100644
--- a/partner_invoicing_mode_at_shipping/__init__.py
+++ b/partner_invoicing_mode_at_shipping/__init__.py
@@ -1,2 +1 @@
 from . import models
-from . import tests
diff --git a/partner_invoicing_mode_at_shipping/__manifest__.py b/partner_invoicing_mode_at_shipping/__manifest__.py
index 7815728e342..f3bffecec92 100644
--- a/partner_invoicing_mode_at_shipping/__manifest__.py
+++ b/partner_invoicing_mode_at_shipping/__manifest__.py
@@ -2,7 +2,7 @@
 # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
 {
     "name": "Partner Invoicing Mode At Shipping",
-    "version": "15.0.1.0.0",
+    "version": "16.0.1.0.0",
     "summary": "Create invoices automatically when goods are shipped.",
     "author": "Camptocamp, Odoo Community Association (OCA)",
     "website": "https://github.com/OCA/account-invoicing",
diff --git a/partner_invoicing_mode_at_shipping/models/stock_move.py b/partner_invoicing_mode_at_shipping/models/stock_move.py
index 3870a990091..7dc6546baed 100644
--- a/partner_invoicing_mode_at_shipping/models/stock_move.py
+++ b/partner_invoicing_mode_at_shipping/models/stock_move.py
@@ -12,7 +12,7 @@ def _get_related_invoices(self):
         related to this stock move.
         """
         invoices = super()._get_related_invoices()
-        line_invoices = self.mapped("sale_line_id.order_id.invoice_ids").filtered(
+        line_invoices = self.sale_line_id.order_id.invoice_ids.filtered(
             lambda x: x.state == "posted"
         )
         invoices |= line_invoices
diff --git a/partner_invoicing_mode_at_shipping/models/stock_picking.py b/partner_invoicing_mode_at_shipping/models/stock_picking.py
index 1dd7e24ac40..da62d0fbd7c 100644
--- a/partner_invoicing_mode_at_shipping/models/stock_picking.py
+++ b/partner_invoicing_mode_at_shipping/models/stock_picking.py
@@ -24,16 +24,12 @@ def _invoice_at_shipping(self):
 
     def _invoicing_at_shipping(self):
         self.ensure_one()
-        sales = self.env["sale.order"].browse()
-        # Filter out non invoicable sales order
-        for sale in self._get_sales_order_to_invoice():
-            if sale._get_invoiceable_lines():
-                sales |= sale
+        sales = self._get_sales_order_to_invoice()
         # Split invoice creation on partner sales grouping on invoice settings
         sales_one_invoice_per_order = sales.filtered(
             "partner_invoice_id.one_invoice_per_order"
         )
-        invoices = self.env["account.move"].browse()
+        invoices = self.env["account.move"]
         if sales_one_invoice_per_order:
             invoices |= sales_one_invoice_per_order._create_invoices(grouped=True)
         sales_many_invoice_per_order = sales - sales_one_invoice_per_order
@@ -44,6 +40,6 @@ def _invoicing_at_shipping(self):
         return invoices or _("Nothing to invoice.")
 
     def _get_sales_order_to_invoice(self):
-        return self.mapped("move_lines.sale_line_id.order_id").filtered(
+        return self.move_ids.sale_line_id.order_id.filtered(
             lambda r: r._get_invoiceable_lines()
         )
diff --git a/partner_invoicing_mode_at_shipping/static/description/index.html b/partner_invoicing_mode_at_shipping/static/description/index.html
index e5585743373..3f86dbd697c 100644
--- a/partner_invoicing_mode_at_shipping/static/description/index.html
+++ b/partner_invoicing_mode_at_shipping/static/description/index.html
@@ -3,8 +3,8 @@
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="generator" content="Docutils 0.15.1: http://docutils.sourceforge.net/" />
-<title>Account Invoice Mode At Shipping</title>
+<meta name="generator" content="Docutils: http://docutils.sourceforge.net/" />
+<title>Partner Invoicing Mode At Shipping</title>
 <style type="text/css">
 
 /*
@@ -360,16 +360,16 @@
 </style>
 </head>
 <body>
-<div class="document" id="account-invoice-mode-at-shipping">
-<h1 class="title">Account Invoice Mode At Shipping</h1>
+<div class="document" id="partner-invoicing-mode-at-shipping">
+<h1 class="title">Partner Invoicing Mode At Shipping</h1>
 
 <!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 !! This file is generated by oca-gen-addon-readme !!
 !! changes will be overwritten.                   !!
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
-<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/account-invoicing/tree/14.0/account_invoice_mode_at_shipping"><img alt="OCA/account-invoicing" src="https://img.shields.io/badge/github-OCA%2Faccount--invoicing-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/account-invoicing-14-0/account-invoicing-14-0-account_invoice_mode_at_shipping"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/95/14.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
+<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/account-invoicing/tree/16.0/partner_invoicing_mode_at_shipping"><img alt="OCA/account-invoicing" src="https://img.shields.io/badge/github-OCA%2Faccount--invoicing-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/account-invoicing-16-0/account-invoicing-16-0-partner_invoicing_mode_at_shipping"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/95/16.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
 <p>This module allows to select a <cite>At shipping</cite> invoicing mode for a customer.
-It is based on <cite>account_invoice_base_invoicing_mode</cite>.
+It is based on <cite>partner_invoicing_mode</cite>.
 When this mode is selected the customer will be invoiced automatically on
 delivery of the goods.</p>
 <p><strong>Table of contents</strong></p>
@@ -390,7 +390,7 @@ <h1><a class="toc-backref" href="#id1">Bug Tracker</a></h1>
 <p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/account-invoicing/issues">GitHub Issues</a>.
 In case of trouble, please check there if your issue has already been reported.
 If you spotted it first, help us smashing it by providing a detailed and welcomed
-<a class="reference external" href="https://github.com/OCA/account-invoicing/issues/new?body=module:%20account_invoice_mode_at_shipping%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
+<a class="reference external" href="https://github.com/OCA/account-invoicing/issues/new?body=module:%20partner_invoicing_mode_at_shipping%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
 <p>Do not contact contributors directly about support or help with technical issues.</p>
 </div>
 <div class="section" id="credits">
@@ -429,7 +429,7 @@ <h2><a class="toc-backref" href="#id6">Maintainers</a></h2>
 <p>OCA, or the Odoo Community Association, is a nonprofit organization whose
 mission is to support the collaborative development of Odoo features and
 promote its widespread use.</p>
-<p>This module is part of the <a class="reference external" href="https://github.com/OCA/account-invoicing/tree/14.0/account_invoice_mode_at_shipping">OCA/account-invoicing</a> project on GitHub.</p>
+<p>This module is part of the <a class="reference external" href="https://github.com/OCA/account-invoicing/tree/16.0/partner_invoicing_mode_at_shipping">OCA/account-invoicing</a> project on GitHub.</p>
 <p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
 </div>
 </div>
diff --git a/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_at_shipping.py b/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_at_shipping.py
index 2caccae74f8..b83563d9415 100644
--- a/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_at_shipping.py
+++ b/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_at_shipping.py
@@ -2,6 +2,7 @@
 # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
 
 from odoo.tests.common import TransactionCase
+from odoo.tools import mute_logger
 
 
 class TestInvoiceModeAtShipping(TransactionCase):
@@ -38,9 +39,10 @@ def test_invoice_created_at_shipping(self):
         self.partner.invoicing_mode = "at_shipping"
         self.so1.action_confirm()
         for picking in self.so1.picking_ids:
-            for line in picking.move_lines:
-                line.quantity_done = line.product_uom_qty
-                picking.action_assign()
+            for move in picking.move_ids:
+                move.quantity_done = move.product_uom_qty
+            picking.action_assign()
+            with mute_logger("odoo.addons.queue_job.delay"):
                 picking.with_context(test_queue_job_no_delay=True).button_validate()
         self.assertEqual(len(self.so1.invoice_ids), 1)
         self.assertEqual(self.so1.invoice_ids.state, "posted")
@@ -50,8 +52,75 @@ def test_invoice_not_created_at_shipping(self):
         self.partner.invoicing_mode = "standard"
         self.so1.action_confirm()
         for picking in self.so1.picking_ids:
-            for line in picking.move_lines:
-                line.quantity_done = line.product_uom_qty
+            for move in picking.move_ids:
+                move.quantity_done = move.product_uom_qty
             picking.action_assign()
-            picking.button_validate()
+            with mute_logger("odoo.addons.queue_job.delay"):
+                picking.with_context(test_queue_job_no_delay=True).button_validate()
         self.assertEqual(len(self.so1.invoice_ids), 0)
+
+    def test_picking_multi_order_single_invoice(self):
+        """A picking for more than one sale order creating a single invoice"""
+        self.partner.invoicing_mode = "at_shipping"
+        self.partner.one_invoice_per_order = False
+        so2 = self.so1.copy()
+        for order in self.so1, so2:
+            order.action_confirm()
+        # Effectively merge both pickings
+        picking = self.so1.picking_ids
+        so2.picking_ids.move_ids.picking_id = picking
+        # Transfer the remaining picking with moves
+        for move in picking.move_ids:
+            move.quantity_done = move.product_uom_qty
+        picking.action_assign()
+        with mute_logger("odoo.addons.queue_job.delay"):
+            picking.with_context(test_queue_job_no_delay=True).button_validate()
+        self.assertEqual(len(self.so1.invoice_ids), 1)
+        self.assertEqual(self.so1.invoice_ids.state, "posted")
+        self.assertEqual(self.so1.invoice_ids, so2.invoice_ids)
+
+    def test_picking_multi_order_multi_invoice(self):
+        """A picking for more than one sale order creates more than one invoice"""
+        self.partner.invoicing_mode = "at_shipping"
+        self.partner.one_invoice_per_order = True
+        so2 = self.so1.copy()
+        for order in self.so1, so2:
+            order.action_confirm()
+        # Effectively merge both pickings
+        picking = self.so1.picking_ids
+        so2.picking_ids.move_ids.picking_id = picking
+        # Transfer the remaining picking with moves
+        for move in picking.move_ids:
+            move.quantity_done = move.product_uom_qty
+        picking.action_assign()
+        with mute_logger("odoo.addons.queue_job.delay"):
+            picking.with_context(test_queue_job_no_delay=True).button_validate()
+        self.assertEqual(len(self.so1.invoice_ids), 1)
+        self.assertEqual(self.so1.invoice_ids.state, "posted")
+        self.assertEqual(len(so2.invoice_ids), 1)
+        self.assertEqual(so2.invoice_ids.state, "posted")
+        self.assertNotEqual(self.so1.invoice_ids, so2.invoice_ids)
+
+    def test_picking_backorder(self):
+        """In case of a backorder, another invoice is created"""
+        self.partner.invoicing_mode = "at_shipping"
+        self.so1.action_confirm()
+        picking = self.so1.picking_ids
+        picking.move_ids.quantity_done = 2
+        picking.action_assign()
+        with mute_logger("odoo.addons.queue_job.delay"):
+            picking.with_context(
+                skip_backorder=True, test_queue_job_no_delay=True
+            ).button_validate()
+        self.assertEqual(len(self.so1.invoice_ids), 1)
+        self.assertEqual(self.so1.invoice_ids.state, "posted")
+        # Now process the backorder
+        backorder = self.so1.picking_ids - picking
+        backorder.move_ids.quantity_done = 2
+        backorder.action_assign()
+        with mute_logger("odoo.addons.queue_job.delay"):
+            backorder.with_context(test_queue_job_no_delay=True).button_validate()
+        self.assertEqual(len(self.so1.invoice_ids), 2)
+        self.assertTrue(
+            all(invoice.state == "posted") for invoice in self.so1.invoice_ids
+        )

From 2d9a5eefb51ae61130a70e967d2556b3860e161f Mon Sep 17 00:00:00 2001
From: oca-ci <oca-ci@odoo-community.org>
Date: Fri, 21 Apr 2023 00:44:03 +0000
Subject: [PATCH 08/32] [UPD] Update partner_invoicing_mode_at_shipping.pot

---
 .../partner_invoicing_mode_at_shipping.pot    | 47 +++++++++++++++++++
 1 file changed, 47 insertions(+)
 create mode 100644 partner_invoicing_mode_at_shipping/i18n/partner_invoicing_mode_at_shipping.pot

diff --git a/partner_invoicing_mode_at_shipping/i18n/partner_invoicing_mode_at_shipping.pot b/partner_invoicing_mode_at_shipping/i18n/partner_invoicing_mode_at_shipping.pot
new file mode 100644
index 00000000000..2a52ab4c717
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/i18n/partner_invoicing_mode_at_shipping.pot
@@ -0,0 +1,47 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# 	* partner_invoicing_mode_at_shipping
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 16.0\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model.fields.selection,name:partner_invoicing_mode_at_shipping.selection__res_partner__invoicing_mode__at_shipping
+msgid "At Shipping"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model,name:partner_invoicing_mode_at_shipping.model_res_partner
+msgid "Contact"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_res_partner__invoicing_mode
+#: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_res_users__invoicing_mode
+msgid "Invoicing Mode"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#. odoo-python
+#: code:addons/partner_invoicing_mode_at_shipping/models/stock_picking.py:0
+#, python-format
+msgid "Nothing to invoice."
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model,name:partner_invoicing_mode_at_shipping.model_stock_move
+msgid "Stock Move"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model,name:partner_invoicing_mode_at_shipping.model_stock_picking
+msgid "Transfer"
+msgstr ""

From 212022af62193b3feffc509239e41c90ac6fb862 Mon Sep 17 00:00:00 2001
From: OCA-git-bot <oca-git-bot@odoo-community.org>
Date: Fri, 21 Apr 2023 00:48:31 +0000
Subject: [PATCH 09/32] [UPD] README.rst

---
 .../static/description/index.html                               | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/partner_invoicing_mode_at_shipping/static/description/index.html b/partner_invoicing_mode_at_shipping/static/description/index.html
index 3f86dbd697c..229a168ddc8 100644
--- a/partner_invoicing_mode_at_shipping/static/description/index.html
+++ b/partner_invoicing_mode_at_shipping/static/description/index.html
@@ -3,7 +3,7 @@
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="generator" content="Docutils: http://docutils.sourceforge.net/" />
+<meta name="generator" content="Docutils 0.15.1: http://docutils.sourceforge.net/" />
 <title>Partner Invoicing Mode At Shipping</title>
 <style type="text/css">
 

From dc4798efc21176f4cfa3a454d6bb4aaac3d1f694 Mon Sep 17 00:00:00 2001
From: OCA-git-bot <oca-git-bot@odoo-community.org>
Date: Fri, 21 Apr 2023 00:49:10 +0000
Subject: [PATCH 10/32] partner_invoicing_mode_at_shipping 16.0.1.0.1

---
 partner_invoicing_mode_at_shipping/__manifest__.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/partner_invoicing_mode_at_shipping/__manifest__.py b/partner_invoicing_mode_at_shipping/__manifest__.py
index f3bffecec92..b91a21ced78 100644
--- a/partner_invoicing_mode_at_shipping/__manifest__.py
+++ b/partner_invoicing_mode_at_shipping/__manifest__.py
@@ -2,7 +2,7 @@
 # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
 {
     "name": "Partner Invoicing Mode At Shipping",
-    "version": "16.0.1.0.0",
+    "version": "16.0.1.0.1",
     "summary": "Create invoices automatically when goods are shipped.",
     "author": "Camptocamp, Odoo Community Association (OCA)",
     "website": "https://github.com/OCA/account-invoicing",

From 14778836f0976490b077f12c2967166e2549c407 Mon Sep 17 00:00:00 2001
From: Ivorra78 <informatica@totmaterial.es>
Date: Sat, 29 Jul 2023 08:42:27 +0000
Subject: [PATCH 11/32] Added translation using Weblate (Spanish)

---
 partner_invoicing_mode_at_shipping/i18n/es.po | 48 +++++++++++++++++++
 1 file changed, 48 insertions(+)
 create mode 100644 partner_invoicing_mode_at_shipping/i18n/es.po

diff --git a/partner_invoicing_mode_at_shipping/i18n/es.po b/partner_invoicing_mode_at_shipping/i18n/es.po
new file mode 100644
index 00000000000..fee83422cbb
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/i18n/es.po
@@ -0,0 +1,48 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# 	* partner_invoicing_mode_at_shipping
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 16.0\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: es\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model.fields.selection,name:partner_invoicing_mode_at_shipping.selection__res_partner__invoicing_mode__at_shipping
+msgid "At Shipping"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model,name:partner_invoicing_mode_at_shipping.model_res_partner
+msgid "Contact"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_res_partner__invoicing_mode
+#: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_res_users__invoicing_mode
+msgid "Invoicing Mode"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#. odoo-python
+#: code:addons/partner_invoicing_mode_at_shipping/models/stock_picking.py:0
+#, python-format
+msgid "Nothing to invoice."
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model,name:partner_invoicing_mode_at_shipping.model_stock_move
+msgid "Stock Move"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model,name:partner_invoicing_mode_at_shipping.model_stock_picking
+msgid "Transfer"
+msgstr ""

From 17b8662b42e2a22ff3f724214d7e912435c8fdb8 Mon Sep 17 00:00:00 2001
From: Ivorra78 <informatica@totmaterial.es>
Date: Sat, 29 Jul 2023 08:43:43 +0000
Subject: [PATCH 12/32] Translated using Weblate (Spanish)

Currently translated at 100.0% (6 of 6 strings)

Translation: account-invoicing-16.0/account-invoicing-16.0-partner_invoicing_mode_at_shipping
Translate-URL: https://translation.odoo-community.org/projects/account-invoicing-16-0/account-invoicing-16-0-partner_invoicing_mode_at_shipping/es/
---
 partner_invoicing_mode_at_shipping/i18n/es.po | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/partner_invoicing_mode_at_shipping/i18n/es.po b/partner_invoicing_mode_at_shipping/i18n/es.po
index fee83422cbb..f4d4670aad8 100644
--- a/partner_invoicing_mode_at_shipping/i18n/es.po
+++ b/partner_invoicing_mode_at_shipping/i18n/es.po
@@ -6,43 +6,45 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Odoo Server 16.0\n"
 "Report-Msgid-Bugs-To: \n"
-"Last-Translator: Automatically generated\n"
+"PO-Revision-Date: 2023-07-29 10:09+0000\n"
+"Last-Translator: Ivorra78 <informatica@totmaterial.es>\n"
 "Language-Team: none\n"
 "Language: es\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: \n"
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.17\n"
 
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model.fields.selection,name:partner_invoicing_mode_at_shipping.selection__res_partner__invoicing_mode__at_shipping
 msgid "At Shipping"
-msgstr ""
+msgstr "En envío"
 
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model,name:partner_invoicing_mode_at_shipping.model_res_partner
 msgid "Contact"
-msgstr ""
+msgstr "Contacto"
 
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_res_partner__invoicing_mode
 #: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_res_users__invoicing_mode
 msgid "Invoicing Mode"
-msgstr ""
+msgstr "Modo de facturación"
 
 #. module: partner_invoicing_mode_at_shipping
 #. odoo-python
 #: code:addons/partner_invoicing_mode_at_shipping/models/stock_picking.py:0
 #, python-format
 msgid "Nothing to invoice."
-msgstr ""
+msgstr "Nada para Facturar."
 
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model,name:partner_invoicing_mode_at_shipping.model_stock_move
 msgid "Stock Move"
-msgstr ""
+msgstr "Movimiento de existencias"
 
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model,name:partner_invoicing_mode_at_shipping.model_stock_picking
 msgid "Transfer"
-msgstr ""
+msgstr "Transferencia"

From 51bf4bae09ca06df833533351f2dca5daffb97e7 Mon Sep 17 00:00:00 2001
From: OCA-git-bot <oca-git-bot@odoo-community.org>
Date: Sun, 3 Sep 2023 11:37:15 +0000
Subject: [PATCH 13/32] [UPD] README.rst

---
 partner_invoicing_mode_at_shipping/README.rst | 15 +++++---
 .../static/description/index.html             | 38 ++++++++++---------
 2 files changed, 29 insertions(+), 24 deletions(-)

diff --git a/partner_invoicing_mode_at_shipping/README.rst b/partner_invoicing_mode_at_shipping/README.rst
index 94f493a81d1..373f2aff3c0 100644
--- a/partner_invoicing_mode_at_shipping/README.rst
+++ b/partner_invoicing_mode_at_shipping/README.rst
@@ -2,10 +2,13 @@
 Partner Invoicing Mode At Shipping
 ==================================
 
-.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+.. 
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    !! This file is generated by oca-gen-addon-readme !!
    !! changes will be overwritten.                   !!
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   !! source digest: sha256:56633cb4b17fae8ac33e95dd4ae02ad4ef513adf71cf972a8db705a28fdec624
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
 .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
     :target: https://odoo-community.org/page/development-status
@@ -19,11 +22,11 @@ Partner Invoicing Mode At Shipping
 .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
     :target: https://translation.odoo-community.org/projects/account-invoicing-16-0/account-invoicing-16-0-partner_invoicing_mode_at_shipping
     :alt: Translate me on Weblate
-.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
-    :target: https://runbot.odoo-community.org/runbot/95/16.0
-    :alt: Try me on Runbot
+.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
+    :target: https://runboat.odoo-community.org/builds?repo=OCA/account-invoicing&target_branch=16.0
+    :alt: Try me on Runboat
 
-|badge1| |badge2| |badge3| |badge4| |badge5| 
+|badge1| |badge2| |badge3| |badge4| |badge5|
 
 This module allows to select a `At shipping` invoicing mode for a customer.
 It is based on `partner_invoicing_mode`.
@@ -40,7 +43,7 @@ Bug Tracker
 
 Bugs are tracked on `GitHub Issues <https://github.com/OCA/account-invoicing/issues>`_.
 In case of trouble, please check there if your issue has already been reported.
-If you spotted it first, help us smashing it by providing a detailed and welcomed
+If you spotted it first, help us to smash it by providing a detailed and welcomed
 `feedback <https://github.com/OCA/account-invoicing/issues/new?body=module:%20partner_invoicing_mode_at_shipping%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
 
 Do not contact contributors directly about support or help with technical issues.
diff --git a/partner_invoicing_mode_at_shipping/static/description/index.html b/partner_invoicing_mode_at_shipping/static/description/index.html
index 229a168ddc8..8837cb328ba 100644
--- a/partner_invoicing_mode_at_shipping/static/description/index.html
+++ b/partner_invoicing_mode_at_shipping/static/description/index.html
@@ -1,20 +1,20 @@
-<?xml version="1.0" encoding="utf-8" ?>
+<?xml version="1.0" encoding="utf-8"?>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="generator" content="Docutils 0.15.1: http://docutils.sourceforge.net/" />
+<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
 <title>Partner Invoicing Mode At Shipping</title>
 <style type="text/css">
 
 /*
 :Author: David Goodger (goodger@python.org)
-:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
+:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
 :Copyright: This stylesheet has been placed in the public domain.
 
 Default cascading style sheet for the HTML output of Docutils.
 
-See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
+See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
 customize this style sheet.
 */
 
@@ -366,8 +366,10 @@ <h1 class="title">Partner Invoicing Mode At Shipping</h1>
 <!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 !! This file is generated by oca-gen-addon-readme !!
 !! changes will be overwritten.                   !!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!! source digest: sha256:56633cb4b17fae8ac33e95dd4ae02ad4ef513adf71cf972a8db705a28fdec624
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
-<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/account-invoicing/tree/16.0/partner_invoicing_mode_at_shipping"><img alt="OCA/account-invoicing" src="https://img.shields.io/badge/github-OCA%2Faccount--invoicing-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/account-invoicing-16-0/account-invoicing-16-0-partner_invoicing_mode_at_shipping"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/95/16.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
+<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/account-invoicing/tree/16.0/partner_invoicing_mode_at_shipping"><img alt="OCA/account-invoicing" src="https://img.shields.io/badge/github-OCA%2Faccount--invoicing-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/account-invoicing-16-0/account-invoicing-16-0-partner_invoicing_mode_at_shipping"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/account-invoicing&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
 <p>This module allows to select a <cite>At shipping</cite> invoicing mode for a customer.
 It is based on <cite>partner_invoicing_mode</cite>.
 When this mode is selected the customer will be invoiced automatically on
@@ -375,34 +377,34 @@ <h1 class="title">Partner Invoicing Mode At Shipping</h1>
 <p><strong>Table of contents</strong></p>
 <div class="contents local topic" id="contents">
 <ul class="simple">
-<li><a class="reference internal" href="#bug-tracker" id="id1">Bug Tracker</a></li>
-<li><a class="reference internal" href="#credits" id="id2">Credits</a><ul>
-<li><a class="reference internal" href="#authors" id="id3">Authors</a></li>
-<li><a class="reference internal" href="#contributors" id="id4">Contributors</a></li>
-<li><a class="reference internal" href="#other-credits" id="id5">Other credits</a></li>
-<li><a class="reference internal" href="#maintainers" id="id6">Maintainers</a></li>
+<li><a class="reference internal" href="#bug-tracker" id="toc-entry-1">Bug Tracker</a></li>
+<li><a class="reference internal" href="#credits" id="toc-entry-2">Credits</a><ul>
+<li><a class="reference internal" href="#authors" id="toc-entry-3">Authors</a></li>
+<li><a class="reference internal" href="#contributors" id="toc-entry-4">Contributors</a></li>
+<li><a class="reference internal" href="#other-credits" id="toc-entry-5">Other credits</a></li>
+<li><a class="reference internal" href="#maintainers" id="toc-entry-6">Maintainers</a></li>
 </ul>
 </li>
 </ul>
 </div>
 <div class="section" id="bug-tracker">
-<h1><a class="toc-backref" href="#id1">Bug Tracker</a></h1>
+<h1><a class="toc-backref" href="#toc-entry-1">Bug Tracker</a></h1>
 <p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/account-invoicing/issues">GitHub Issues</a>.
 In case of trouble, please check there if your issue has already been reported.
-If you spotted it first, help us smashing it by providing a detailed and welcomed
+If you spotted it first, help us to smash it by providing a detailed and welcomed
 <a class="reference external" href="https://github.com/OCA/account-invoicing/issues/new?body=module:%20partner_invoicing_mode_at_shipping%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
 <p>Do not contact contributors directly about support or help with technical issues.</p>
 </div>
 <div class="section" id="credits">
-<h1><a class="toc-backref" href="#id2">Credits</a></h1>
+<h1><a class="toc-backref" href="#toc-entry-2">Credits</a></h1>
 <div class="section" id="authors">
-<h2><a class="toc-backref" href="#id3">Authors</a></h2>
+<h2><a class="toc-backref" href="#toc-entry-3">Authors</a></h2>
 <ul class="simple">
 <li>Camptocamp</li>
 </ul>
 </div>
 <div class="section" id="contributors">
-<h2><a class="toc-backref" href="#id4">Contributors</a></h2>
+<h2><a class="toc-backref" href="#toc-entry-4">Contributors</a></h2>
 <ul>
 <li><p class="first"><a class="reference external" href="https://www.camptocamp.com">Camptocamp</a>:</p>
 <blockquote>
@@ -416,14 +418,14 @@ <h2><a class="toc-backref" href="#id4">Contributors</a></h2>
 </ul>
 </div>
 <div class="section" id="other-credits">
-<h2><a class="toc-backref" href="#id5">Other credits</a></h2>
+<h2><a class="toc-backref" href="#toc-entry-5">Other credits</a></h2>
 <p>The development of this module has been financially supported by:</p>
 <ul class="simple">
 <li>Camptocamp</li>
 </ul>
 </div>
 <div class="section" id="maintainers">
-<h2><a class="toc-backref" href="#id6">Maintainers</a></h2>
+<h2><a class="toc-backref" href="#toc-entry-6">Maintainers</a></h2>
 <p>This module is maintained by the OCA.</p>
 <a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
 <p>OCA, or the Odoo Community Association, is a nonprofit organization whose

From 7196388ceba63af15263e71f591b4176e211f737 Mon Sep 17 00:00:00 2001
From: Denis Roussel <denis.roussel@acsone.eu>
Date: Mon, 18 Dec 2023 12:51:13 +0100
Subject: [PATCH 14/32] [IMP] partner_invoicing_mode_at_shipping: Add grouping
 option per picking

---
 partner_invoicing_mode_at_shipping/README.rst |  6 +-
 .../models/__init__.py                        |  1 +
 .../models/res_partner.py                     | 33 ++++++++-
 .../models/sale_order.py                      | 46 ++++++++++++
 .../models/stock_picking.py                   | 11 ++-
 .../readme/DESCRIPTION.rst                    |  4 +
 .../static/description/index.html             |  5 +-
 .../tests/test_invoice_mode_at_shipping.py    | 73 +++++++++++++++++++
 8 files changed, 172 insertions(+), 7 deletions(-)
 create mode 100644 partner_invoicing_mode_at_shipping/models/sale_order.py

diff --git a/partner_invoicing_mode_at_shipping/README.rst b/partner_invoicing_mode_at_shipping/README.rst
index 373f2aff3c0..37516f2e984 100644
--- a/partner_invoicing_mode_at_shipping/README.rst
+++ b/partner_invoicing_mode_at_shipping/README.rst
@@ -7,7 +7,7 @@ Partner Invoicing Mode At Shipping
    !! This file is generated by oca-gen-addon-readme !!
    !! changes will be overwritten.                   !!
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-   !! source digest: sha256:56633cb4b17fae8ac33e95dd4ae02ad4ef513adf71cf972a8db705a28fdec624
+   !! source digest: sha256:c3631731c8b2841936e312dd563cdb6e41134c558ffc530d9675123065346d96
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
 .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
@@ -33,6 +33,10 @@ It is based on `partner_invoicing_mode`.
 When this mode is selected the customer will be invoiced automatically on
 delivery of the goods.
 
+Another option is the 'One Invoice Per Picking'. That one is not compatible
+with the 'At shipping' invoicing mode. In that case, the invoicing validation
+will occur at a different moment (monthly, ...).
+
 **Table of contents**
 
 .. contents::
diff --git a/partner_invoicing_mode_at_shipping/models/__init__.py b/partner_invoicing_mode_at_shipping/models/__init__.py
index b87ddbd73f5..eee3b02a332 100644
--- a/partner_invoicing_mode_at_shipping/models/__init__.py
+++ b/partner_invoicing_mode_at_shipping/models/__init__.py
@@ -1,3 +1,4 @@
 from . import res_partner
 from . import stock_move
 from . import stock_picking
+from . import sale_order
diff --git a/partner_invoicing_mode_at_shipping/models/res_partner.py b/partner_invoicing_mode_at_shipping/models/res_partner.py
index f9a1327e249..1d9a9737f7e 100644
--- a/partner_invoicing_mode_at_shipping/models/res_partner.py
+++ b/partner_invoicing_mode_at_shipping/models/res_partner.py
@@ -1,7 +1,8 @@
 # Copyright 2020 Camptocamp SA
 # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
 
-from odoo import fields, models
+from odoo import _, api, fields, models
+from odoo.exceptions import ValidationError
 
 
 class ResPartner(models.Model):
@@ -11,3 +12,33 @@ class ResPartner(models.Model):
         selection_add=[("at_shipping", "At Shipping")],
         ondelete={"at_shipping": "set default"},
     )
+
+    one_invoice_per_picking = fields.Boolean(
+        help="Check this if you want to create one invoice per picking using the"
+        " partner invoicing mode that should be different than 'At Shipping'."
+    )
+
+    @api.constrains(
+        "invoicing_mode", "one_invoice_per_picking", "one_invoice_per_order"
+    )
+    def _check_invoicing_mode_one_invoice_per_picking(self):
+        for partner in self:
+            if (
+                partner.invoicing_mode == "at_shipping"
+                and partner.one_invoice_per_picking
+            ):
+                raise ValidationError(
+                    _(
+                        "You cannot configure the partner %(partner)s with "
+                        "Invoicing Mode 'At Shipping' and 'One Invoice Per Picking'!",
+                        partner=partner.name,
+                    ),
+                )
+            if partner.one_invoice_per_picking and partner.one_invoice_per_order:
+                raise ValidationError(
+                    _(
+                        "You cannot configure the partner %(partner)s with "
+                        "'One Invoice Per Order' and 'One Invoice Per Picking'!",
+                        partner=partner.name,
+                    ),
+                )
diff --git a/partner_invoicing_mode_at_shipping/models/sale_order.py b/partner_invoicing_mode_at_shipping/models/sale_order.py
new file mode 100644
index 00000000000..7ee15ac23d6
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/models/sale_order.py
@@ -0,0 +1,46 @@
+# Copyright 2023 ACSONE SA/NV
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+
+from odoo import fields, models
+from odoo.osv.expression import OR
+
+
+class SaleOrder(models.Model):
+    _inherit = "sale.order"
+
+    one_invoice_per_picking = fields.Boolean(
+        related="partner_invoice_id.one_invoice_per_picking",
+        store=True,
+        index=True,
+    )
+
+    def _get_generate_invoices_state_domain(self):
+        domain = super()._get_generate_invoices_state_domain()
+        domain = OR(
+            [
+                domain,
+                [
+                    ("one_invoice_per_picking", "=", True),
+                    ("invoice_ids.state", "=", "draft"),
+                ],
+            ]
+        )
+        return domain
+
+    def _get_generated_invoices(self, partition):
+        sales_to_validate_invoices = self.filtered(
+            lambda sale: sale.one_invoice_per_picking
+            and any(invoice.state == "draft" for invoice in self.invoice_ids)
+        )
+        sales_create_invoices = self - sales_to_validate_invoices
+        if sales_create_invoices:
+            invoices = super(SaleOrder, sales_create_invoices)._get_generated_invoices(
+                partition
+            )
+        else:
+            invoices = self.env["account.move"].browse()
+        to_validate_invoices = sales_to_validate_invoices.mapped(
+            "invoice_ids"
+        ).filtered(lambda invoice: invoice.state == "draft")
+        return invoices | to_validate_invoices
diff --git a/partner_invoicing_mode_at_shipping/models/stock_picking.py b/partner_invoicing_mode_at_shipping/models/stock_picking.py
index da62d0fbd7c..79b234c7127 100644
--- a/partner_invoicing_mode_at_shipping/models/stock_picking.py
+++ b/partner_invoicing_mode_at_shipping/models/stock_picking.py
@@ -17,9 +17,9 @@ def _action_done(self):
     def _invoice_at_shipping(self):
         """Check if picking must be invoiced at shipping."""
         self.ensure_one()
-        return (
-            self.picking_type_code == "outgoing"
-            and self.sale_id.partner_invoice_id.invoicing_mode == "at_shipping"
+        return self.picking_type_code == "outgoing" and (
+            self.sale_id.partner_invoice_id.invoicing_mode == "at_shipping"
+            or self.sale_id.partner_invoice_id.one_invoice_per_picking
         )
 
     def _invoicing_at_shipping(self):
@@ -35,7 +35,10 @@ def _invoicing_at_shipping(self):
         sales_many_invoice_per_order = sales - sales_one_invoice_per_order
         if sales_many_invoice_per_order:
             invoices |= sales_many_invoice_per_order._create_invoices(grouped=False)
-        for invoice in invoices:
+        # The invoices per picking will use the invoicing_mode
+        for invoice in invoices.filtered(
+            lambda invoice: not invoice.partner_id.one_invoice_per_picking
+        ):
             invoice.with_delay()._validate_invoice()
         return invoices or _("Nothing to invoice.")
 
diff --git a/partner_invoicing_mode_at_shipping/readme/DESCRIPTION.rst b/partner_invoicing_mode_at_shipping/readme/DESCRIPTION.rst
index 9a3d5a02e2d..61022b9d7ff 100644
--- a/partner_invoicing_mode_at_shipping/readme/DESCRIPTION.rst
+++ b/partner_invoicing_mode_at_shipping/readme/DESCRIPTION.rst
@@ -2,3 +2,7 @@ This module allows to select a `At shipping` invoicing mode for a customer.
 It is based on `partner_invoicing_mode`.
 When this mode is selected the customer will be invoiced automatically on
 delivery of the goods.
+
+Another option is the 'One Invoice Per Picking'. That one is not compatible
+with the 'At shipping' invoicing mode. In that case, the invoicing validation
+will occur at a different moment (monthly, ...).
diff --git a/partner_invoicing_mode_at_shipping/static/description/index.html b/partner_invoicing_mode_at_shipping/static/description/index.html
index 8837cb328ba..96af63e7a49 100644
--- a/partner_invoicing_mode_at_shipping/static/description/index.html
+++ b/partner_invoicing_mode_at_shipping/static/description/index.html
@@ -367,13 +367,16 @@ <h1 class="title">Partner Invoicing Mode At Shipping</h1>
 !! This file is generated by oca-gen-addon-readme !!
 !! changes will be overwritten.                   !!
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-!! source digest: sha256:56633cb4b17fae8ac33e95dd4ae02ad4ef513adf71cf972a8db705a28fdec624
+!! source digest: sha256:c3631731c8b2841936e312dd563cdb6e41134c558ffc530d9675123065346d96
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
 <p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/account-invoicing/tree/16.0/partner_invoicing_mode_at_shipping"><img alt="OCA/account-invoicing" src="https://img.shields.io/badge/github-OCA%2Faccount--invoicing-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/account-invoicing-16-0/account-invoicing-16-0-partner_invoicing_mode_at_shipping"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/account-invoicing&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
 <p>This module allows to select a <cite>At shipping</cite> invoicing mode for a customer.
 It is based on <cite>partner_invoicing_mode</cite>.
 When this mode is selected the customer will be invoiced automatically on
 delivery of the goods.</p>
+<p>Another option is the ‘One Invoice Per Picking’. That one is not compatible
+with the ‘At shipping’ invoicing mode. In that case, the invoicing validation
+will occur at a different moment (monthly, …).</p>
 <p><strong>Table of contents</strong></p>
 <div class="contents local topic" id="contents">
 <ul class="simple">
diff --git a/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_at_shipping.py b/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_at_shipping.py
index b83563d9415..aea177e65e9 100644
--- a/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_at_shipping.py
+++ b/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_at_shipping.py
@@ -1,9 +1,12 @@
 # Copyright 2020 Camptocamp SA
 # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
 
+from odoo.exceptions import ValidationError
 from odoo.tests.common import TransactionCase
 from odoo.tools import mute_logger
 
+from odoo.addons.queue_job.tests.common import trap_jobs
+
 
 class TestInvoiceModeAtShipping(TransactionCase):
     @classmethod
@@ -124,3 +127,73 @@ def test_picking_backorder(self):
         self.assertTrue(
             all(invoice.state == "posted") for invoice in self.so1.invoice_ids
         )
+
+    def test_invoice_created_at_shipping_per_delivery(self):
+        """Check that an invoice is created when goods are shipped."""
+        self.partner.invoicing_mode = "standard"
+        self.partner.one_invoice_per_picking = True
+        self.so1.action_confirm()
+        picking = self.so1.picking_ids
+
+        # Deliver partially
+        picking.move_ids.quantity_done = 2.0
+        with trap_jobs() as trap:
+            picking._action_done()
+            trap.assert_enqueued_job(
+                picking._invoicing_at_shipping,
+            )
+            trap.perform_enqueued_jobs()
+
+        self.assertEqual(picking.state, "done")
+        invoice = self.so1.invoice_ids
+        # Invoice is generated but is still draft
+        self.assertEqual(
+            "draft",
+            invoice.state,
+        )
+
+        backorder = self.so1.picking_ids - picking
+        self.assertTrue(backorder)
+
+        backorder.move_ids.quantity_done = 2.0
+        with trap_jobs() as trap:
+            backorder._action_done()
+            trap.assert_enqueued_job(
+                backorder._invoicing_at_shipping,
+            )
+            with trap_jobs() as trap_invoice:
+                trap.perform_enqueued_jobs()
+                self.assertFalse(trap_invoice.enqueued_jobs)
+        invoice_2 = self.so1.invoice_ids - invoice
+        self.assertEqual(
+            "draft",
+            invoice_2.state,
+        )
+        # Launch the invoicing
+        with trap_jobs() as trap:
+            self.env["sale.order"].cron_generate_standard_invoices()
+            trap.assert_enqueued_job(
+                self.env["sale.order"]._generate_invoices_by_partner,
+                args=(self.so1.ids,),
+            )
+            with trap_jobs() as trap_invoice:
+                trap.perform_enqueued_jobs()
+                trap_invoice.assert_enqueued_job(
+                    self.so1.invoice_ids[0]._validate_invoice
+                )
+                trap_invoice.assert_enqueued_job(
+                    self.so1.invoice_ids[1]._validate_invoice
+                )
+                trap_invoice.perform_enqueued_jobs()
+        self.assertEqual("posted", invoice.state)
+        self.assertEqual("posted", invoice_2.state)
+
+    def test_invoice_created_at_shipping_per_delivery_constrains(self):
+        with self.assertRaises(ValidationError):
+            self.partner.write(
+                {"one_invoice_per_picking": True, "invoicing_mode": "at_shipping"}
+            )
+        with self.assertRaises(ValidationError):
+            self.partner.write(
+                {"one_invoice_per_order": True, "one_invoice_per_picking": True}
+            )

From 645f53dcafb6607796652555a7ff5aed97498a4a Mon Sep 17 00:00:00 2001
From: mymage <stefano.consolaro@mymage.it>
Date: Mon, 26 Feb 2024 16:12:01 +0000
Subject: [PATCH 15/32] Added translation using Weblate (Italian)

---
 partner_invoicing_mode_at_shipping/i18n/it.po | 48 +++++++++++++++++++
 1 file changed, 48 insertions(+)
 create mode 100644 partner_invoicing_mode_at_shipping/i18n/it.po

diff --git a/partner_invoicing_mode_at_shipping/i18n/it.po b/partner_invoicing_mode_at_shipping/i18n/it.po
new file mode 100644
index 00000000000..5de184a256e
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/i18n/it.po
@@ -0,0 +1,48 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# 	* partner_invoicing_mode_at_shipping
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 16.0\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: it\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model.fields.selection,name:partner_invoicing_mode_at_shipping.selection__res_partner__invoicing_mode__at_shipping
+msgid "At Shipping"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model,name:partner_invoicing_mode_at_shipping.model_res_partner
+msgid "Contact"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_res_partner__invoicing_mode
+#: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_res_users__invoicing_mode
+msgid "Invoicing Mode"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#. odoo-python
+#: code:addons/partner_invoicing_mode_at_shipping/models/stock_picking.py:0
+#, python-format
+msgid "Nothing to invoice."
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model,name:partner_invoicing_mode_at_shipping.model_stock_move
+msgid "Stock Move"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model,name:partner_invoicing_mode_at_shipping.model_stock_picking
+msgid "Transfer"
+msgstr ""

From 855516fc52c16b46e6823c54ec37317a23e70c15 Mon Sep 17 00:00:00 2001
From: mymage <stefano.consolaro@mymage.it>
Date: Tue, 27 Feb 2024 12:09:07 +0000
Subject: [PATCH 16/32] Translated using Weblate (Italian)

Currently translated at 100.0% (6 of 6 strings)

Translation: account-invoicing-16.0/account-invoicing-16.0-partner_invoicing_mode_at_shipping
Translate-URL: https://translation.odoo-community.org/projects/account-invoicing-16-0/account-invoicing-16-0-partner_invoicing_mode_at_shipping/it/
---
 partner_invoicing_mode_at_shipping/i18n/it.po | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/partner_invoicing_mode_at_shipping/i18n/it.po b/partner_invoicing_mode_at_shipping/i18n/it.po
index 5de184a256e..d3604a05e5a 100644
--- a/partner_invoicing_mode_at_shipping/i18n/it.po
+++ b/partner_invoicing_mode_at_shipping/i18n/it.po
@@ -6,43 +6,45 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Odoo Server 16.0\n"
 "Report-Msgid-Bugs-To: \n"
-"Last-Translator: Automatically generated\n"
+"PO-Revision-Date: 2024-02-27 12:11+0000\n"
+"Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
 "Language-Team: none\n"
 "Language: it\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: \n"
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.17\n"
 
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model.fields.selection,name:partner_invoicing_mode_at_shipping.selection__res_partner__invoicing_mode__at_shipping
 msgid "At Shipping"
-msgstr ""
+msgstr "Alla spedizione"
 
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model,name:partner_invoicing_mode_at_shipping.model_res_partner
 msgid "Contact"
-msgstr ""
+msgstr "Contatto"
 
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_res_partner__invoicing_mode
 #: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_res_users__invoicing_mode
 msgid "Invoicing Mode"
-msgstr ""
+msgstr "Modo fatturazione"
 
 #. module: partner_invoicing_mode_at_shipping
 #. odoo-python
 #: code:addons/partner_invoicing_mode_at_shipping/models/stock_picking.py:0
 #, python-format
 msgid "Nothing to invoice."
-msgstr ""
+msgstr "Nulla da fatturare."
 
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model,name:partner_invoicing_mode_at_shipping.model_stock_move
 msgid "Stock Move"
-msgstr ""
+msgstr "Movimento di magazzino"
 
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model,name:partner_invoicing_mode_at_shipping.model_stock_picking
 msgid "Transfer"
-msgstr ""
+msgstr "Trasferimento"

From e38f0124f841f41a81a01f89dfc23aadb07473e6 Mon Sep 17 00:00:00 2001
From: Denis Roussel <denis.roussel@acsone.eu>
Date: Mon, 18 Dec 2023 15:16:40 +0100
Subject: [PATCH 17/32] [IMP] partner_invoicing_mode_at_shipping: Compute
 'one_invoice_per_picking' instead of related

---
 .../models/sale_order.py                          | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/partner_invoicing_mode_at_shipping/models/sale_order.py b/partner_invoicing_mode_at_shipping/models/sale_order.py
index 7ee15ac23d6..42131e8f97a 100644
--- a/partner_invoicing_mode_at_shipping/models/sale_order.py
+++ b/partner_invoicing_mode_at_shipping/models/sale_order.py
@@ -2,7 +2,7 @@
 # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
 
 
-from odoo import fields, models
+from odoo import api, fields, models
 from odoo.osv.expression import OR
 
 
@@ -10,11 +10,22 @@ class SaleOrder(models.Model):
     _inherit = "sale.order"
 
     one_invoice_per_picking = fields.Boolean(
-        related="partner_invoice_id.one_invoice_per_picking",
+        compute="_compute_one_invoice_per_picking",
         store=True,
         index=True,
     )
 
+    @api.depends("partner_invoice_id")
+    def _compute_one_invoice_per_picking(self):
+        """
+        Compute this field (instead a related) to avoid computing all
+        related sale orders if option changed on partner level.
+        """
+        for order in self:
+            order.one_invoice_per_picking = (
+                order.partner_invoice_id.one_invoice_per_picking
+            )
+
     def _get_generate_invoices_state_domain(self):
         domain = super()._get_generate_invoices_state_domain()
         domain = OR(

From a7ce0803bd0cccdac2ed5698ad2cc09a96050550 Mon Sep 17 00:00:00 2001
From: Denis Roussel <denis.roussel@acsone.eu>
Date: Mon, 18 Dec 2023 16:32:25 +0100
Subject: [PATCH 18/32] [IMP] partner_invoicing_mode_at_shipping: Refactor
 tests and change to 'shipping' instead of 'picking'

---
 partner_invoicing_mode_at_shipping/README.rst |   4 +-
 .../models/res_partner.py                     |  16 +--
 .../models/sale_order.py                      |  14 +--
 .../models/stock_picking.py                   |   4 +-
 .../readme/DESCRIPTION.rst                    |   2 +-
 .../static/description/index.html             |   4 +-
 .../tests/__init__.py                         |   2 +-
 .../tests/common.py                           |  56 ++++++++++
 .../tests/test_invoice_mode_at_shipping.py    | 100 +-----------------
 .../tests/test_invoice_mode_group_delivery.py |  82 ++++++++++++++
 10 files changed, 164 insertions(+), 120 deletions(-)
 create mode 100644 partner_invoicing_mode_at_shipping/tests/common.py
 create mode 100644 partner_invoicing_mode_at_shipping/tests/test_invoice_mode_group_delivery.py

diff --git a/partner_invoicing_mode_at_shipping/README.rst b/partner_invoicing_mode_at_shipping/README.rst
index 37516f2e984..4c028c24029 100644
--- a/partner_invoicing_mode_at_shipping/README.rst
+++ b/partner_invoicing_mode_at_shipping/README.rst
@@ -7,7 +7,7 @@ Partner Invoicing Mode At Shipping
    !! This file is generated by oca-gen-addon-readme !!
    !! changes will be overwritten.                   !!
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-   !! source digest: sha256:c3631731c8b2841936e312dd563cdb6e41134c558ffc530d9675123065346d96
+   !! source digest: sha256:47e9c7cd8fac525769bb0981e527ee62f1fa76548509eff6a0c41cecd5222ee8
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
 .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
@@ -33,7 +33,7 @@ It is based on `partner_invoicing_mode`.
 When this mode is selected the customer will be invoiced automatically on
 delivery of the goods.
 
-Another option is the 'One Invoice Per Picking'. That one is not compatible
+Another option is the 'One Invoice Per Shipping'. That one is not compatible
 with the 'At shipping' invoicing mode. In that case, the invoicing validation
 will occur at a different moment (monthly, ...).
 
diff --git a/partner_invoicing_mode_at_shipping/models/res_partner.py b/partner_invoicing_mode_at_shipping/models/res_partner.py
index 1d9a9737f7e..e801ec25d15 100644
--- a/partner_invoicing_mode_at_shipping/models/res_partner.py
+++ b/partner_invoicing_mode_at_shipping/models/res_partner.py
@@ -13,32 +13,32 @@ class ResPartner(models.Model):
         ondelete={"at_shipping": "set default"},
     )
 
-    one_invoice_per_picking = fields.Boolean(
-        help="Check this if you want to create one invoice per picking using the"
+    one_invoice_per_shipping = fields.Boolean(
+        help="Check this if you want to create one invoice per shipping using the"
         " partner invoicing mode that should be different than 'At Shipping'."
     )
 
     @api.constrains(
-        "invoicing_mode", "one_invoice_per_picking", "one_invoice_per_order"
+        "invoicing_mode", "one_invoice_per_shipping", "one_invoice_per_order"
     )
-    def _check_invoicing_mode_one_invoice_per_picking(self):
+    def _check_invoicing_mode_one_invoice_per_shipping(self):
         for partner in self:
             if (
                 partner.invoicing_mode == "at_shipping"
-                and partner.one_invoice_per_picking
+                and partner.one_invoice_per_shipping
             ):
                 raise ValidationError(
                     _(
                         "You cannot configure the partner %(partner)s with "
-                        "Invoicing Mode 'At Shipping' and 'One Invoice Per Picking'!",
+                        "Invoicing Mode 'At Shipping' and 'One Invoice Per Shipping'!",
                         partner=partner.name,
                     ),
                 )
-            if partner.one_invoice_per_picking and partner.one_invoice_per_order:
+            if partner.one_invoice_per_shipping and partner.one_invoice_per_order:
                 raise ValidationError(
                     _(
                         "You cannot configure the partner %(partner)s with "
-                        "'One Invoice Per Order' and 'One Invoice Per Picking'!",
+                        "'One Invoice Per Order' and 'One Invoice Per Shipping'!",
                         partner=partner.name,
                     ),
                 )
diff --git a/partner_invoicing_mode_at_shipping/models/sale_order.py b/partner_invoicing_mode_at_shipping/models/sale_order.py
index 42131e8f97a..dcef8eaace3 100644
--- a/partner_invoicing_mode_at_shipping/models/sale_order.py
+++ b/partner_invoicing_mode_at_shipping/models/sale_order.py
@@ -9,21 +9,21 @@
 class SaleOrder(models.Model):
     _inherit = "sale.order"
 
-    one_invoice_per_picking = fields.Boolean(
-        compute="_compute_one_invoice_per_picking",
+    one_invoice_per_shipping = fields.Boolean(
+        compute="_compute_one_invoice_per_shipping",
         store=True,
         index=True,
     )
 
     @api.depends("partner_invoice_id")
-    def _compute_one_invoice_per_picking(self):
+    def _compute_one_invoice_per_shipping(self):
         """
         Compute this field (instead a related) to avoid computing all
         related sale orders if option changed on partner level.
         """
         for order in self:
-            order.one_invoice_per_picking = (
-                order.partner_invoice_id.one_invoice_per_picking
+            order.one_invoice_per_shipping = (
+                order.partner_invoice_id.one_invoice_per_shipping
             )
 
     def _get_generate_invoices_state_domain(self):
@@ -32,7 +32,7 @@ def _get_generate_invoices_state_domain(self):
             [
                 domain,
                 [
-                    ("one_invoice_per_picking", "=", True),
+                    ("one_invoice_per_shipping", "=", True),
                     ("invoice_ids.state", "=", "draft"),
                 ],
             ]
@@ -41,7 +41,7 @@ def _get_generate_invoices_state_domain(self):
 
     def _get_generated_invoices(self, partition):
         sales_to_validate_invoices = self.filtered(
-            lambda sale: sale.one_invoice_per_picking
+            lambda sale: sale.one_invoice_per_shipping
             and any(invoice.state == "draft" for invoice in self.invoice_ids)
         )
         sales_create_invoices = self - sales_to_validate_invoices
diff --git a/partner_invoicing_mode_at_shipping/models/stock_picking.py b/partner_invoicing_mode_at_shipping/models/stock_picking.py
index 79b234c7127..84da22bf3df 100644
--- a/partner_invoicing_mode_at_shipping/models/stock_picking.py
+++ b/partner_invoicing_mode_at_shipping/models/stock_picking.py
@@ -19,7 +19,7 @@ def _invoice_at_shipping(self):
         self.ensure_one()
         return self.picking_type_code == "outgoing" and (
             self.sale_id.partner_invoice_id.invoicing_mode == "at_shipping"
-            or self.sale_id.partner_invoice_id.one_invoice_per_picking
+            or self.sale_id.partner_invoice_id.one_invoice_per_shipping
         )
 
     def _invoicing_at_shipping(self):
@@ -37,7 +37,7 @@ def _invoicing_at_shipping(self):
             invoices |= sales_many_invoice_per_order._create_invoices(grouped=False)
         # The invoices per picking will use the invoicing_mode
         for invoice in invoices.filtered(
-            lambda invoice: not invoice.partner_id.one_invoice_per_picking
+            lambda invoice: not invoice.partner_id.one_invoice_per_shipping
         ):
             invoice.with_delay()._validate_invoice()
         return invoices or _("Nothing to invoice.")
diff --git a/partner_invoicing_mode_at_shipping/readme/DESCRIPTION.rst b/partner_invoicing_mode_at_shipping/readme/DESCRIPTION.rst
index 61022b9d7ff..b5f1abd304d 100644
--- a/partner_invoicing_mode_at_shipping/readme/DESCRIPTION.rst
+++ b/partner_invoicing_mode_at_shipping/readme/DESCRIPTION.rst
@@ -3,6 +3,6 @@ It is based on `partner_invoicing_mode`.
 When this mode is selected the customer will be invoiced automatically on
 delivery of the goods.
 
-Another option is the 'One Invoice Per Picking'. That one is not compatible
+Another option is the 'One Invoice Per Shipping'. That one is not compatible
 with the 'At shipping' invoicing mode. In that case, the invoicing validation
 will occur at a different moment (monthly, ...).
diff --git a/partner_invoicing_mode_at_shipping/static/description/index.html b/partner_invoicing_mode_at_shipping/static/description/index.html
index 96af63e7a49..cc9cf8029f4 100644
--- a/partner_invoicing_mode_at_shipping/static/description/index.html
+++ b/partner_invoicing_mode_at_shipping/static/description/index.html
@@ -367,14 +367,14 @@ <h1 class="title">Partner Invoicing Mode At Shipping</h1>
 !! This file is generated by oca-gen-addon-readme !!
 !! changes will be overwritten.                   !!
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-!! source digest: sha256:c3631731c8b2841936e312dd563cdb6e41134c558ffc530d9675123065346d96
+!! source digest: sha256:47e9c7cd8fac525769bb0981e527ee62f1fa76548509eff6a0c41cecd5222ee8
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
 <p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/account-invoicing/tree/16.0/partner_invoicing_mode_at_shipping"><img alt="OCA/account-invoicing" src="https://img.shields.io/badge/github-OCA%2Faccount--invoicing-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/account-invoicing-16-0/account-invoicing-16-0-partner_invoicing_mode_at_shipping"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/account-invoicing&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
 <p>This module allows to select a <cite>At shipping</cite> invoicing mode for a customer.
 It is based on <cite>partner_invoicing_mode</cite>.
 When this mode is selected the customer will be invoiced automatically on
 delivery of the goods.</p>
-<p>Another option is the ‘One Invoice Per Picking’. That one is not compatible
+<p>Another option is the ‘One Invoice Per Shipping’. That one is not compatible
 with the ‘At shipping’ invoicing mode. In that case, the invoicing validation
 will occur at a different moment (monthly, …).</p>
 <p><strong>Table of contents</strong></p>
diff --git a/partner_invoicing_mode_at_shipping/tests/__init__.py b/partner_invoicing_mode_at_shipping/tests/__init__.py
index 094b649436f..5fa78f34aa5 100644
--- a/partner_invoicing_mode_at_shipping/tests/__init__.py
+++ b/partner_invoicing_mode_at_shipping/tests/__init__.py
@@ -1 +1 @@
-from . import test_invoice_mode_at_shipping
+from . import test_invoice_mode_at_shipping, test_invoice_mode_group_delivery
diff --git a/partner_invoicing_mode_at_shipping/tests/common.py b/partner_invoicing_mode_at_shipping/tests/common.py
new file mode 100644
index 00000000000..0d8b587ab21
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/tests/common.py
@@ -0,0 +1,56 @@
+# Copyright 2023 ACSONE SA/NV
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+
+class InvoiceModeAtShippingCommon:
+    @classmethod
+    def setUpClass(cls):
+        super().setUpClass()
+        cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
+        cls.partner = cls.env.ref("base.res_partner_1")
+        cls.product = cls.env.ref("product.product_delivery_01")
+        cls.so1 = cls.env["sale.order"].create(
+            {
+                "partner_id": cls.partner.id,
+                "partner_invoice_id": cls.partner.id,
+                "partner_shipping_id": cls.partner.id,
+                "order_line": [
+                    (
+                        0,
+                        0,
+                        {
+                            "name": "Line one",
+                            "product_id": cls.product.id,
+                            "product_uom_qty": 4,
+                            "product_uom": cls.product.uom_id.id,
+                            "price_unit": 123,
+                        },
+                    )
+                ],
+                "pricelist_id": cls.env.ref("product.list0").id,
+            }
+        )
+
+    @classmethod
+    def _create_order(cls):
+        cls.so1 = cls.env["sale.order"].create(
+            {
+                "partner_id": cls.partner.id,
+                "partner_invoice_id": cls.partner.id,
+                "partner_shipping_id": cls.partner.id,
+                "order_line": [
+                    (
+                        0,
+                        0,
+                        {
+                            "name": "Line one",
+                            "product_id": cls.product.id,
+                            "product_uom_qty": 4,
+                            "product_uom": cls.product.uom_id.id,
+                            "price_unit": 123,
+                        },
+                    )
+                ],
+                "pricelist_id": cls.env.ref("product.list0").id,
+            }
+        )
diff --git a/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_at_shipping.py b/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_at_shipping.py
index aea177e65e9..3621c28964a 100644
--- a/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_at_shipping.py
+++ b/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_at_shipping.py
@@ -1,41 +1,17 @@
 # Copyright 2020 Camptocamp SA
 # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
 
-from odoo.exceptions import ValidationError
 from odoo.tests.common import TransactionCase
 from odoo.tools import mute_logger
 
-from odoo.addons.queue_job.tests.common import trap_jobs
+from .common import InvoiceModeAtShippingCommon
 
 
-class TestInvoiceModeAtShipping(TransactionCase):
+class TestInvoiceModeAtShipping(InvoiceModeAtShippingCommon, TransactionCase):
     @classmethod
     def setUpClass(cls):
         super().setUpClass()
-        cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
-        cls.partner = cls.env.ref("base.res_partner_1")
-        cls.product = cls.env.ref("product.product_delivery_01")
-        cls.so1 = cls.env["sale.order"].create(
-            {
-                "partner_id": cls.partner.id,
-                "partner_invoice_id": cls.partner.id,
-                "partner_shipping_id": cls.partner.id,
-                "order_line": [
-                    (
-                        0,
-                        0,
-                        {
-                            "name": "Line one",
-                            "product_id": cls.product.id,
-                            "product_uom_qty": 4,
-                            "product_uom": cls.product.uom_id.id,
-                            "price_unit": 123,
-                        },
-                    )
-                ],
-                "pricelist_id": cls.env.ref("product.list0").id,
-            }
-        )
+        cls._create_order()
 
     def test_invoice_created_at_shipping(self):
         """Check that an invoice is created when goods are shipped."""
@@ -127,73 +103,3 @@ def test_picking_backorder(self):
         self.assertTrue(
             all(invoice.state == "posted") for invoice in self.so1.invoice_ids
         )
-
-    def test_invoice_created_at_shipping_per_delivery(self):
-        """Check that an invoice is created when goods are shipped."""
-        self.partner.invoicing_mode = "standard"
-        self.partner.one_invoice_per_picking = True
-        self.so1.action_confirm()
-        picking = self.so1.picking_ids
-
-        # Deliver partially
-        picking.move_ids.quantity_done = 2.0
-        with trap_jobs() as trap:
-            picking._action_done()
-            trap.assert_enqueued_job(
-                picking._invoicing_at_shipping,
-            )
-            trap.perform_enqueued_jobs()
-
-        self.assertEqual(picking.state, "done")
-        invoice = self.so1.invoice_ids
-        # Invoice is generated but is still draft
-        self.assertEqual(
-            "draft",
-            invoice.state,
-        )
-
-        backorder = self.so1.picking_ids - picking
-        self.assertTrue(backorder)
-
-        backorder.move_ids.quantity_done = 2.0
-        with trap_jobs() as trap:
-            backorder._action_done()
-            trap.assert_enqueued_job(
-                backorder._invoicing_at_shipping,
-            )
-            with trap_jobs() as trap_invoice:
-                trap.perform_enqueued_jobs()
-                self.assertFalse(trap_invoice.enqueued_jobs)
-        invoice_2 = self.so1.invoice_ids - invoice
-        self.assertEqual(
-            "draft",
-            invoice_2.state,
-        )
-        # Launch the invoicing
-        with trap_jobs() as trap:
-            self.env["sale.order"].cron_generate_standard_invoices()
-            trap.assert_enqueued_job(
-                self.env["sale.order"]._generate_invoices_by_partner,
-                args=(self.so1.ids,),
-            )
-            with trap_jobs() as trap_invoice:
-                trap.perform_enqueued_jobs()
-                trap_invoice.assert_enqueued_job(
-                    self.so1.invoice_ids[0]._validate_invoice
-                )
-                trap_invoice.assert_enqueued_job(
-                    self.so1.invoice_ids[1]._validate_invoice
-                )
-                trap_invoice.perform_enqueued_jobs()
-        self.assertEqual("posted", invoice.state)
-        self.assertEqual("posted", invoice_2.state)
-
-    def test_invoice_created_at_shipping_per_delivery_constrains(self):
-        with self.assertRaises(ValidationError):
-            self.partner.write(
-                {"one_invoice_per_picking": True, "invoicing_mode": "at_shipping"}
-            )
-        with self.assertRaises(ValidationError):
-            self.partner.write(
-                {"one_invoice_per_order": True, "one_invoice_per_picking": True}
-            )
diff --git a/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_group_delivery.py b/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_group_delivery.py
new file mode 100644
index 00000000000..b5b0457572f
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_group_delivery.py
@@ -0,0 +1,82 @@
+# Copyright 2023 ACSONE SA/NV
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+from odoo.exceptions import ValidationError
+from odoo.tests.common import TransactionCase
+
+from odoo.addons.queue_job.tests.common import trap_jobs
+
+from .common import InvoiceModeAtShippingCommon
+
+
+class TestInvoiceModeAtShipping(InvoiceModeAtShippingCommon, TransactionCase):
+    def test_invoice_created_at_shipping_per_delivery(self):
+        """Check that an invoice is created when goods are shipped."""
+        self.partner.invoicing_mode = "standard"
+        self.partner.one_invoice_per_shipping = True
+        self._create_order()
+        self.so1.action_confirm()
+        picking = self.so1.picking_ids
+
+        # Deliver partially
+        picking.move_ids.quantity_done = 2.0
+        with trap_jobs() as trap:
+            picking._action_done()
+            trap.assert_enqueued_job(
+                picking._invoicing_at_shipping,
+            )
+            trap.perform_enqueued_jobs()
+
+        self.assertEqual(picking.state, "done")
+        invoice = self.so1.invoice_ids
+        # Invoice is generated but is still draft
+        self.assertEqual(
+            "draft",
+            invoice.state,
+        )
+
+        backorder = self.so1.picking_ids - picking
+        self.assertTrue(backorder)
+
+        backorder.move_ids.quantity_done = 2.0
+        with trap_jobs() as trap:
+            backorder._action_done()
+            trap.assert_enqueued_job(
+                backorder._invoicing_at_shipping,
+            )
+            with trap_jobs() as trap_invoice:
+                trap.perform_enqueued_jobs()
+                self.assertFalse(trap_invoice.enqueued_jobs)
+        invoice_2 = self.so1.invoice_ids - invoice
+        self.assertEqual(
+            "draft",
+            invoice_2.state,
+        )
+        # Launch the invoicing
+        with trap_jobs() as trap:
+            self.env["sale.order"].cron_generate_standard_invoices()
+            trap.assert_enqueued_job(
+                self.env["sale.order"]._generate_invoices_by_partner,
+                args=(self.so1.ids,),
+            )
+            with trap_jobs() as trap_invoice:
+                trap.perform_enqueued_jobs()
+                trap_invoice.assert_enqueued_job(
+                    self.so1.invoice_ids[0]._validate_invoice
+                )
+                trap_invoice.assert_enqueued_job(
+                    self.so1.invoice_ids[1]._validate_invoice
+                )
+                trap_invoice.perform_enqueued_jobs()
+        self.assertEqual("posted", invoice.state)
+        self.assertEqual("posted", invoice_2.state)
+
+    def test_invoice_created_at_shipping_per_delivery_constrains(self):
+        with self.assertRaises(ValidationError):
+            self.partner.write(
+                {"one_invoice_per_shipping": True, "invoicing_mode": "at_shipping"}
+            )
+        with self.assertRaises(ValidationError):
+            self.partner.write(
+                {"one_invoice_per_order": True, "one_invoice_per_shipping": True}
+            )

From 6f2260f5a034fa9c8f7ee7ef694d98a0a6d3cd3b Mon Sep 17 00:00:00 2001
From: Denis Roussel <denis.roussel@acsone.eu>
Date: Wed, 20 Dec 2023 09:50:30 +0100
Subject: [PATCH 19/32] [IMP] partner_invoicing_mode_at_shipping: Add migration
 script for 'one_invoice_per_shipping' fill in / Use draft invoices.

---
 partner_invoicing_mode_at_shipping/README.rst |  2 +-
 .../__init__.py                               |  1 +
 .../__manifest__.py                           |  3 +-
 partner_invoicing_mode_at_shipping/hooks.py   | 26 ++++++
 .../migrations/16.0.1.1.0/pre-migrate.py      | 13 +++
 .../models/res_partner.py                     |  3 +-
 .../models/sale_order.py                      | 86 +++++++++++++++----
 .../static/description/index.html             |  2 +-
 .../tests/test_invoice_mode_group_delivery.py | 12 ++-
 9 files changed, 124 insertions(+), 24 deletions(-)
 create mode 100644 partner_invoicing_mode_at_shipping/hooks.py
 create mode 100644 partner_invoicing_mode_at_shipping/migrations/16.0.1.1.0/pre-migrate.py

diff --git a/partner_invoicing_mode_at_shipping/README.rst b/partner_invoicing_mode_at_shipping/README.rst
index 4c028c24029..eeab91eedff 100644
--- a/partner_invoicing_mode_at_shipping/README.rst
+++ b/partner_invoicing_mode_at_shipping/README.rst
@@ -7,7 +7,7 @@ Partner Invoicing Mode At Shipping
    !! This file is generated by oca-gen-addon-readme !!
    !! changes will be overwritten.                   !!
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-   !! source digest: sha256:47e9c7cd8fac525769bb0981e527ee62f1fa76548509eff6a0c41cecd5222ee8
+   !! source digest: sha256:4a933620441dbc8743721220168501ad6218c0e259c57d7d5dac9258c9127a75
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
 .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
diff --git a/partner_invoicing_mode_at_shipping/__init__.py b/partner_invoicing_mode_at_shipping/__init__.py
index 0650744f6bc..6d58305f5dd 100644
--- a/partner_invoicing_mode_at_shipping/__init__.py
+++ b/partner_invoicing_mode_at_shipping/__init__.py
@@ -1 +1,2 @@
 from . import models
+from .hooks import pre_init_hook
diff --git a/partner_invoicing_mode_at_shipping/__manifest__.py b/partner_invoicing_mode_at_shipping/__manifest__.py
index b91a21ced78..b509b44c0c1 100644
--- a/partner_invoicing_mode_at_shipping/__manifest__.py
+++ b/partner_invoicing_mode_at_shipping/__manifest__.py
@@ -2,7 +2,7 @@
 # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
 {
     "name": "Partner Invoicing Mode At Shipping",
-    "version": "16.0.1.0.1",
+    "version": "16.0.1.1.0",
     "summary": "Create invoices automatically when goods are shipped.",
     "author": "Camptocamp, Odoo Community Association (OCA)",
     "website": "https://github.com/OCA/account-invoicing",
@@ -12,4 +12,5 @@
         "data/queue_job_data.xml",
     ],
     "depends": ["account", "partner_invoicing_mode", "queue_job", "stock"],
+    "pre_init_hook": "pre_init_hook",
 }
diff --git a/partner_invoicing_mode_at_shipping/hooks.py b/partner_invoicing_mode_at_shipping/hooks.py
new file mode 100644
index 00000000000..dc998200a68
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/hooks.py
@@ -0,0 +1,26 @@
+# Copyright 2023 ACSONE SA/NV
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+from openupgradelib import openupgrade
+
+from odoo import SUPERUSER_ID, api
+
+
+def _add_one_invoice_per_shipping(env):
+    if not openupgrade.column_exists(env.cr, "sale_order", "one_invoice_per_shipping"):
+        field_spec = [
+            (
+                "one_invoice_per_shipping",
+                "sale.order",
+                "sale_order",
+                "boolean",
+                "boolean",
+                "partner_invoicing_mode_at_shipping",
+                False,
+            )
+        ]
+        openupgrade.add_fields(env, field_spec)
+
+
+def pre_init_hook(cr):
+    env = api.Environment(cr, SUPERUSER_ID, {})
+    _add_one_invoice_per_shipping(env)
diff --git a/partner_invoicing_mode_at_shipping/migrations/16.0.1.1.0/pre-migrate.py b/partner_invoicing_mode_at_shipping/migrations/16.0.1.1.0/pre-migrate.py
new file mode 100644
index 00000000000..d6262c5da7b
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/migrations/16.0.1.1.0/pre-migrate.py
@@ -0,0 +1,13 @@
+# Copyright 2023 ACSONE SA/NV
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+from openupgradelib import openupgrade
+
+# pylint: disable=odoo-addons-relative-import
+from odoo.addons.partner_invoicing_mode_at_shipping.hooks import (
+    _add_one_invoice_per_shipping,
+)
+
+
+@openupgrade.migrate()
+def migrate(env, version):
+    _add_one_invoice_per_shipping(env)
diff --git a/partner_invoicing_mode_at_shipping/models/res_partner.py b/partner_invoicing_mode_at_shipping/models/res_partner.py
index e801ec25d15..2c79f448c45 100644
--- a/partner_invoicing_mode_at_shipping/models/res_partner.py
+++ b/partner_invoicing_mode_at_shipping/models/res_partner.py
@@ -14,8 +14,9 @@ class ResPartner(models.Model):
     )
 
     one_invoice_per_shipping = fields.Boolean(
+        index=True,
         help="Check this if you want to create one invoice per shipping using the"
-        " partner invoicing mode that should be different than 'At Shipping'."
+        " partner invoicing mode that should be different than 'At Shipping'.",
     )
 
     @api.constrains(
diff --git a/partner_invoicing_mode_at_shipping/models/sale_order.py b/partner_invoicing_mode_at_shipping/models/sale_order.py
index dcef8eaace3..a2c0d8a0d37 100644
--- a/partner_invoicing_mode_at_shipping/models/sale_order.py
+++ b/partner_invoicing_mode_at_shipping/models/sale_order.py
@@ -1,9 +1,6 @@
 # Copyright 2023 ACSONE SA/NV
 # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
-
-
-from odoo import api, fields, models
-from odoo.osv.expression import OR
+from odoo import _, api, fields, models
 
 
 class SaleOrder(models.Model):
@@ -26,19 +23,6 @@ def _compute_one_invoice_per_shipping(self):
                 order.partner_invoice_id.one_invoice_per_shipping
             )
 
-    def _get_generate_invoices_state_domain(self):
-        domain = super()._get_generate_invoices_state_domain()
-        domain = OR(
-            [
-                domain,
-                [
-                    ("one_invoice_per_shipping", "=", True),
-                    ("invoice_ids.state", "=", "draft"),
-                ],
-            ]
-        )
-        return domain
-
     def _get_generated_invoices(self, partition):
         sales_to_validate_invoices = self.filtered(
             lambda sale: sale.one_invoice_per_shipping
@@ -55,3 +39,71 @@ def _get_generated_invoices(self, partition):
             "invoice_ids"
         ).filtered(lambda invoice: invoice.state == "draft")
         return invoices | to_validate_invoices
+
+    def generate_invoices(
+        self,
+        companies=None,
+        invoicing_mode="standard",
+        last_execution_field="invoicing_mode_standard_last_execution",
+    ):
+        saleorders = super().generate_invoices(
+            companies=companies,
+            invoicing_mode=invoicing_mode,
+            last_execution_field=last_execution_field,
+        )
+        # Validate the preceding generated invoices in draft mode.
+        description = _(
+            "Validate the invoices generated by shipping for the "
+            "invoicing mode %(invoicing_mode_name)s"
+        )
+        self.with_delay(
+            description=description
+        )._validate_per_shipping_generated_invoices(
+            companies=companies, invoicing_mode=invoicing_mode
+        )
+
+        return saleorders
+
+    @api.model
+    def _validate_per_shipping_generated_invoices(
+        self, companies=None, invoicing_mode="standard"
+    ) -> str:
+        """
+            This will validate all draft invoices that have been generated.
+
+        :param companies: _description_, defaults to None
+        :type companies: _type_, optional
+        :param invoicing_mode: _description_, defaults to "standard"
+        :type invoicing_mode: str, optional
+        :return: String result for queue job
+        :rtype: AccountMove
+        """
+        if companies is None:
+            companies = self.env.company
+        invoices = self.env["account.move"].search(
+            self._get_per_shipping_to_validate_invoices_domain(
+                companies=companies, invoicing_mode=invoicing_mode
+            )
+        )
+        for invoice in invoices:
+            invoice.with_delay()._validate_invoice()
+        for partner, __invoices in invoices.partition("partner_id").items():
+            partner._update_next_invoice_date()
+        return ",".join(invoices.mapped("display_name"))
+
+    def _get_per_shipping_to_validate_invoices_domain(
+        self, companies, invoicing_mode="standard"
+    ) -> list:
+        """
+            This will return the domain for invoices that should be posted.
+
+        :return: Domain
+        :rtype: list
+        """
+        return [
+            ("company_id", "in", companies.ids),
+            ("move_type", "in", ("out_invoice", "out_refund")),
+            ("state", "=", "draft"),
+            ("partner_id.one_invoice_per_shipping", "=", True),
+            ("partner_id.invoicing_mode", "=", invoicing_mode),
+        ]
diff --git a/partner_invoicing_mode_at_shipping/static/description/index.html b/partner_invoicing_mode_at_shipping/static/description/index.html
index cc9cf8029f4..9a05dc83646 100644
--- a/partner_invoicing_mode_at_shipping/static/description/index.html
+++ b/partner_invoicing_mode_at_shipping/static/description/index.html
@@ -367,7 +367,7 @@ <h1 class="title">Partner Invoicing Mode At Shipping</h1>
 !! This file is generated by oca-gen-addon-readme !!
 !! changes will be overwritten.                   !!
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-!! source digest: sha256:47e9c7cd8fac525769bb0981e527ee62f1fa76548509eff6a0c41cecd5222ee8
+!! source digest: sha256:4a933620441dbc8743721220168501ad6218c0e259c57d7d5dac9258c9127a75
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
 <p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/account-invoicing/tree/16.0/partner_invoicing_mode_at_shipping"><img alt="OCA/account-invoicing" src="https://img.shields.io/badge/github-OCA%2Faccount--invoicing-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/account-invoicing-16-0/account-invoicing-16-0-partner_invoicing_mode_at_shipping"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/account-invoicing&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
 <p>This module allows to select a <cite>At shipping</cite> invoicing mode for a customer.
diff --git a/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_group_delivery.py b/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_group_delivery.py
index b5b0457572f..fa44a7ad3da 100644
--- a/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_group_delivery.py
+++ b/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_group_delivery.py
@@ -9,7 +9,12 @@
 from .common import InvoiceModeAtShippingCommon
 
 
-class TestInvoiceModeAtShipping(InvoiceModeAtShippingCommon, TransactionCase):
+class TestInvoiceModeAtShippingGrouped(InvoiceModeAtShippingCommon, TransactionCase):
+    @classmethod
+    def setUpClass(cls):
+        super().setUpClass()
+        cls.companies = cls.env["res.company"].search([])
+
     def test_invoice_created_at_shipping_per_delivery(self):
         """Check that an invoice is created when goods are shipped."""
         self.partner.invoicing_mode = "standard"
@@ -56,8 +61,9 @@ def test_invoice_created_at_shipping_per_delivery(self):
         with trap_jobs() as trap:
             self.env["sale.order"].cron_generate_standard_invoices()
             trap.assert_enqueued_job(
-                self.env["sale.order"]._generate_invoices_by_partner,
-                args=(self.so1.ids,),
+                self.env["sale.order"]._validate_per_shipping_generated_invoices,
+                args=(),
+                kwargs={"companies": self.companies, "invoicing_mode": "standard"},
             )
             with trap_jobs() as trap_invoice:
                 trap.perform_enqueued_jobs()

From 382813f3b7fc25ef475cde5d65f12758431062d1 Mon Sep 17 00:00:00 2001
From: Denis Roussel <denis.roussel@acsone.eu>
Date: Wed, 20 Dec 2023 14:07:11 +0100
Subject: [PATCH 20/32] [IMP] partner_invoicing_mode_at_shipping: Add
 'one_invoice_per_shipping' option on res_partner view

---
 partner_invoicing_mode_at_shipping/README.rst  |  2 +-
 .../__manifest__.py                            |  1 +
 .../static/description/index.html              |  2 +-
 .../views/res_partner.xml                      | 18 ++++++++++++++++++
 4 files changed, 21 insertions(+), 2 deletions(-)
 create mode 100644 partner_invoicing_mode_at_shipping/views/res_partner.xml

diff --git a/partner_invoicing_mode_at_shipping/README.rst b/partner_invoicing_mode_at_shipping/README.rst
index eeab91eedff..c78a717e150 100644
--- a/partner_invoicing_mode_at_shipping/README.rst
+++ b/partner_invoicing_mode_at_shipping/README.rst
@@ -7,7 +7,7 @@ Partner Invoicing Mode At Shipping
    !! This file is generated by oca-gen-addon-readme !!
    !! changes will be overwritten.                   !!
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-   !! source digest: sha256:4a933620441dbc8743721220168501ad6218c0e259c57d7d5dac9258c9127a75
+   !! source digest: sha256:f78d0b18a4b7ce5c35159cb8af97f7a9a5926b8d073db42984e3683b000ab3b9
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
 .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
diff --git a/partner_invoicing_mode_at_shipping/__manifest__.py b/partner_invoicing_mode_at_shipping/__manifest__.py
index b509b44c0c1..97347936f8c 100644
--- a/partner_invoicing_mode_at_shipping/__manifest__.py
+++ b/partner_invoicing_mode_at_shipping/__manifest__.py
@@ -10,6 +10,7 @@
     "category": "Accounting & Finance",
     "data": [
         "data/queue_job_data.xml",
+        "views/res_partner.xml",
     ],
     "depends": ["account", "partner_invoicing_mode", "queue_job", "stock"],
     "pre_init_hook": "pre_init_hook",
diff --git a/partner_invoicing_mode_at_shipping/static/description/index.html b/partner_invoicing_mode_at_shipping/static/description/index.html
index 9a05dc83646..b66eac48955 100644
--- a/partner_invoicing_mode_at_shipping/static/description/index.html
+++ b/partner_invoicing_mode_at_shipping/static/description/index.html
@@ -367,7 +367,7 @@ <h1 class="title">Partner Invoicing Mode At Shipping</h1>
 !! This file is generated by oca-gen-addon-readme !!
 !! changes will be overwritten.                   !!
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-!! source digest: sha256:4a933620441dbc8743721220168501ad6218c0e259c57d7d5dac9258c9127a75
+!! source digest: sha256:f78d0b18a4b7ce5c35159cb8af97f7a9a5926b8d073db42984e3683b000ab3b9
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
 <p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/account-invoicing/tree/16.0/partner_invoicing_mode_at_shipping"><img alt="OCA/account-invoicing" src="https://img.shields.io/badge/github-OCA%2Faccount--invoicing-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/account-invoicing-16-0/account-invoicing-16-0-partner_invoicing_mode_at_shipping"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/account-invoicing&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
 <p>This module allows to select a <cite>At shipping</cite> invoicing mode for a customer.
diff --git a/partner_invoicing_mode_at_shipping/views/res_partner.xml b/partner_invoicing_mode_at_shipping/views/res_partner.xml
new file mode 100644
index 00000000000..00ebcef0dfb
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/views/res_partner.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!-- Copyright 2023 ACSONE SA/NV
+     License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
+<odoo>
+    <record id="view_partner_property_form" model="ir.ui.view">
+        <field name="name">view_partner_property_form</field>
+        <field name="model">res.partner</field>
+        <field
+            name="inherit_id"
+            ref="partner_invoicing_mode.view_partner_property_form"
+        />
+        <field name="arch" type="xml">
+            <field name="one_invoice_per_order" position="after">
+                <field name="one_invoice_per_shipping" />
+            </field>
+        </field>
+    </record>
+</odoo>

From ac358ff73cdc5ebdc96a8f7e95e6c791aa850f56 Mon Sep 17 00:00:00 2001
From: Denis Roussel <denis.roussel@acsone.eu>
Date: Fri, 22 Dec 2023 14:53:59 +0100
Subject: [PATCH 21/32] [IMP] partner_invoicing_mode_at_shipping: Remove unused
 function

---
 .../models/sale_order.py                        | 17 -----------------
 1 file changed, 17 deletions(-)

diff --git a/partner_invoicing_mode_at_shipping/models/sale_order.py b/partner_invoicing_mode_at_shipping/models/sale_order.py
index a2c0d8a0d37..4b1093cf310 100644
--- a/partner_invoicing_mode_at_shipping/models/sale_order.py
+++ b/partner_invoicing_mode_at_shipping/models/sale_order.py
@@ -23,23 +23,6 @@ def _compute_one_invoice_per_shipping(self):
                 order.partner_invoice_id.one_invoice_per_shipping
             )
 
-    def _get_generated_invoices(self, partition):
-        sales_to_validate_invoices = self.filtered(
-            lambda sale: sale.one_invoice_per_shipping
-            and any(invoice.state == "draft" for invoice in self.invoice_ids)
-        )
-        sales_create_invoices = self - sales_to_validate_invoices
-        if sales_create_invoices:
-            invoices = super(SaleOrder, sales_create_invoices)._get_generated_invoices(
-                partition
-            )
-        else:
-            invoices = self.env["account.move"].browse()
-        to_validate_invoices = sales_to_validate_invoices.mapped(
-            "invoice_ids"
-        ).filtered(lambda invoice: invoice.state == "draft")
-        return invoices | to_validate_invoices
-
     def generate_invoices(
         self,
         companies=None,

From f5fa1b3015a727ed9426bd12bbe6095c51376b21 Mon Sep 17 00:00:00 2001
From: Denis Roussel <denis.roussel@acsone.eu>
Date: Thu, 8 Feb 2024 08:53:41 +0100
Subject: [PATCH 22/32] [FIX] partner_invoicing_mode_at_shipping: Add
 one_invoice_per_shipping to commercial_fields

---
 partner_invoicing_mode_at_shipping/models/res_partner.py | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/partner_invoicing_mode_at_shipping/models/res_partner.py b/partner_invoicing_mode_at_shipping/models/res_partner.py
index 2c79f448c45..7c3fa457544 100644
--- a/partner_invoicing_mode_at_shipping/models/res_partner.py
+++ b/partner_invoicing_mode_at_shipping/models/res_partner.py
@@ -19,6 +19,12 @@ class ResPartner(models.Model):
         " partner invoicing mode that should be different than 'At Shipping'.",
     )
 
+    @api.model
+    def _commercial_fields(self):
+        return super()._commercial_fields() + [
+            "one_invoice_per_shipping",
+        ]
+
     @api.constrains(
         "invoicing_mode", "one_invoice_per_shipping", "one_invoice_per_order"
     )

From a8fe4e221ec1b46b55cd7ce734694ceb9e933e7a Mon Sep 17 00:00:00 2001
From: Tran Anh Tuan <anhtuan@trobz.com>
Date: Thu, 28 Mar 2024 15:19:23 +0700
Subject: [PATCH 23/32] [IMP] partner_invoicing_mode_at_shipping: Extract
 _invoicing_at_shipping_validation function and add option auto validate
 invoice on partner

---
 .../models/stock_picking.py                              | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/partner_invoicing_mode_at_shipping/models/stock_picking.py b/partner_invoicing_mode_at_shipping/models/stock_picking.py
index 84da22bf3df..ee5edfee2a0 100644
--- a/partner_invoicing_mode_at_shipping/models/stock_picking.py
+++ b/partner_invoicing_mode_at_shipping/models/stock_picking.py
@@ -22,6 +22,11 @@ def _invoice_at_shipping(self):
             or self.sale_id.partner_invoice_id.one_invoice_per_shipping
         )
 
+    def _invoicing_at_shipping_validation(self, invoices):
+        return invoices.filtered(
+            lambda invoice: invoice.partner_id.invoicing_mode == "at_shipping"
+        )
+
     def _invoicing_at_shipping(self):
         self.ensure_one()
         sales = self._get_sales_order_to_invoice()
@@ -36,9 +41,7 @@ def _invoicing_at_shipping(self):
         if sales_many_invoice_per_order:
             invoices |= sales_many_invoice_per_order._create_invoices(grouped=False)
         # The invoices per picking will use the invoicing_mode
-        for invoice in invoices.filtered(
-            lambda invoice: not invoice.partner_id.one_invoice_per_shipping
-        ):
+        for invoice in self._invoicing_at_shipping_validation(invoices):
             invoice.with_delay()._validate_invoice()
         return invoices or _("Nothing to invoice.")
 

From 73eab0ae9dae2af4486a4fa2ac81f76f0b00e377 Mon Sep 17 00:00:00 2001
From: oca-ci <oca-ci@odoo-community.org>
Date: Thu, 27 Jun 2024 08:16:52 +0000
Subject: [PATCH 24/32] [UPD] Update partner_invoicing_mode_at_shipping.pot

---
 .../partner_invoicing_mode_at_shipping.pot    | 47 +++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/partner_invoicing_mode_at_shipping/i18n/partner_invoicing_mode_at_shipping.pot b/partner_invoicing_mode_at_shipping/i18n/partner_invoicing_mode_at_shipping.pot
index 2a52ab4c717..801cb53f05f 100644
--- a/partner_invoicing_mode_at_shipping/i18n/partner_invoicing_mode_at_shipping.pot
+++ b/partner_invoicing_mode_at_shipping/i18n/partner_invoicing_mode_at_shipping.pot
@@ -18,6 +18,14 @@ msgstr ""
 msgid "At Shipping"
 msgstr ""
 
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model.fields,help:partner_invoicing_mode_at_shipping.field_res_partner__one_invoice_per_shipping
+#: model:ir.model.fields,help:partner_invoicing_mode_at_shipping.field_res_users__one_invoice_per_shipping
+msgid ""
+"Check this if you want to create one invoice per shipping using the partner "
+"invoicing mode that should be different than 'At Shipping'."
+msgstr ""
+
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model,name:partner_invoicing_mode_at_shipping.model_res_partner
 msgid "Contact"
@@ -36,6 +44,18 @@ msgstr ""
 msgid "Nothing to invoice."
 msgstr ""
 
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_res_partner__one_invoice_per_shipping
+#: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_res_users__one_invoice_per_shipping
+#: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_sale_order__one_invoice_per_shipping
+msgid "One Invoice Per Shipping"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model,name:partner_invoicing_mode_at_shipping.model_sale_order
+msgid "Sales Order"
+msgstr ""
+
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model,name:partner_invoicing_mode_at_shipping.model_stock_move
 msgid "Stock Move"
@@ -45,3 +65,30 @@ msgstr ""
 #: model:ir.model,name:partner_invoicing_mode_at_shipping.model_stock_picking
 msgid "Transfer"
 msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#. odoo-python
+#: code:addons/partner_invoicing_mode_at_shipping/models/sale_order.py:0
+#, python-format
+msgid ""
+"Validate the invoices generated by shipping for the invoicing mode "
+"%(invoicing_mode_name)s"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#. odoo-python
+#: code:addons/partner_invoicing_mode_at_shipping/models/res_partner.py:0
+#, python-format
+msgid ""
+"You cannot configure the partner %(partner)s with 'One Invoice Per Order' "
+"and 'One Invoice Per Shipping'!"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#. odoo-python
+#: code:addons/partner_invoicing_mode_at_shipping/models/res_partner.py:0
+#, python-format
+msgid ""
+"You cannot configure the partner %(partner)s with Invoicing Mode 'At "
+"Shipping' and 'One Invoice Per Shipping'!"
+msgstr ""

From 57048eaf2e62e79252e8983a881c353dd98cb178 Mon Sep 17 00:00:00 2001
From: OCA-git-bot <oca-git-bot@odoo-community.org>
Date: Thu, 27 Jun 2024 08:24:59 +0000
Subject: [PATCH 25/32] [BOT] post-merge updates

---
 partner_invoicing_mode_at_shipping/README.rst                  | 2 +-
 partner_invoicing_mode_at_shipping/__manifest__.py             | 2 +-
 .../static/description/index.html                              | 3 +--
 3 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/partner_invoicing_mode_at_shipping/README.rst b/partner_invoicing_mode_at_shipping/README.rst
index c78a717e150..482b5d7dd5c 100644
--- a/partner_invoicing_mode_at_shipping/README.rst
+++ b/partner_invoicing_mode_at_shipping/README.rst
@@ -7,7 +7,7 @@ Partner Invoicing Mode At Shipping
    !! This file is generated by oca-gen-addon-readme !!
    !! changes will be overwritten.                   !!
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-   !! source digest: sha256:f78d0b18a4b7ce5c35159cb8af97f7a9a5926b8d073db42984e3683b000ab3b9
+   !! source digest: sha256:6f96589039ddad82b6acdcd148f04264085935d83c2fc147507bf3ab3ae41c1b
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
 .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
diff --git a/partner_invoicing_mode_at_shipping/__manifest__.py b/partner_invoicing_mode_at_shipping/__manifest__.py
index 97347936f8c..bb14468e348 100644
--- a/partner_invoicing_mode_at_shipping/__manifest__.py
+++ b/partner_invoicing_mode_at_shipping/__manifest__.py
@@ -2,7 +2,7 @@
 # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
 {
     "name": "Partner Invoicing Mode At Shipping",
-    "version": "16.0.1.1.0",
+    "version": "16.0.1.2.0",
     "summary": "Create invoices automatically when goods are shipped.",
     "author": "Camptocamp, Odoo Community Association (OCA)",
     "website": "https://github.com/OCA/account-invoicing",
diff --git a/partner_invoicing_mode_at_shipping/static/description/index.html b/partner_invoicing_mode_at_shipping/static/description/index.html
index b66eac48955..3e22980a80e 100644
--- a/partner_invoicing_mode_at_shipping/static/description/index.html
+++ b/partner_invoicing_mode_at_shipping/static/description/index.html
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="utf-8"?>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
@@ -367,7 +366,7 @@ <h1 class="title">Partner Invoicing Mode At Shipping</h1>
 !! This file is generated by oca-gen-addon-readme !!
 !! changes will be overwritten.                   !!
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-!! source digest: sha256:f78d0b18a4b7ce5c35159cb8af97f7a9a5926b8d073db42984e3683b000ab3b9
+!! source digest: sha256:6f96589039ddad82b6acdcd148f04264085935d83c2fc147507bf3ab3ae41c1b
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
 <p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/account-invoicing/tree/16.0/partner_invoicing_mode_at_shipping"><img alt="OCA/account-invoicing" src="https://img.shields.io/badge/github-OCA%2Faccount--invoicing-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/account-invoicing-16-0/account-invoicing-16-0-partner_invoicing_mode_at_shipping"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/account-invoicing&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
 <p>This module allows to select a <cite>At shipping</cite> invoicing mode for a customer.

From 301ef09152efa7366357ba81a0f7d2b0bd593c7c Mon Sep 17 00:00:00 2001
From: Weblate <noreply@weblate.org>
Date: Thu, 27 Jun 2024 08:25:07 +0000
Subject: [PATCH 26/32] Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translation: account-invoicing-16.0/account-invoicing-16.0-partner_invoicing_mode_at_shipping
Translate-URL: https://translation.odoo-community.org/projects/account-invoicing-16-0/account-invoicing-16-0-partner_invoicing_mode_at_shipping/
---
 partner_invoicing_mode_at_shipping/i18n/es.po | 47 +++++++++++++++++++
 partner_invoicing_mode_at_shipping/i18n/it.po | 47 +++++++++++++++++++
 2 files changed, 94 insertions(+)

diff --git a/partner_invoicing_mode_at_shipping/i18n/es.po b/partner_invoicing_mode_at_shipping/i18n/es.po
index f4d4670aad8..446724a6273 100644
--- a/partner_invoicing_mode_at_shipping/i18n/es.po
+++ b/partner_invoicing_mode_at_shipping/i18n/es.po
@@ -21,6 +21,14 @@ msgstr ""
 msgid "At Shipping"
 msgstr "En envío"
 
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model.fields,help:partner_invoicing_mode_at_shipping.field_res_partner__one_invoice_per_shipping
+#: model:ir.model.fields,help:partner_invoicing_mode_at_shipping.field_res_users__one_invoice_per_shipping
+msgid ""
+"Check this if you want to create one invoice per shipping using the partner "
+"invoicing mode that should be different than 'At Shipping'."
+msgstr ""
+
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model,name:partner_invoicing_mode_at_shipping.model_res_partner
 msgid "Contact"
@@ -39,6 +47,18 @@ msgstr "Modo de facturación"
 msgid "Nothing to invoice."
 msgstr "Nada para Facturar."
 
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_res_partner__one_invoice_per_shipping
+#: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_res_users__one_invoice_per_shipping
+#: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_sale_order__one_invoice_per_shipping
+msgid "One Invoice Per Shipping"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model,name:partner_invoicing_mode_at_shipping.model_sale_order
+msgid "Sales Order"
+msgstr ""
+
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model,name:partner_invoicing_mode_at_shipping.model_stock_move
 msgid "Stock Move"
@@ -48,3 +68,30 @@ msgstr "Movimiento de existencias"
 #: model:ir.model,name:partner_invoicing_mode_at_shipping.model_stock_picking
 msgid "Transfer"
 msgstr "Transferencia"
+
+#. module: partner_invoicing_mode_at_shipping
+#. odoo-python
+#: code:addons/partner_invoicing_mode_at_shipping/models/sale_order.py:0
+#, python-format
+msgid ""
+"Validate the invoices generated by shipping for the invoicing mode "
+"%(invoicing_mode_name)s"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#. odoo-python
+#: code:addons/partner_invoicing_mode_at_shipping/models/res_partner.py:0
+#, python-format
+msgid ""
+"You cannot configure the partner %(partner)s with 'One Invoice Per Order' "
+"and 'One Invoice Per Shipping'!"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#. odoo-python
+#: code:addons/partner_invoicing_mode_at_shipping/models/res_partner.py:0
+#, python-format
+msgid ""
+"You cannot configure the partner %(partner)s with Invoicing Mode 'At "
+"Shipping' and 'One Invoice Per Shipping'!"
+msgstr ""
diff --git a/partner_invoicing_mode_at_shipping/i18n/it.po b/partner_invoicing_mode_at_shipping/i18n/it.po
index d3604a05e5a..068bee427bf 100644
--- a/partner_invoicing_mode_at_shipping/i18n/it.po
+++ b/partner_invoicing_mode_at_shipping/i18n/it.po
@@ -21,6 +21,14 @@ msgstr ""
 msgid "At Shipping"
 msgstr "Alla spedizione"
 
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model.fields,help:partner_invoicing_mode_at_shipping.field_res_partner__one_invoice_per_shipping
+#: model:ir.model.fields,help:partner_invoicing_mode_at_shipping.field_res_users__one_invoice_per_shipping
+msgid ""
+"Check this if you want to create one invoice per shipping using the partner "
+"invoicing mode that should be different than 'At Shipping'."
+msgstr ""
+
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model,name:partner_invoicing_mode_at_shipping.model_res_partner
 msgid "Contact"
@@ -39,6 +47,18 @@ msgstr "Modo fatturazione"
 msgid "Nothing to invoice."
 msgstr "Nulla da fatturare."
 
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_res_partner__one_invoice_per_shipping
+#: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_res_users__one_invoice_per_shipping
+#: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_sale_order__one_invoice_per_shipping
+msgid "One Invoice Per Shipping"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model,name:partner_invoicing_mode_at_shipping.model_sale_order
+msgid "Sales Order"
+msgstr ""
+
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model,name:partner_invoicing_mode_at_shipping.model_stock_move
 msgid "Stock Move"
@@ -48,3 +68,30 @@ msgstr "Movimento di magazzino"
 #: model:ir.model,name:partner_invoicing_mode_at_shipping.model_stock_picking
 msgid "Transfer"
 msgstr "Trasferimento"
+
+#. module: partner_invoicing_mode_at_shipping
+#. odoo-python
+#: code:addons/partner_invoicing_mode_at_shipping/models/sale_order.py:0
+#, python-format
+msgid ""
+"Validate the invoices generated by shipping for the invoicing mode "
+"%(invoicing_mode_name)s"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#. odoo-python
+#: code:addons/partner_invoicing_mode_at_shipping/models/res_partner.py:0
+#, python-format
+msgid ""
+"You cannot configure the partner %(partner)s with 'One Invoice Per Order' "
+"and 'One Invoice Per Shipping'!"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#. odoo-python
+#: code:addons/partner_invoicing_mode_at_shipping/models/res_partner.py:0
+#, python-format
+msgid ""
+"You cannot configure the partner %(partner)s with Invoicing Mode 'At "
+"Shipping' and 'One Invoice Per Shipping'!"
+msgstr ""

From 6c4bec37c0e7f4d30ed9d1481db962241ab18562 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Anna=20Mart=C3=ADnez?= <anna080678@gmail.com>
Date: Sat, 29 Jun 2024 08:34:35 +0000
Subject: [PATCH 27/32] Translated using Weblate (Spanish)

Currently translated at 58.3% (7 of 12 strings)

Translation: account-invoicing-16.0/account-invoicing-16.0-partner_invoicing_mode_at_shipping
Translate-URL: https://translation.odoo-community.org/projects/account-invoicing-16-0/account-invoicing-16-0-partner_invoicing_mode_at_shipping/es/
---
 partner_invoicing_mode_at_shipping/i18n/es.po | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/partner_invoicing_mode_at_shipping/i18n/es.po b/partner_invoicing_mode_at_shipping/i18n/es.po
index 446724a6273..61af664fb58 100644
--- a/partner_invoicing_mode_at_shipping/i18n/es.po
+++ b/partner_invoicing_mode_at_shipping/i18n/es.po
@@ -6,8 +6,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Odoo Server 16.0\n"
 "Report-Msgid-Bugs-To: \n"
-"PO-Revision-Date: 2023-07-29 10:09+0000\n"
-"Last-Translator: Ivorra78 <informatica@totmaterial.es>\n"
+"PO-Revision-Date: 2024-06-29 10:47+0000\n"
+"Last-Translator: Anna Martínez <anna080678@gmail.com>\n"
 "Language-Team: none\n"
 "Language: es\n"
 "MIME-Version: 1.0\n"
@@ -57,7 +57,7 @@ msgstr ""
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model,name:partner_invoicing_mode_at_shipping.model_sale_order
 msgid "Sales Order"
-msgstr ""
+msgstr "Pedido de venta"
 
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model,name:partner_invoicing_mode_at_shipping.model_stock_move

From f334eed90cfb55a4f25d4f24e961145184ca02b2 Mon Sep 17 00:00:00 2001
From: mymage <stefano.consolaro@mymage.it>
Date: Mon, 15 Jul 2024 07:24:27 +0000
Subject: [PATCH 28/32] Translated using Weblate (Italian)

Currently translated at 100.0% (12 of 12 strings)

Translation: account-invoicing-16.0/account-invoicing-16.0-partner_invoicing_mode_at_shipping
Translate-URL: https://translation.odoo-community.org/projects/account-invoicing-16-0/account-invoicing-16-0-partner_invoicing_mode_at_shipping/it/
---
 partner_invoicing_mode_at_shipping/i18n/it.po | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/partner_invoicing_mode_at_shipping/i18n/it.po b/partner_invoicing_mode_at_shipping/i18n/it.po
index 068bee427bf..5082725eec0 100644
--- a/partner_invoicing_mode_at_shipping/i18n/it.po
+++ b/partner_invoicing_mode_at_shipping/i18n/it.po
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Odoo Server 16.0\n"
 "Report-Msgid-Bugs-To: \n"
-"PO-Revision-Date: 2024-02-27 12:11+0000\n"
+"PO-Revision-Date: 2024-07-15 07:37+0000\n"
 "Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
 "Language-Team: none\n"
 "Language: it\n"
@@ -14,7 +14,7 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: \n"
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.17\n"
+"X-Generator: Weblate 5.6.2\n"
 
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model.fields.selection,name:partner_invoicing_mode_at_shipping.selection__res_partner__invoicing_mode__at_shipping
@@ -28,6 +28,9 @@ msgid ""
 "Check this if you want to create one invoice per shipping using the partner "
 "invoicing mode that should be different than 'At Shipping'."
 msgstr ""
+"Selezionare questa opzione se si vuole creare una fattura per spedizione "
+"utilizzando il modo di fatturazione del partner che deve essere diverso da "
+"'Alla spedizione'."
 
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model,name:partner_invoicing_mode_at_shipping.model_res_partner
@@ -52,12 +55,12 @@ msgstr "Nulla da fatturare."
 #: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_res_users__one_invoice_per_shipping
 #: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_sale_order__one_invoice_per_shipping
 msgid "One Invoice Per Shipping"
-msgstr ""
+msgstr "Una fattura per spedizione"
 
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model,name:partner_invoicing_mode_at_shipping.model_sale_order
 msgid "Sales Order"
-msgstr ""
+msgstr "Ordine di vendita"
 
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model,name:partner_invoicing_mode_at_shipping.model_stock_move
@@ -77,6 +80,8 @@ msgid ""
 "Validate the invoices generated by shipping for the invoicing mode "
 "%(invoicing_mode_name)s"
 msgstr ""
+"Validare la fattura generata dalla spedizione per il metodo di fatturazione "
+"%(invoicing_mode_name)s"
 
 #. module: partner_invoicing_mode_at_shipping
 #. odoo-python
@@ -86,6 +91,8 @@ msgid ""
 "You cannot configure the partner %(partner)s with 'One Invoice Per Order' "
 "and 'One Invoice Per Shipping'!"
 msgstr ""
+"Non si può configurare il partner %(partner)s con 'Una fattura per ordine' e "
+"'Una fattura per spedizione'!"
 
 #. module: partner_invoicing_mode_at_shipping
 #. odoo-python
@@ -95,3 +102,5 @@ msgid ""
 "You cannot configure the partner %(partner)s with Invoicing Mode 'At "
 "Shipping' and 'One Invoice Per Shipping'!"
 msgstr ""
+"Non si può configurare il partner %(partner)s con il metodo di fatturazione "
+"'Alla spedizione' e 'Una fattura per spedizione'!"

From ab930467ce9695183b148c2b6bf60d69462e3114 Mon Sep 17 00:00:00 2001
From: samibc2c <sami.bouzidi@camptocamp.com>
Date: Wed, 6 Nov 2024 13:02:43 +0000
Subject: [PATCH 29/32] Added translation using Weblate (French)

---
 partner_invoicing_mode_at_shipping/i18n/fr.po | 95 +++++++++++++++++++
 1 file changed, 95 insertions(+)
 create mode 100644 partner_invoicing_mode_at_shipping/i18n/fr.po

diff --git a/partner_invoicing_mode_at_shipping/i18n/fr.po b/partner_invoicing_mode_at_shipping/i18n/fr.po
new file mode 100644
index 00000000000..74136131bc6
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/i18n/fr.po
@@ -0,0 +1,95 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# 	* partner_invoicing_mode_at_shipping
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 16.0\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: fr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=n > 1;\n"
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model.fields.selection,name:partner_invoicing_mode_at_shipping.selection__res_partner__invoicing_mode__at_shipping
+msgid "At Shipping"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model.fields,help:partner_invoicing_mode_at_shipping.field_res_partner__one_invoice_per_shipping
+#: model:ir.model.fields,help:partner_invoicing_mode_at_shipping.field_res_users__one_invoice_per_shipping
+msgid ""
+"Check this if you want to create one invoice per shipping using the partner "
+"invoicing mode that should be different than 'At Shipping'."
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model,name:partner_invoicing_mode_at_shipping.model_res_partner
+msgid "Contact"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_res_partner__invoicing_mode
+#: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_res_users__invoicing_mode
+msgid "Invoicing Mode"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#. odoo-python
+#: code:addons/partner_invoicing_mode_at_shipping/models/stock_picking.py:0
+#, python-format
+msgid "Nothing to invoice."
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_res_partner__one_invoice_per_shipping
+#: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_res_users__one_invoice_per_shipping
+#: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_sale_order__one_invoice_per_shipping
+msgid "One Invoice Per Shipping"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model,name:partner_invoicing_mode_at_shipping.model_sale_order
+msgid "Sales Order"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model,name:partner_invoicing_mode_at_shipping.model_stock_move
+msgid "Stock Move"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#: model:ir.model,name:partner_invoicing_mode_at_shipping.model_stock_picking
+msgid "Transfer"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#. odoo-python
+#: code:addons/partner_invoicing_mode_at_shipping/models/sale_order.py:0
+#, python-format
+msgid ""
+"Validate the invoices generated by shipping for the invoicing mode "
+"%(invoicing_mode_name)s"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#. odoo-python
+#: code:addons/partner_invoicing_mode_at_shipping/models/res_partner.py:0
+#, python-format
+msgid ""
+"You cannot configure the partner %(partner)s with 'One Invoice Per Order' "
+"and 'One Invoice Per Shipping'!"
+msgstr ""
+
+#. module: partner_invoicing_mode_at_shipping
+#. odoo-python
+#: code:addons/partner_invoicing_mode_at_shipping/models/res_partner.py:0
+#, python-format
+msgid ""
+"You cannot configure the partner %(partner)s with Invoicing Mode 'At "
+"Shipping' and 'One Invoice Per Shipping'!"
+msgstr ""

From e8c0f9e9b2f9f18f5bb7118d28063bb52050882a Mon Sep 17 00:00:00 2001
From: samibc2c <sami.bouzidi@camptocamp.com>
Date: Wed, 6 Nov 2024 13:03:31 +0000
Subject: [PATCH 30/32] Translated using Weblate (French)

Currently translated at 100.0% (12 of 12 strings)

Translation: account-invoicing-16.0/account-invoicing-16.0-partner_invoicing_mode_at_shipping
Translate-URL: https://translation.odoo-community.org/projects/account-invoicing-16-0/account-invoicing-16-0-partner_invoicing_mode_at_shipping/fr/
---
 partner_invoicing_mode_at_shipping/i18n/fr.po | 29 +++++++++++++------
 1 file changed, 20 insertions(+), 9 deletions(-)

diff --git a/partner_invoicing_mode_at_shipping/i18n/fr.po b/partner_invoicing_mode_at_shipping/i18n/fr.po
index 74136131bc6..a0cca2a2d9c 100644
--- a/partner_invoicing_mode_at_shipping/i18n/fr.po
+++ b/partner_invoicing_mode_at_shipping/i18n/fr.po
@@ -6,18 +6,20 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Odoo Server 16.0\n"
 "Report-Msgid-Bugs-To: \n"
-"Last-Translator: Automatically generated\n"
+"PO-Revision-Date: 2024-11-06 14:06+0000\n"
+"Last-Translator: samibc2c <sami.bouzidi@camptocamp.com>\n"
 "Language-Team: none\n"
 "Language: fr\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: \n"
 "Plural-Forms: nplurals=2; plural=n > 1;\n"
+"X-Generator: Weblate 5.6.2\n"
 
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model.fields.selection,name:partner_invoicing_mode_at_shipping.selection__res_partner__invoicing_mode__at_shipping
 msgid "At Shipping"
-msgstr ""
+msgstr "A l'expédition"
 
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model.fields,help:partner_invoicing_mode_at_shipping.field_res_partner__one_invoice_per_shipping
@@ -26,46 +28,49 @@ msgid ""
 "Check this if you want to create one invoice per shipping using the partner "
 "invoicing mode that should be different than 'At Shipping'."
 msgstr ""
+"Cochez si vous souhaitez créer une facture par expédition en utilisant le "
+"mode de facturation du partenaire, qui doit être différent de 'A "
+"l'expédition'."
 
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model,name:partner_invoicing_mode_at_shipping.model_res_partner
 msgid "Contact"
-msgstr ""
+msgstr "Contact"
 
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_res_partner__invoicing_mode
 #: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_res_users__invoicing_mode
 msgid "Invoicing Mode"
-msgstr ""
+msgstr "Mode de facturation"
 
 #. module: partner_invoicing_mode_at_shipping
 #. odoo-python
 #: code:addons/partner_invoicing_mode_at_shipping/models/stock_picking.py:0
 #, python-format
 msgid "Nothing to invoice."
-msgstr ""
+msgstr "Rien à facturer."
 
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_res_partner__one_invoice_per_shipping
 #: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_res_users__one_invoice_per_shipping
 #: model:ir.model.fields,field_description:partner_invoicing_mode_at_shipping.field_sale_order__one_invoice_per_shipping
 msgid "One Invoice Per Shipping"
-msgstr ""
+msgstr "Une facture par expédition"
 
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model,name:partner_invoicing_mode_at_shipping.model_sale_order
 msgid "Sales Order"
-msgstr ""
+msgstr "Bon de commande"
 
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model,name:partner_invoicing_mode_at_shipping.model_stock_move
 msgid "Stock Move"
-msgstr ""
+msgstr "Mouvement de stock"
 
 #. module: partner_invoicing_mode_at_shipping
 #: model:ir.model,name:partner_invoicing_mode_at_shipping.model_stock_picking
 msgid "Transfer"
-msgstr ""
+msgstr "Transfert"
 
 #. module: partner_invoicing_mode_at_shipping
 #. odoo-python
@@ -75,6 +80,8 @@ msgid ""
 "Validate the invoices generated by shipping for the invoicing mode "
 "%(invoicing_mode_name)s"
 msgstr ""
+"Valider les factures générées par l'expédition pour le mode de facturation "
+"%(invoicing_mode_name)s"
 
 #. module: partner_invoicing_mode_at_shipping
 #. odoo-python
@@ -84,6 +91,8 @@ msgid ""
 "You cannot configure the partner %(partner)s with 'One Invoice Per Order' "
 "and 'One Invoice Per Shipping'!"
 msgstr ""
+"Vous ne pouvez pas configurer le partenaire %(partner)s with 'Une facture "
+"par commande' et 'Une facture par expédition' !"
 
 #. module: partner_invoicing_mode_at_shipping
 #. odoo-python
@@ -93,3 +102,5 @@ msgid ""
 "You cannot configure the partner %(partner)s with Invoicing Mode 'At "
 "Shipping' and 'One Invoice Per Shipping'!"
 msgstr ""
+"Vous ne pouvez pas configurer le partenaire %(partner)s avec le mode de "
+"facturation 'à l'expédition' et 'Une facture par expédition' !"

From d3abea969b6f6451f4fb243b7e5b625242ea27e7 Mon Sep 17 00:00:00 2001
From: chaule97 <lebaochau97@gmail.com>
Date: Tue, 31 Dec 2024 12:11:57 +0700
Subject: [PATCH 31/32] [IMP] partner_invoicing_mode_at_shipping: pre-commit
 auto fixes

---
 partner_invoicing_mode_at_shipping/README.rst | 40 +++++++++----------
 .../pyproject.toml                            |  3 ++
 .../readme/CONTRIBUTORS.md                    |  5 +++
 .../readme/CONTRIBUTORS.rst                   |  5 ---
 .../readme/{CREDITS.rst => CREDITS.md}        |  2 +-
 .../readme/DESCRIPTION.md                     |  8 ++++
 .../readme/DESCRIPTION.rst                    |  8 ----
 .../static/description/index.html             | 31 +++++++-------
 8 files changed, 54 insertions(+), 48 deletions(-)
 create mode 100644 partner_invoicing_mode_at_shipping/pyproject.toml
 create mode 100644 partner_invoicing_mode_at_shipping/readme/CONTRIBUTORS.md
 delete mode 100644 partner_invoicing_mode_at_shipping/readme/CONTRIBUTORS.rst
 rename partner_invoicing_mode_at_shipping/readme/{CREDITS.rst => CREDITS.md} (83%)
 create mode 100644 partner_invoicing_mode_at_shipping/readme/DESCRIPTION.md
 delete mode 100644 partner_invoicing_mode_at_shipping/readme/DESCRIPTION.rst

diff --git a/partner_invoicing_mode_at_shipping/README.rst b/partner_invoicing_mode_at_shipping/README.rst
index 482b5d7dd5c..e47260cb17b 100644
--- a/partner_invoicing_mode_at_shipping/README.rst
+++ b/partner_invoicing_mode_at_shipping/README.rst
@@ -17,25 +17,25 @@ Partner Invoicing Mode At Shipping
     :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
     :alt: License: AGPL-3
 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Faccount--invoicing-lightgray.png?logo=github
-    :target: https://github.com/OCA/account-invoicing/tree/16.0/partner_invoicing_mode_at_shipping
+    :target: https://github.com/OCA/account-invoicing/tree/17.0/partner_invoicing_mode_at_shipping
     :alt: OCA/account-invoicing
 .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
-    :target: https://translation.odoo-community.org/projects/account-invoicing-16-0/account-invoicing-16-0-partner_invoicing_mode_at_shipping
+    :target: https://translation.odoo-community.org/projects/account-invoicing-17-0/account-invoicing-17-0-partner_invoicing_mode_at_shipping
     :alt: Translate me on Weblate
 .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
-    :target: https://runboat.odoo-community.org/builds?repo=OCA/account-invoicing&target_branch=16.0
+    :target: https://runboat.odoo-community.org/builds?repo=OCA/account-invoicing&target_branch=17.0
     :alt: Try me on Runboat
 
 |badge1| |badge2| |badge3| |badge4| |badge5|
 
-This module allows to select a `At shipping` invoicing mode for a customer.
-It is based on `partner_invoicing_mode`.
-When this mode is selected the customer will be invoiced automatically on
-delivery of the goods.
+This module allows to select a At shipping invoicing mode for a
+customer. It is based on partner_invoicing_mode. When this mode is
+selected the customer will be invoiced automatically on delivery of the
+goods.
 
-Another option is the 'One Invoice Per Shipping'. That one is not compatible
-with the 'At shipping' invoicing mode. In that case, the invoicing validation
-will occur at a different moment (monthly, ...).
+Another option is the 'One Invoice Per Shipping'. That one is not
+compatible with the 'At shipping' invoicing mode. In that case, the
+invoicing validation will occur at a different moment (monthly, ...).
 
 **Table of contents**
 
@@ -48,7 +48,7 @@ Bug Tracker
 Bugs are tracked on `GitHub Issues <https://github.com/OCA/account-invoicing/issues>`_.
 In case of trouble, please check there if your issue has already been reported.
 If you spotted it first, help us to smash it by providing a detailed and welcomed
-`feedback <https://github.com/OCA/account-invoicing/issues/new?body=module:%20partner_invoicing_mode_at_shipping%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
+`feedback <https://github.com/OCA/account-invoicing/issues/new?body=module:%20partner_invoicing_mode_at_shipping%0Aversion:%2017.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
 
 Do not contact contributors directly about support or help with technical issues.
 
@@ -56,28 +56,28 @@ Credits
 =======
 
 Authors
-~~~~~~~
+-------
 
 * Camptocamp
 
 Contributors
-~~~~~~~~~~~~
+------------
 
-* `Camptocamp <https://www.camptocamp.com>`_:
+-  `Camptocamp <https://www.camptocamp.com>`__:
 
-    * Thierry Ducrest <thierry.ducrest@camptocamp.com>
+      -  Thierry Ducrest <thierry.ducrest@camptocamp.com>
 
-* Phuc (Tran Thanh) <phuc@trobz.com>
+-  Phuc (Tran Thanh) <phuc@trobz.com>
 
 Other credits
-~~~~~~~~~~~~~
+-------------
 
 The development of this module has been financially supported by:
 
-* Camptocamp
+-  Camptocamp
 
 Maintainers
-~~~~~~~~~~~
+-----------
 
 This module is maintained by the OCA.
 
@@ -89,6 +89,6 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose
 mission is to support the collaborative development of Odoo features and
 promote its widespread use.
 
-This module is part of the `OCA/account-invoicing <https://github.com/OCA/account-invoicing/tree/16.0/partner_invoicing_mode_at_shipping>`_ project on GitHub.
+This module is part of the `OCA/account-invoicing <https://github.com/OCA/account-invoicing/tree/17.0/partner_invoicing_mode_at_shipping>`_ project on GitHub.
 
 You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/partner_invoicing_mode_at_shipping/pyproject.toml b/partner_invoicing_mode_at_shipping/pyproject.toml
new file mode 100644
index 00000000000..4231d0cccb3
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/pyproject.toml
@@ -0,0 +1,3 @@
+[build-system]
+requires = ["whool"]
+build-backend = "whool.buildapi"
diff --git a/partner_invoicing_mode_at_shipping/readme/CONTRIBUTORS.md b/partner_invoicing_mode_at_shipping/readme/CONTRIBUTORS.md
new file mode 100644
index 00000000000..7d04f82d381
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/readme/CONTRIBUTORS.md
@@ -0,0 +1,5 @@
+- [Camptocamp](https://www.camptocamp.com):
+
+  > - Thierry Ducrest \<<thierry.ducrest@camptocamp.com>\>
+
+- Phuc (Tran Thanh) \<<phuc@trobz.com>\>
diff --git a/partner_invoicing_mode_at_shipping/readme/CONTRIBUTORS.rst b/partner_invoicing_mode_at_shipping/readme/CONTRIBUTORS.rst
deleted file mode 100644
index ecddfcde7f4..00000000000
--- a/partner_invoicing_mode_at_shipping/readme/CONTRIBUTORS.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-* `Camptocamp <https://www.camptocamp.com>`_:
-
-    * Thierry Ducrest <thierry.ducrest@camptocamp.com>
-
-* Phuc (Tran Thanh) <phuc@trobz.com>
diff --git a/partner_invoicing_mode_at_shipping/readme/CREDITS.rst b/partner_invoicing_mode_at_shipping/readme/CREDITS.md
similarity index 83%
rename from partner_invoicing_mode_at_shipping/readme/CREDITS.rst
rename to partner_invoicing_mode_at_shipping/readme/CREDITS.md
index f5cc070c78e..705d3b30cad 100644
--- a/partner_invoicing_mode_at_shipping/readme/CREDITS.rst
+++ b/partner_invoicing_mode_at_shipping/readme/CREDITS.md
@@ -1,3 +1,3 @@
 The development of this module has been financially supported by:
 
-* Camptocamp
+- Camptocamp
diff --git a/partner_invoicing_mode_at_shipping/readme/DESCRIPTION.md b/partner_invoicing_mode_at_shipping/readme/DESCRIPTION.md
new file mode 100644
index 00000000000..a59d643c323
--- /dev/null
+++ b/partner_invoicing_mode_at_shipping/readme/DESCRIPTION.md
@@ -0,0 +1,8 @@
+This module allows to select a At shipping invoicing mode for a
+customer. It is based on partner_invoicing_mode. When this mode is
+selected the customer will be invoiced automatically on delivery of the
+goods.
+
+Another option is the 'One Invoice Per Shipping'. That one is not
+compatible with the 'At shipping' invoicing mode. In that case, the
+invoicing validation will occur at a different moment (monthly, ...).
diff --git a/partner_invoicing_mode_at_shipping/readme/DESCRIPTION.rst b/partner_invoicing_mode_at_shipping/readme/DESCRIPTION.rst
deleted file mode 100644
index b5f1abd304d..00000000000
--- a/partner_invoicing_mode_at_shipping/readme/DESCRIPTION.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-This module allows to select a `At shipping` invoicing mode for a customer.
-It is based on `partner_invoicing_mode`.
-When this mode is selected the customer will be invoiced automatically on
-delivery of the goods.
-
-Another option is the 'One Invoice Per Shipping'. That one is not compatible
-with the 'At shipping' invoicing mode. In that case, the invoicing validation
-will occur at a different moment (monthly, ...).
diff --git a/partner_invoicing_mode_at_shipping/static/description/index.html b/partner_invoicing_mode_at_shipping/static/description/index.html
index 3e22980a80e..f4d54cc6f93 100644
--- a/partner_invoicing_mode_at_shipping/static/description/index.html
+++ b/partner_invoicing_mode_at_shipping/static/description/index.html
@@ -8,10 +8,11 @@
 
 /*
 :Author: David Goodger (goodger@python.org)
-:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
+:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
 :Copyright: This stylesheet has been placed in the public domain.
 
 Default cascading style sheet for the HTML output of Docutils.
+Despite the name, some widely supported CSS2 features are used.
 
 See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
 customize this style sheet.
@@ -274,7 +275,7 @@
   margin-left: 2em ;
   margin-right: 2em }
 
-pre.code .ln { color: grey; } /* line numbers */
+pre.code .ln { color: gray; } /* line numbers */
 pre.code, code { background-color: #eeeeee }
 pre.code .comment, code .comment { color: #5C6576 }
 pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
@@ -300,7 +301,7 @@
 span.pre {
   white-space: pre }
 
-span.problematic {
+span.problematic, pre.problematic {
   color: red }
 
 span.section-subtitle {
@@ -368,14 +369,14 @@ <h1 class="title">Partner Invoicing Mode At Shipping</h1>
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 !! source digest: sha256:6f96589039ddad82b6acdcd148f04264085935d83c2fc147507bf3ab3ae41c1b
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
-<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/account-invoicing/tree/16.0/partner_invoicing_mode_at_shipping"><img alt="OCA/account-invoicing" src="https://img.shields.io/badge/github-OCA%2Faccount--invoicing-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/account-invoicing-16-0/account-invoicing-16-0-partner_invoicing_mode_at_shipping"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/account-invoicing&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
-<p>This module allows to select a <cite>At shipping</cite> invoicing mode for a customer.
-It is based on <cite>partner_invoicing_mode</cite>.
-When this mode is selected the customer will be invoiced automatically on
-delivery of the goods.</p>
-<p>Another option is the ‘One Invoice Per Shipping’. That one is not compatible
-with the ‘At shipping’ invoicing mode. In that case, the invoicing validation
-will occur at a different moment (monthly, …).</p>
+<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/account-invoicing/tree/17.0/partner_invoicing_mode_at_shipping"><img alt="OCA/account-invoicing" src="https://img.shields.io/badge/github-OCA%2Faccount--invoicing-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/account-invoicing-17-0/account-invoicing-17-0-partner_invoicing_mode_at_shipping"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/account-invoicing&amp;target_branch=17.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
+<p>This module allows to select a At shipping invoicing mode for a
+customer. It is based on partner_invoicing_mode. When this mode is
+selected the customer will be invoiced automatically on delivery of the
+goods.</p>
+<p>Another option is the ‘One Invoice Per Shipping’. That one is not
+compatible with the ‘At shipping’ invoicing mode. In that case, the
+invoicing validation will occur at a different moment (monthly, …).</p>
 <p><strong>Table of contents</strong></p>
 <div class="contents local topic" id="contents">
 <ul class="simple">
@@ -394,7 +395,7 @@ <h1><a class="toc-backref" href="#toc-entry-1">Bug Tracker</a></h1>
 <p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/account-invoicing/issues">GitHub Issues</a>.
 In case of trouble, please check there if your issue has already been reported.
 If you spotted it first, help us to smash it by providing a detailed and welcomed
-<a class="reference external" href="https://github.com/OCA/account-invoicing/issues/new?body=module:%20partner_invoicing_mode_at_shipping%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
+<a class="reference external" href="https://github.com/OCA/account-invoicing/issues/new?body=module:%20partner_invoicing_mode_at_shipping%0Aversion:%2017.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
 <p>Do not contact contributors directly about support or help with technical issues.</p>
 </div>
 <div class="section" id="credits">
@@ -429,11 +430,13 @@ <h2><a class="toc-backref" href="#toc-entry-5">Other credits</a></h2>
 <div class="section" id="maintainers">
 <h2><a class="toc-backref" href="#toc-entry-6">Maintainers</a></h2>
 <p>This module is maintained by the OCA.</p>
-<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
+<a class="reference external image-reference" href="https://odoo-community.org">
+<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
+</a>
 <p>OCA, or the Odoo Community Association, is a nonprofit organization whose
 mission is to support the collaborative development of Odoo features and
 promote its widespread use.</p>
-<p>This module is part of the <a class="reference external" href="https://github.com/OCA/account-invoicing/tree/16.0/partner_invoicing_mode_at_shipping">OCA/account-invoicing</a> project on GitHub.</p>
+<p>This module is part of the <a class="reference external" href="https://github.com/OCA/account-invoicing/tree/17.0/partner_invoicing_mode_at_shipping">OCA/account-invoicing</a> project on GitHub.</p>
 <p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
 </div>
 </div>

From 3f12bd5bf5bbd249b89609752b785c9a17c4fdba Mon Sep 17 00:00:00 2001
From: Nils Coenen <74965194+NICO-SOLUTIONS@users.noreply.github.com>
Date: Mon, 8 Apr 2024 22:25:31 +0200
Subject: [PATCH 32/32] [MIG] partner_invoicing_mode_at_shipping: Migration to
 17.0

---
 partner_invoicing_mode_at_shipping/README.rst |  7 +++++-
 .../__manifest__.py                           |  5 +++-
 partner_invoicing_mode_at_shipping/hooks.py   |  5 +---
 .../migrations/16.0.1.1.0/pre-migrate.py      | 13 ----------
 .../models/__init__.py                        |  1 -
 .../models/stock_move.py                      | 19 ---------------
 .../models/stock_picking.py                   |  3 ++-
 .../readme/CONTRIBUTORS.md                    |  2 ++
 .../readme/CREDITS.md                         |  2 +-
 .../static/description/index.html             |  7 +++++-
 .../tests/common.py                           |  2 --
 .../tests/test_invoice_mode_at_shipping.py    | 24 +++++++++----------
 .../tests/test_invoice_mode_group_delivery.py |  4 ++--
 requirements.txt                              |  2 ++
 14 files changed, 38 insertions(+), 58 deletions(-)
 delete mode 100644 partner_invoicing_mode_at_shipping/migrations/16.0.1.1.0/pre-migrate.py
 delete mode 100644 partner_invoicing_mode_at_shipping/models/stock_move.py
 create mode 100644 requirements.txt

diff --git a/partner_invoicing_mode_at_shipping/README.rst b/partner_invoicing_mode_at_shipping/README.rst
index e47260cb17b..119dcd6f845 100644
--- a/partner_invoicing_mode_at_shipping/README.rst
+++ b/partner_invoicing_mode_at_shipping/README.rst
@@ -69,10 +69,15 @@ Contributors
 
 -  Phuc (Tran Thanh) <phuc@trobz.com>
 
+-  Nils Coenen <nils.coenen@nico-solutions.de>
+
+-  Chau Le <chaulb@trobz.com>
+
 Other credits
 -------------
 
-The development of this module has been financially supported by:
+The development and migration of this module has been financially
+supported by:
 
 -  Camptocamp
 
diff --git a/partner_invoicing_mode_at_shipping/__manifest__.py b/partner_invoicing_mode_at_shipping/__manifest__.py
index bb14468e348..cfb64ef27fd 100644
--- a/partner_invoicing_mode_at_shipping/__manifest__.py
+++ b/partner_invoicing_mode_at_shipping/__manifest__.py
@@ -2,7 +2,7 @@
 # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
 {
     "name": "Partner Invoicing Mode At Shipping",
-    "version": "16.0.1.2.0",
+    "version": "17.0.1.0.0",
     "summary": "Create invoices automatically when goods are shipped.",
     "author": "Camptocamp, Odoo Community Association (OCA)",
     "website": "https://github.com/OCA/account-invoicing",
@@ -13,5 +13,8 @@
         "views/res_partner.xml",
     ],
     "depends": ["account", "partner_invoicing_mode", "queue_job", "stock"],
+    "external_dependencies": {
+        "python": ["openupgradelib"],
+    },
     "pre_init_hook": "pre_init_hook",
 }
diff --git a/partner_invoicing_mode_at_shipping/hooks.py b/partner_invoicing_mode_at_shipping/hooks.py
index dc998200a68..e6a69d915ed 100644
--- a/partner_invoicing_mode_at_shipping/hooks.py
+++ b/partner_invoicing_mode_at_shipping/hooks.py
@@ -2,8 +2,6 @@
 # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
 from openupgradelib import openupgrade
 
-from odoo import SUPERUSER_ID, api
-
 
 def _add_one_invoice_per_shipping(env):
     if not openupgrade.column_exists(env.cr, "sale_order", "one_invoice_per_shipping"):
@@ -21,6 +19,5 @@ def _add_one_invoice_per_shipping(env):
         openupgrade.add_fields(env, field_spec)
 
 
-def pre_init_hook(cr):
-    env = api.Environment(cr, SUPERUSER_ID, {})
+def pre_init_hook(env):
     _add_one_invoice_per_shipping(env)
diff --git a/partner_invoicing_mode_at_shipping/migrations/16.0.1.1.0/pre-migrate.py b/partner_invoicing_mode_at_shipping/migrations/16.0.1.1.0/pre-migrate.py
deleted file mode 100644
index d6262c5da7b..00000000000
--- a/partner_invoicing_mode_at_shipping/migrations/16.0.1.1.0/pre-migrate.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2023 ACSONE SA/NV
-# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
-from openupgradelib import openupgrade
-
-# pylint: disable=odoo-addons-relative-import
-from odoo.addons.partner_invoicing_mode_at_shipping.hooks import (
-    _add_one_invoice_per_shipping,
-)
-
-
-@openupgrade.migrate()
-def migrate(env, version):
-    _add_one_invoice_per_shipping(env)
diff --git a/partner_invoicing_mode_at_shipping/models/__init__.py b/partner_invoicing_mode_at_shipping/models/__init__.py
index eee3b02a332..ddbf4e06b0d 100644
--- a/partner_invoicing_mode_at_shipping/models/__init__.py
+++ b/partner_invoicing_mode_at_shipping/models/__init__.py
@@ -1,4 +1,3 @@
 from . import res_partner
-from . import stock_move
 from . import stock_picking
 from . import sale_order
diff --git a/partner_invoicing_mode_at_shipping/models/stock_move.py b/partner_invoicing_mode_at_shipping/models/stock_move.py
deleted file mode 100644
index 7dc6546baed..00000000000
--- a/partner_invoicing_mode_at_shipping/models/stock_move.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2020 Camptocamp SA
-# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
-
-from odoo import models
-
-
-class StockMove(models.Model):
-    _inherit = "stock.move"
-
-    def _get_related_invoices(self):
-        """Overridden from stock_account to return the customer invoices
-        related to this stock move.
-        """
-        invoices = super()._get_related_invoices()
-        line_invoices = self.sale_line_id.order_id.invoice_ids.filtered(
-            lambda x: x.state == "posted"
-        )
-        invoices |= line_invoices
-        return invoices
diff --git a/partner_invoicing_mode_at_shipping/models/stock_picking.py b/partner_invoicing_mode_at_shipping/models/stock_picking.py
index ee5edfee2a0..ae4d5208967 100644
--- a/partner_invoicing_mode_at_shipping/models/stock_picking.py
+++ b/partner_invoicing_mode_at_shipping/models/stock_picking.py
@@ -1,7 +1,7 @@
 # Copyright 2020 Camptocamp SA
 # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
 
-from odoo import _, models
+from odoo import _, api, models
 
 
 class StockPicking(models.Model):
@@ -27,6 +27,7 @@ def _invoicing_at_shipping_validation(self, invoices):
             lambda invoice: invoice.partner_id.invoicing_mode == "at_shipping"
         )
 
+    @api.model
     def _invoicing_at_shipping(self):
         self.ensure_one()
         sales = self._get_sales_order_to_invoice()
diff --git a/partner_invoicing_mode_at_shipping/readme/CONTRIBUTORS.md b/partner_invoicing_mode_at_shipping/readme/CONTRIBUTORS.md
index 7d04f82d381..fd3082e3509 100644
--- a/partner_invoicing_mode_at_shipping/readme/CONTRIBUTORS.md
+++ b/partner_invoicing_mode_at_shipping/readme/CONTRIBUTORS.md
@@ -3,3 +3,5 @@
   > - Thierry Ducrest \<<thierry.ducrest@camptocamp.com>\>
 
 - Phuc (Tran Thanh) \<<phuc@trobz.com>\>
+- Nils Coenen \<<nils.coenen@nico-solutions.de>\>
+- Chau Le \<<chaulb@trobz.com>\>
diff --git a/partner_invoicing_mode_at_shipping/readme/CREDITS.md b/partner_invoicing_mode_at_shipping/readme/CREDITS.md
index 705d3b30cad..c2d2a1e6b83 100644
--- a/partner_invoicing_mode_at_shipping/readme/CREDITS.md
+++ b/partner_invoicing_mode_at_shipping/readme/CREDITS.md
@@ -1,3 +1,3 @@
-The development of this module has been financially supported by:
+The development and migration of this module has been financially supported by:
 
 - Camptocamp
diff --git a/partner_invoicing_mode_at_shipping/static/description/index.html b/partner_invoicing_mode_at_shipping/static/description/index.html
index f4d54cc6f93..d84384fd192 100644
--- a/partner_invoicing_mode_at_shipping/static/description/index.html
+++ b/partner_invoicing_mode_at_shipping/static/description/index.html
@@ -418,11 +418,16 @@ <h2><a class="toc-backref" href="#toc-entry-4">Contributors</a></h2>
 </li>
 <li><p class="first">Phuc (Tran Thanh) &lt;<a class="reference external" href="mailto:phuc&#64;trobz.com">phuc&#64;trobz.com</a>&gt;</p>
 </li>
+<li><p class="first">Nils Coenen &lt;<a class="reference external" href="mailto:nils.coenen&#64;nico-solutions.de">nils.coenen&#64;nico-solutions.de</a>&gt;</p>
+</li>
+<li><p class="first">Chau Le &lt;<a class="reference external" href="mailto:chaulb&#64;trobz.com">chaulb&#64;trobz.com</a>&gt;</p>
+</li>
 </ul>
 </div>
 <div class="section" id="other-credits">
 <h2><a class="toc-backref" href="#toc-entry-5">Other credits</a></h2>
-<p>The development of this module has been financially supported by:</p>
+<p>The development and migration of this module has been financially
+supported by:</p>
 <ul class="simple">
 <li>Camptocamp</li>
 </ul>
diff --git a/partner_invoicing_mode_at_shipping/tests/common.py b/partner_invoicing_mode_at_shipping/tests/common.py
index 0d8b587ab21..a2690f3cc9d 100644
--- a/partner_invoicing_mode_at_shipping/tests/common.py
+++ b/partner_invoicing_mode_at_shipping/tests/common.py
@@ -27,7 +27,6 @@ def setUpClass(cls):
                         },
                     )
                 ],
-                "pricelist_id": cls.env.ref("product.list0").id,
             }
         )
 
@@ -51,6 +50,5 @@ def _create_order(cls):
                         },
                     )
                 ],
-                "pricelist_id": cls.env.ref("product.list0").id,
             }
         )
diff --git a/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_at_shipping.py b/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_at_shipping.py
index 3621c28964a..254929c81d1 100644
--- a/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_at_shipping.py
+++ b/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_at_shipping.py
@@ -19,10 +19,10 @@ def test_invoice_created_at_shipping(self):
         self.so1.action_confirm()
         for picking in self.so1.picking_ids:
             for move in picking.move_ids:
-                move.quantity_done = move.product_uom_qty
+                move.quantity = move.product_uom_qty
             picking.action_assign()
             with mute_logger("odoo.addons.queue_job.delay"):
-                picking.with_context(test_queue_job_no_delay=True).button_validate()
+                picking.with_context(queue_job__no_delay=True).button_validate()
         self.assertEqual(len(self.so1.invoice_ids), 1)
         self.assertEqual(self.so1.invoice_ids.state, "posted")
 
@@ -32,10 +32,10 @@ def test_invoice_not_created_at_shipping(self):
         self.so1.action_confirm()
         for picking in self.so1.picking_ids:
             for move in picking.move_ids:
-                move.quantity_done = move.product_uom_qty
+                move.quantity = move.product_uom_qty
             picking.action_assign()
             with mute_logger("odoo.addons.queue_job.delay"):
-                picking.with_context(test_queue_job_no_delay=True).button_validate()
+                picking.with_context(queue_job__no_delay=True).button_validate()
         self.assertEqual(len(self.so1.invoice_ids), 0)
 
     def test_picking_multi_order_single_invoice(self):
@@ -50,10 +50,10 @@ def test_picking_multi_order_single_invoice(self):
         so2.picking_ids.move_ids.picking_id = picking
         # Transfer the remaining picking with moves
         for move in picking.move_ids:
-            move.quantity_done = move.product_uom_qty
+            move.quantity = move.product_uom_qty
         picking.action_assign()
         with mute_logger("odoo.addons.queue_job.delay"):
-            picking.with_context(test_queue_job_no_delay=True).button_validate()
+            picking.with_context(queue_job__no_delay=True).button_validate()
         self.assertEqual(len(self.so1.invoice_ids), 1)
         self.assertEqual(self.so1.invoice_ids.state, "posted")
         self.assertEqual(self.so1.invoice_ids, so2.invoice_ids)
@@ -70,10 +70,10 @@ def test_picking_multi_order_multi_invoice(self):
         so2.picking_ids.move_ids.picking_id = picking
         # Transfer the remaining picking with moves
         for move in picking.move_ids:
-            move.quantity_done = move.product_uom_qty
+            move.quantity = move.product_uom_qty
         picking.action_assign()
         with mute_logger("odoo.addons.queue_job.delay"):
-            picking.with_context(test_queue_job_no_delay=True).button_validate()
+            picking.with_context(queue_job__no_delay=True).button_validate()
         self.assertEqual(len(self.so1.invoice_ids), 1)
         self.assertEqual(self.so1.invoice_ids.state, "posted")
         self.assertEqual(len(so2.invoice_ids), 1)
@@ -85,20 +85,20 @@ def test_picking_backorder(self):
         self.partner.invoicing_mode = "at_shipping"
         self.so1.action_confirm()
         picking = self.so1.picking_ids
-        picking.move_ids.quantity_done = 2
+        picking.move_ids.quantity = 2
         picking.action_assign()
         with mute_logger("odoo.addons.queue_job.delay"):
             picking.with_context(
-                skip_backorder=True, test_queue_job_no_delay=True
+                skip_backorder=True, queue_job__no_delay=True
             ).button_validate()
         self.assertEqual(len(self.so1.invoice_ids), 1)
         self.assertEqual(self.so1.invoice_ids.state, "posted")
         # Now process the backorder
         backorder = self.so1.picking_ids - picking
-        backorder.move_ids.quantity_done = 2
+        backorder.move_ids.quantity = 2
         backorder.action_assign()
         with mute_logger("odoo.addons.queue_job.delay"):
-            backorder.with_context(test_queue_job_no_delay=True).button_validate()
+            backorder.with_context(queue_job__no_delay=True).button_validate()
         self.assertEqual(len(self.so1.invoice_ids), 2)
         self.assertTrue(
             all(invoice.state == "posted") for invoice in self.so1.invoice_ids
diff --git a/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_group_delivery.py b/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_group_delivery.py
index fa44a7ad3da..7a69359eb9b 100644
--- a/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_group_delivery.py
+++ b/partner_invoicing_mode_at_shipping/tests/test_invoice_mode_group_delivery.py
@@ -24,7 +24,7 @@ def test_invoice_created_at_shipping_per_delivery(self):
         picking = self.so1.picking_ids
 
         # Deliver partially
-        picking.move_ids.quantity_done = 2.0
+        picking.move_ids.write({"quantity": 2.0, "picked": True})
         with trap_jobs() as trap:
             picking._action_done()
             trap.assert_enqueued_job(
@@ -43,7 +43,7 @@ def test_invoice_created_at_shipping_per_delivery(self):
         backorder = self.so1.picking_ids - picking
         self.assertTrue(backorder)
 
-        backorder.move_ids.quantity_done = 2.0
+        backorder.move_ids.write({"quantity": 2.0, "picked": True})
         with trap_jobs() as trap:
             backorder._action_done()
             trap.assert_enqueued_job(
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 00000000000..180fc49789b
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,2 @@
+# generated from manifests external_dependencies
+openupgradelib