Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
e4ffe09
[FIX] website_event: Ease attendee form inputs extensibility
CarmenMiranda Jan 16, 2026
f7c7a0e
[FIX] spreadsheet: cannot undo a list duplication
rrahir Feb 17, 2026
68b67c9
[FIX] mass_mailing: prevent wrappers application on favorites templates
delcourtfl Dec 3, 2025
a05b731
[FIX] website_forum: fix wrong props passed to WebsiteForumTagsWrapper
xavieralt Jan 15, 2026
d168193
[FIX] hw_drivers: fix SSL verification for IoT handlers
orma-odoo Feb 18, 2026
0acc648
[FIX] sale_project: unlink SO when no SO item is linked to a task
agbr-odoo Dec 26, 2025
20e54e3
[FIX] survey: use answer token in cookies
mwath Jan 22, 2026
766a370
[ADD] pos_edi_ubl: Helpers to generate UBL in the PoS
antoine162 Jun 17, 2025
57aa2e1
[ADD] l10n_jo_edi_pos: Added JoFotara PoS support
hsal-odoo Oct 28, 2025
7b9e596
[FIX] l10n_{hr,ro}_edi: Fix dependency to Peppol BIS3 constraints
clbr-odoo Feb 17, 2026
dc921ed
[FIX] core: map model names to attrs
xmo-odoo Feb 19, 2026
bc5cadb
[FIX] l10n_es_edi_facturae: restrict xml currency fields to 2 decimals
agr-odoo Feb 17, 2026
09019b4
[FIX] delivery, website_sale_collect: fix case formatting in pick-up
mma1377 Feb 17, 2026
1208b6a
[FIX] barcodes_gs1_nomenclature: prevent traceback on barcode rule form
dhha-odoo Feb 18, 2026
3eff8c9
[FIX] spreadsheet: update o_spreadsheet to latest version
LucasLefevre Feb 19, 2026
ff4e38e
[IMP] l10n_pl_edi: KSeF Download Bills
abmn-odoo Feb 3, 2026
4777f00
[FIX] account_peppol: Avoid commercial_partner_id being empty
robodoo Feb 20, 2026
e1e6fcb
[FIX] website_project: Avoid duplicated description in project form
sben-odoo Feb 3, 2026
58139b9
[FIX] account_peppol: ensure PDF is embedded in Peppol XML
bhra-odoo Jan 27, 2026
436921c
[IMP] account_edi_ubl_cii: Identify the correct tax at import
Jan 29, 2026
4550058
[CHG] load product pricelist cache on product selection + lazy load c…
benwillig Oct 8, 2025
16f7b5f
[FIX] fixed error when closing the customer screen without selecting …
benwillig Nov 13, 2025
9550d89
Revert "[FIX] point_of_sale: prevent setting non available pricelist …
benwillig Feb 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions addons/account_edi_ubl_cii/models/account_edi_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,9 +427,8 @@ def _import_invoice_ubl_cii(self, invoice, file_data, new=False):

# Update the invoice.
invoice.move_type = move_type
with invoice._get_edi_creation() as invoice:
with invoice.with_context(disable_onchange_name_predictive=True)._get_edi_creation() as invoice:
logs = self._import_fill_invoice(invoice, tree, qty_factor)

