Initial commit: Odoo 18.0-20251222 extra-addons
Some checks failed
pre-commit / pre-commit (push) Has been cancelled
tests / Detect unreleased dependencies (push) Has been cancelled
tests / test with OCB (push) Has been cancelled
tests / test with Odoo (push) Has been cancelled

This commit is contained in:
tocmo0nlord
2026-03-13 20:43:25 +00:00
parent 36e847a7df
commit adbe430761
9472 changed files with 1265727 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
from . import account_move
from . import res_company
from . import res_config_settings
from . import res_partner
from . import sale_order

View File

@@ -0,0 +1,38 @@
# Copyright 2021 Camptocamp SA
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
from odoo import _, api, models
from odoo.exceptions import UserError
class AccountMove(models.Model):
_inherit = "account.move"
def _get_ordered_invoice_lines(self):
"""Sort invoice lines according to the section ordering"""
return self.invoice_line_ids.sorted(
key=self.env["account.move.line"]._get_section_ordering()
)
class AccountMoveLine(models.Model):
_inherit = "account.move.line"
def _get_section_group(self):
"""Return the section group to be used for a single invoice line"""
self.ensure_one()
return self.mapped(self._get_section_grouping())
def _get_section_grouping(self):
"""Defines the grouping relation from the invoice lines to be used.
Meant to be overriden, in order to allow custom grouping.
"""
invoice_section_grouping = self.company_id.invoice_section_grouping
if invoice_section_grouping == "sale_order":
return "sale_line_ids.order_id"
raise UserError(_("Unrecognized invoice_section_grouping"))
@api.model
def _get_section_ordering(self):
"""Function to sort invoice lines before grouping"""
return lambda r: r.mapped(r._get_section_grouping())

View File

@@ -0,0 +1,23 @@
# Copyright 2021 Camptocamp SA
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
from odoo import fields, models
class ResCompany(models.Model):
_inherit = "res.company"
invoice_section_name_scheme = fields.Char(
help="This is the name of the sections on invoices when generated from "
"sales orders. Keep empty to use default. You can use a python "
"expression with the 'object' (representing sale order) and 'time'"
" variables."
)
invoice_section_grouping = fields.Selection(
[
("sale_order", "Group by sale Order"),
],
help="Defines object used to group invoice lines",
default="sale_order",
required=True,
)

View File

@@ -0,0 +1,18 @@
# Copyright 2021 Camptocamp SA
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
from odoo import fields, models
class ResConfigSettings(models.TransientModel):
_inherit = "res.config.settings"
invoice_section_name_scheme = fields.Char(
related="company_id.invoice_section_name_scheme",
readonly=False,
)
invoice_section_grouping = fields.Selection(
related="company_id.invoice_section_grouping",
readonly=False,
required=True,
)

View File

@@ -0,0 +1,14 @@
# Copyright 2021 Camptocamp SA
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
from odoo import fields, models
class ResPartner(models.Model):
_inherit = "res.partner"
invoice_section_name_scheme = fields.Char(
help="This is the name of the sections on invoices when generated from "
"sales orders. Keep empty to use default. You can use a python "
"expression with the 'object' (representing sale order) and 'time'"
" variables."
)

View File

@@ -0,0 +1,84 @@
# Copyright 2020 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
from collections import OrderedDict
from odoo import models
from odoo.tools.safe_eval import safe_eval, time
class SaleOrder(models.Model):
_inherit = "sale.order"
def _create_invoices(self, grouped=False, final=False, date=None):
"""Add sections by groups in the invoice line.
Order the invoicing lines by groups and add lines section with
the group name.
Only do this for invoices targetting multiple groups
"""
invoices = super()._create_invoices(grouped=grouped, final=final, date=date)
for invoice in invoices.sudo():
if invoice.line_ids and (
len(invoice.line_ids.mapped(invoice.line_ids._get_section_grouping()))
== 1
):
continue
sequence = 10
# Because invoices are already created, this would require
# an extra read access in order to read order fields.
move_lines = invoice._get_ordered_invoice_lines()
# Group move lines according to their sale order
section_grouping_matrix = OrderedDict()
for move_line in move_lines:
group = move_line._get_section_group()
section_grouping_matrix.setdefault(group, []).append(move_line.id)
# Prepare section lines for each group
section_lines = []
for group, move_line_ids in section_grouping_matrix.items():
if group:
section_lines.append(
(
0,
0,
{
"name": group._get_invoice_section_name(),
"display_type": "line_section",
"sequence": sequence,
# see test: test_create_invoice_with_default_journal
# forcing the account_id is needed to avoid
# incorrect default value
"account_id": False,
# see test: test_create_invoice_with_currency
# if the currency is not set with the right value
# the total amount will be wrong
# because all line do not have the same currency
"currency_id": invoice.currency_id.id,
},
)
)
sequence += 10
for move_line in (
self.env["account.move.line"].sudo().browse(move_line_ids)
):
# Because invoices are already created, this would require
# an extra write access in order to read order fields.
move_line.sequence = sequence
sequence += 10
# Because invoices are already created, this would require
# an extra write access in order to read order fields.
invoice.line_ids = section_lines
return invoices
def _get_invoice_section_name(self):
"""Returns the text for the section name."""
self.ensure_one()
naming_scheme = (
self.partner_invoice_id.invoice_section_name_scheme
or self.company_id.invoice_section_name_scheme
)
if naming_scheme:
return safe_eval(naming_scheme, {"object": self, "time": time})
elif self.client_order_ref:
return "{} - {}".format(self.name, self.client_order_ref or "")
else:
return self.name