if invoice:
body = Markup("<strong>%s</strong>") % \
_("Format used to import the invoice: %s",
Expand All @@ -444,7 +443,7 @@ def _import_invoice_ubl_cii(self, invoice, file_data, new=False):
# For UBL, we should override the computed tax amount if it is less than 0.05 different of the one in the xml.
# In order to support use case where the tax total is adapted for rounding purpose.
# This has to be done after the first import in order to let Odoo compute the taxes before overriding if needed.
with invoice._get_edi_creation() as invoice:
with invoice.with_context(disable_onchange_name_predictive=True)._get_edi_creation() as invoice:
self._correct_invoice_tax_amount(tree, invoice)

attachments = self._import_attachments(invoice, tree)
Expand Down Expand Up @@ -890,7 +889,7 @@ def _retrieve_taxes(self, record, line_values, tax_type, tax_exigibility=False):
]
tax = self.env['account.tax']
if hasattr(record, '_get_specific_tax'):
tax = record._get_specific_tax(line_values['name'], 'percent', amount, tax_type)
tax = record._get_specific_tax(line_values['name'], 'percent', amount, tax_type).filtered_domain(domain)[:1]
if tax_exigibility:
if not tax and tax_exigibility:
tax = self.env['account.tax'].search(domain + [('price_include', '=', False), ('tax_exigibility', '=', tax_exigibility)], limit=1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1121,6 +1121,7 @@ def _add_invoice_config_vals(self, vals):
'currency_id': invoice.currency_id,
'company_currency_id': invoice.company_id.currency_id,
'company': invoice.company_id,
'journal': invoice.journal_id,

'use_company_currency': False, # If true, use the company currency for the amounts instead of the invoice currency
'fixed_taxes_as_allowance_charges': True, # If true, include fixed taxes as AllowanceCharges on lines instead of as taxes
Expand Down
6 changes: 5 additions & 1 deletion addons/account_edi_ubl_cii/models/account_move_send.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ def _hook_invoice_document_after_pdf_report_render(self, invoice, invoice_data):
super()._hook_invoice_document_after_pdf_report_render(invoice, invoice_data)

# Add PDF to XML
if 'ubl_cii_xml_options' in invoice_data and invoice_data['ubl_cii_xml_options']['ubl_cii_format'] != 'facturx':
if self._needs_ubl_postprocessing(invoice_data):
self._postprocess_invoice_ubl_xml(invoice, invoice_data)

# Always silently generate a Factur-X and embed it inside the PDF for inter-portability
Expand Down Expand Up @@ -204,6 +204,10 @@ def _hook_invoice_document_after_pdf_report_render(self, invoice, invoice_data):
reader_buffer.close()
writer_buffer.close()

@api.model
def _needs_ubl_postprocessing(self, invoice_data):
return 'ubl_cii_xml_options' in invoice_data and invoice_data['ubl_cii_xml_options']['ubl_cii_format'] != 'facturx'

@api.model
def _postprocess_invoice_ubl_xml(self, invoice, invoice_data):
# Adding the PDF to the XML
Expand Down
5 changes: 5 additions & 0 deletions addons/account_peppol/models/account_move_send.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,11 @@ def _call_web_service_after_invoice_pdf_render(self, invoices_data):
)
continue

if invoice.invoice_pdf_report_id and self._needs_ubl_postprocessing(invoice_data):
self._postprocess_invoice_ubl_xml(invoice, invoice_data)
xml_file = invoice_data['ubl_cii_xml_attachment_values']['raw']
filename = invoice_data['ubl_cii_xml_attachment_values']['name']

if len(xml_file) > 64000000:
invoice_data['error'] = _("Invoice %s is too big to send via peppol (64MB limit)", invoice.name)
continue
Expand Down
3 changes: 3 additions & 0 deletions addons/account_peppol/models/res_partner.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ class ResPartner(models.Model):

@api.onchange('invoice_edi_format', 'peppol_endpoint', 'peppol_eas')
def _onchange_verify_peppol_status(self):
if not self.commercial_partner_id:
# avoid issue when commercial_partner_id is on the view
self._compute_commercial_partner()
self.button_account_peppol_check_partner_endpoint()

# -------------------------------------------------------------------------
Expand Down
29 changes: 29 additions & 0 deletions addons/account_peppol/tests/test_peppol_messages.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json
from base64 import b64encode
from contextlib import contextmanager
from lxml import etree
from unittest.mock import patch
from urllib import parse

Expand Down Expand Up @@ -613,3 +614,31 @@ def test_automatic_invoicing_auto_update_partner_peppol_status(self):
transaction.sudo()._post_process()

self.assertRecordValues(partner, [{'peppol_verification_state': 'valid'}])

def test_send_email_then_peppol(self):
"""
Test that the PDF is correctly embedded in the Peppol XML even if the PDF
was already generated by a previous 'Send by Email' action.
"""
move = self.create_move(self.valid_partner)
move.action_post()
wizard_email = self.create_send_and_print(move, sending_methods=['email'])
wizard_email.action_send_and_print()
self.assertTrue(move.invoice_pdf_report_id, "PDF should be generated after sending by email")

wizard_peppol = self.create_send_and_print(move, sending_methods=['peppol'])
self.assertEqual(wizard_peppol.invoice_edi_format, 'ubl_bis3')
wizard_peppol.action_send_and_print()
self.assertTrue(move.ubl_cii_xml_id, "UBL XML should be generated")

root = etree.fromstring(move.ubl_cii_xml_id.raw)
embedded_pdfs = root.xpath(
'//cbc:EmbeddedDocumentBinaryObject[@mimeCode="application/pdf"]',
namespaces={
'cbc': "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2",
}
)
self.assertTrue(
embedded_pdfs and embedded_pdfs[0].text,
"Peppol XML must embed the already-generated PDF"
)
43 changes: 43 additions & 0 deletions addons/account_peppol/tests/test_peppol_participant.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from odoo import Command
from odoo.exceptions import ValidationError
from odoo.tests.form import Form
from odoo.tests.common import tagged, TransactionCase, freeze_time
from odoo.tools import mute_logger
from odoo.tools.misc import file_open
Expand Down Expand Up @@ -341,3 +342,45 @@ def test_deregister_with_client_gone_error(self):

# Should successfully deregister despite Exception
self.assertEqual(self.env.company.account_peppol_proxy_state, 'not_registered')

def test_peppol_commercial_entity(self):
receivable = self.env["account.account"].create({
"account_type": "income",
"name": "test_receiv",
"code": "TESTR"
})
payable = self.env["account.account"].create({
"account_type": "expense",
"name": "test_pay",
"code": "TESTP"
})
company_peppol = self.env["res.company"].create({
"name": "test_be",
"country_id": self.env.ref("base.be").id,
})
partner_view = self.env.ref("base.view_partner_form")
self.env["ir.ui.view"].create({
"name": "test_inherit",
"inherit_id": partner_view.id,
"model": "res.partner",
"type": "form",
"arch": """<xpath expr="//field" position="after">
<field name="commercial_partner_id" />
</xpath>"""
})
env_partner = (self.env["res.partner"]
.with_company(company_peppol)
.with_context(
default_property_account_receivable_id=receivable.id,
default_property_account_payable_id=payable.id
))
with Form(env_partner, view=partner_view) as partner_form:
self.assertEqual(partner_form.peppol_verification_state, "not_verified")
partner_form.name = "test"
partner_form.vat = "BE0477472701"
partner_form.peppol_eas = "odemo"
self.assertFalse(partner_form.commercial_partner_id)
p_rec = partner_form.save()
self.assertEqual(partner_form.peppol_verification_state, "not_valid")
self.assertEqual(p_rec.commercial_partner_id, p_rec)
self.assertEqual(p_rec.commercial_partner_id.name, "test")
9 changes: 5 additions & 4 deletions addons/barcodes_gs1_nomenclature/views/barcodes_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
<attribute name="column_invisible">parent.is_gs1_nomenclature</attribute>
</xpath>
<xpath expr="//field[@name='pattern']" position="after">
<field name="is_gs1_nomenclature" invisible="1"/> <!-- Needed to toggle fields in the barcode rule form without saving this field -->
<field name="gs1_content_type" column_invisible="not parent.is_gs1_nomenclature"/>
<field name="gs1_decimal_usage" column_invisible="not parent.is_gs1_nomenclature" invisible="gs1_content_type != 'measure'"/>
<field name="associated_uom_id" column_invisible="not parent.is_gs1_nomenclature" invisible="gs1_content_type != 'measure'"/>
Expand All @@ -47,12 +48,12 @@
<field name="inherit_id" ref="barcodes.view_barcode_rule_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='encoding']" position="attributes">
<attribute name="invisible">parent.is_gs1_nomenclature or type == 'alias'</attribute>
<attribute name="invisible">is_gs1_nomenclature or type == 'alias'</attribute>
</xpath>
<xpath expr="//field[@name='alias']" position="after">
<field name="gs1_content_type" invisible="not parent.is_gs1_nomenclature"/>
<field name="gs1_decimal_usage" invisible="not parent.is_gs1_nomenclature or gs1_content_type != 'measure'"/>
<field name="associated_uom_id" invisible="not parent.is_gs1_nomenclature or gs1_content_type != 'measure'"/>
<field name="gs1_content_type" invisible="not is_gs1_nomenclature"/>
<field name="gs1_decimal_usage" invisible="not is_gs1_nomenclature or gs1_content_type != 'measure'"/>
<field name="associated_uom_id" invisible="not is_gs1_nomenclature or gs1_content_type != 'measure'"/>
<field name="is_gs1_nomenclature" invisible="1"/>
</xpath>
</field>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ export class LocationSchedule extends Component {
* @return {Object} the localized name of the day (long version).
*/
getWeekDay(weekday) {
return luxon.Info.weekdays()[weekday]
const dayName = luxon.Info.weekdays()[weekday];
return dayName.charAt(0).toUpperCase() + dayName.slice(1);
}

get closedLabel() {
Expand Down
3 changes: 2 additions & 1 deletion addons/hw_drivers/tools/helpers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

import certifi
import configparser
import contextlib
import datetime
Expand Down Expand Up @@ -503,7 +504,7 @@ def download_iot_handlers(auto=True):
server = get_odoo_server_url()
if server:
urllib3.disable_warnings()
pm = urllib3.PoolManager()
pm = urllib3.PoolManager(cert_reqs='CERT_REQUIRED', ca_certs=certifi.where())
server = server + '/iot/get_handlers'
try:
resp = pm.request('POST', server, fields={'mac': get_mac_address(), 'auto': auto}, timeout=8)
Expand Down
8 changes: 4 additions & 4 deletions addons/l10n_es_edi_facturae/data/facturae_templates.xml
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,13 @@
<Quantity t-out="line['Quantity']"/>
<UnitOfMeasure t-out="line.get('UnitOfMeasure')"/>
<UnitPriceWithoutTax t-out="float_repr(refund_multiplier*line['UnitPriceWithoutTax'], 8)"/>
<TotalCost t-out="float_repr(refund_multiplier*line['TotalCost'], 8)"/>
<TotalCost t-out="float_repr(refund_multiplier*line['TotalCost'], file_currency.decimal_places)"/>
<DiscountsAndRebates t-if="line.get('DiscountsAndRebates')">
<t t-foreach="line['DiscountsAndRebates']" t-as="discount">
<Discount>
<DiscountReason t-out="discount['DiscountReason']"/>
<DiscountRate t-out="discount.get('DiscountRate')"/>
<DiscountAmount t-out="float_repr(refund_multiplier*discount['DiscountAmount'], 8)"/>
<DiscountAmount t-out="float_repr(refund_multiplier*discount['DiscountAmount'], file_currency.decimal_places)"/>
</Discount>
</t>
</DiscountsAndRebates>
Expand All @@ -150,11 +150,11 @@
<Charge>
<ChargeReason t-out="charge['ChargeReason']"/>
<ChargeRate t-out="charge.get('ChargeRate')"/>
<ChargeAmount t-out="float_repr(refund_multiplier*charge['ChargeAmount'], 8)"/>
<ChargeAmount t-out="float_repr(refund_multiplier*charge['ChargeAmount'], file_currency.decimal_places)"/>
</Charge>
</t>
</Charges>
<GrossAmount t-out="float_repr(refund_multiplier*line['GrossAmount'], 8)"/>
<GrossAmount t-out="float_repr(refund_multiplier*line['GrossAmount'], file_currency.decimal_places)"/>
<TaxesWithheld t-if="line.get('TaxesWithheld')">
<t t-foreach="line['TaxesWithheld']" t-as="tax"><t t-call="l10n_es_edi_facturae.tax_type"/></t>
</TaxesWithheld>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@
<Quantity>1.0</Quantity>
<UnitOfMeasure>01</UnitOfMeasure>
<UnitPriceWithoutTax>100.00000000</UnitPriceWithoutTax>
<TotalCost>100.00000000</TotalCost>
<GrossAmount>100.00000000</GrossAmount>
<TotalCost>100.00</TotalCost>
<GrossAmount>100.00</GrossAmount>
<TaxesOutputs>
<Tax>
<TaxTypeCode>01</TaxTypeCode>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@
<Quantity>1.0</Quantity>
<UnitOfMeasure>01</UnitOfMeasure>
<UnitPriceWithoutTax>100.00000000</UnitPriceWithoutTax>
<TotalCost>100.00000000</TotalCost>
<GrossAmount>100.00000000</GrossAmount>
<TotalCost>100.00</TotalCost>
<GrossAmount>100.00</GrossAmount>
<TaxesOutputs>
<Tax>
<TaxTypeCode>01</TaxTypeCode>
Expand All @@ -158,8 +158,8 @@
<Quantity>1.0</Quantity>
<UnitOfMeasure>01</UnitOfMeasure>
<UnitPriceWithoutTax>100.00000000</UnitPriceWithoutTax>
<TotalCost>100.00000000</TotalCost>
<GrossAmount>100.00000000</GrossAmount>
<TotalCost>100.00</TotalCost>
<GrossAmount>100.00</GrossAmount>
<TaxesOutputs>
<Tax>
<TaxTypeCode>01</TaxTypeCode>
Expand All @@ -179,8 +179,8 @@
<Quantity>1.0</Quantity>
<UnitOfMeasure>01</UnitOfMeasure>
<UnitPriceWithoutTax>200.00000000</UnitPriceWithoutTax>
<TotalCost>200.00000000</TotalCost>
<GrossAmount>200.00000000</GrossAmount>
<TotalCost>200.00</TotalCost>
<GrossAmount>200.00</GrossAmount>
<TaxesOutputs>
<Tax>
<TaxTypeCode>01</TaxTypeCode>
Expand All @@ -200,15 +200,15 @@
<Quantity>1.0</Quantity>
<UnitOfMeasure>01</UnitOfMeasure>
<UnitPriceWithoutTax>1000.00000000</UnitPriceWithoutTax>
<TotalCost>1000.00000000</TotalCost>
<TotalCost>1000.00</TotalCost>
<DiscountsAndRebates>
<Discount>
<DiscountReason>/</DiscountReason>
<DiscountRate>10.00</DiscountRate>
<DiscountAmount>100.00000000</DiscountAmount>
<DiscountAmount>100.00</DiscountAmount>
</Discount>
</DiscountsAndRebates>
<GrossAmount>900.00000000</GrossAmount>
<GrossAmount>900.00</GrossAmount>
<TaxesOutputs>
<Tax>
<TaxTypeCode>01</TaxTypeCode>
Expand All @@ -228,15 +228,15 @@
<Quantity>1.0</Quantity>
<UnitOfMeasure>01</UnitOfMeasure>
<UnitPriceWithoutTax>1000.00000000</UnitPriceWithoutTax>
<TotalCost>1000.00000000</TotalCost>
<TotalCost>1000.00</TotalCost>
<Charges>
<Charge>
<ChargeReason>/</ChargeReason>
<ChargeRate>10.00</ChargeRate>
<ChargeAmount>100.00000000</ChargeAmount>
<ChargeAmount>100.00</ChargeAmount>
</Charge>
</Charges>
<GrossAmount>1100.00000000</GrossAmount>
<GrossAmount>1100.00</GrossAmount>
<TaxesOutputs>
<Tax>
<TaxTypeCode>01</TaxTypeCode>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@
<Quantity>1.0</Quantity>
<UnitOfMeasure>01</UnitOfMeasure>
<UnitPriceWithoutTax>100.00000000</UnitPriceWithoutTax>
<TotalCost>100.00000000</TotalCost>
<GrossAmount>100.00000000</GrossAmount>
<TotalCost>100.00</TotalCost>
<GrossAmount>100.00</GrossAmount>
<TaxesOutputs>
<Tax>
<TaxTypeCode>01</TaxTypeCode>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@
<Quantity>1.0</Quantity>
<UnitOfMeasure>01</UnitOfMeasure>
<UnitPriceWithoutTax>100.00000000</UnitPriceWithoutTax>
<TotalCost>100.00000000</TotalCost>
<GrossAmount>100.00000000</GrossAmount>
<TotalCost>100.00</TotalCost>
<GrossAmount>100.00</GrossAmount>
<TaxesOutputs>
<Tax>
<TaxTypeCode>01</TaxTypeCode>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@
<Quantity>22.0</Quantity>
<UnitOfMeasure>01</UnitOfMeasure>
<UnitPriceWithoutTax>2.05909091</UnitPriceWithoutTax>
<TotalCost>45.30000000</TotalCost>
<GrossAmount>45.30000000</GrossAmount>
<TotalCost>45.30</TotalCost>
<GrossAmount>45.30</GrossAmount>
<TaxesOutputs>
<Tax>
<TaxTypeCode>01</TaxTypeCode>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@
<Quantity>1.0</Quantity>
<UnitOfMeasure>01</UnitOfMeasure>
<UnitPriceWithoutTax>1000.00000000</UnitPriceWithoutTax>
<TotalCost>1000.00000000</TotalCost>
<GrossAmount>1000.00000000</GrossAmount>
<TotalCost>1000.00</TotalCost>
<GrossAmount>1000.00</GrossAmount>
<TaxesWithheld>
<Tax>
<TaxTypeCode>04</TaxTypeCode>
Expand Down Expand Up @@ -162,8 +162,8 @@
<Quantity>1.0</Quantity>
<UnitOfMeasure>01</UnitOfMeasure>
<UnitPriceWithoutTax>-100.00000000</UnitPriceWithoutTax>
<TotalCost>-100.00000000</TotalCost>
<GrossAmount>-100.00000000</GrossAmount>
<TotalCost>-100.00</TotalCost>
<GrossAmount>-100.00</GrossAmount>
<TaxesWithheld>
<Tax>
<TaxTypeCode>04</TaxTypeCode>
Expand Down
Loading