Daily updates from Odoo
Friday, July 17, 2026
74 changes
11 changes
Enhancements to existing features
Peruvian e-invoicing now includes the product classification codes required by SUNAT's upcoming validation rules. This helps businesses avoid rejected e-invoices for affected goods when the new requirements take effect.
Original PR description
SUNAT is updating its validation rules 2026-08-01, adding three mandatory annexes (25.1, 25.2, 25.3) to Product Catalog N25. E-invoices for these goods are rejected when the required UNSPSC code is not available in the database. Most of the required codes already exist and are active. The rest are handled here: two missing UNSPSC codes were added to the shared catalog, while the fourteen codes that exist but are inactive and the SUNAT-only code 11111111 (which is not part of the UNSPSC standard) are activated from the Peru localization instead. Doing the Peru-specific part in the l10n_pe_edi install hook and upgrade script, the way l10n_mx_edi and l10n_ke_edi_oscu do for their own codes, keeps these activations out of databases that do not use the Peruvian localization. Task-6366907 Forward-Port-Of: odoo/enterprise#124200 Forward-Port-Of: odoo/enterprise#123577
Resolved issues and error corrections
Hong Kong IRD payroll reports now use the correct tax year based on employee start or departure dates. The update also enforces required details when an employee departure reason is marked as “other,” helping businesses meet IRD certification and filing requirements.
Original PR description
As we now have complete support for IRD reports (in master), we started to try to get our system certified by the IRD.
A first submission highlighted a few issues that we are now fixing.
From 19.0:
- In IR56F, the RTN_ASS_YR should be the tax year in which the employee left the company. E.g. after april, the next year.
- In the same report, if the code for the cessation reason is 5 (other), the reason MUST be provided.
From 19.2:
- Same change has to be done when setting RTN_ASS_YR for IR56G
- A same change has to also be done for IR56E, based on the date the employee joined the company.
task-6332150
Forward-Port-Of: odoo/enterprise#124456
Forward-Port-Of: odoo/enterprise#121877Colombian POS orders containing combo products now generate electronic documents that DIAN can accept. The system excludes zero-priced combo parent lines from the submitted XML, preventing card-paid combo sales from failing validation.
Original PR description
Issue: When ordering through POS combo items won't be accepted by DIAN. Steps to reproduce: Set company to Colombia and activate the DIAN module. Simulate a sell of an combo item with POS. Pay with card. Error will ensue. Cause: The XML sent to DIAN is not accepted because one of the items has 0 price (the combo item). Solution: Not sending lines that are combo items. opw-6232599 Forward-Port-Of: odoo/enterprise#123928 Forward-Port-Of: odoo/enterprise#119652
This fixes an issue where attendee email previews could show an outdated event start date after an event was rescheduled. Attendees now receive emails with the correct updated event timing, reducing confusion for multi-day events.
Original PR description
Steps to reproduce: ------------------------------------------------ 1. Install Event module 2. Create a multi day event 3. Create one attendee for the event 4. Change the event dates 5. Go to…
Steps to reproduce: ------------------------------------------------ 1. Install Event module 2. Create a multi day event 3. Create one attendee for the event 4. Change the event dates 5. Go to attendee and Click on Send by Email Observation: ------------------------------------------------ The event start date displayed in the email body is not updated after the event dates are modified. Issue: ------------------------------------------------ In `saas-18.2`, `event_begin_date` and `event_end_date` were simple related fields that automatically updated when their source fields changed. https://github.com/odoo/odoo/blob/saas-18.2/addons/event/models/event_registration.py#L57-L58 However, in `saas-18.3`, slots were introduced and these fields were converted to computed fields https://github.com/odoo/odoo/pull/205945/changes/e2bf8a89d6a50bd40f4673bef38176465f83ba0f * `event_begin_date` is made stored for cohort view grouping * However, the base compute method only depends on `event_id` and `event_slot_id` https://github.com/odoo/odoo/blob/ac37b479321dbe9dbf864e833900e043b1cc70df/addons/event/models/event_registration.py#L177-L180 * When you change `event.date_begin` or `event.date_end`, the registration records don't recompute because the dependency is on the `event_id`, not on the related date fields (`event_id.date_begin`, `event_id.date_end`) * Non-stored computed fields recalculate on-the-fly when accessed, so `event_end_date` appeared to work * Stored computed fields only recalculate when their explicit dependencies change Solution: ------------------------------------------------ * Corrected the dependencies of `_compute_event_begin_date` to recompute value on changing the date of the event opw-6284576 Forward-Port-Of: odoo/enterprise#120184
This fixes an issue that prevented exchange rate adjustment entries from appearing in the bank reconciliation widget. Accounting users can now see the expected exchange movements when reconciling bank transactions, reducing confusion and helping reconciliation stay accurate.
Original PR description
Fix a bug where the exchange moves are no more displayed in the bank reco widget. Bug introduced here: https://github.com/odoo/enterprise/pull/119557 no-task Forward-Port-Of: odoo/enterprise#124495
This fixes a crash when downloading or printing German POS receipts that include Fiskaly TSS certification data. Businesses using certified German point-of-sale flows can reliably access receipts from the backend without errors.
Original PR description
With fiskaly in production, when printing the pos receipt, it crashes because the tss values dictionnary is not correctly interacted with. To reproduce: install l10n_de_pos_cert create a DE shop activate fiskaly and the tss in the settings of the POS create an order in the POS and pay it go to the backend, open the pos order and download the receipt it will crash To reproduce without production credentials, you can not activate fiskaly and the tss but still create and pay the pos order. Then, you can change the pos.config to add the l10n_de_fiskaly_tss_id and change the pos.order to add the l10n_de_fiskaly_time_start. Then download the receipt. opw-6356628 Fixes https://github.com/odoo/enterprise/pull/115676 Forward-Port-Of: odoo/enterprise#123473
VoIP call smart buttons now open the same family-wide records that they count, covering the contact and related company contacts. New records created from those actions still default to the original contact person, reducing confusion for sales, CRM, helpdesk, project, and subscription users.
Original PR description
Commit [1] change the smart buttons on voip.call to count records from all family of the partner (count all record from all partners from the partner's company). However, the actions on the buttons stay the same, they will only open records from the partner itself. This is confusing, we change it to also show records from the whole partner family. [1]: 16772c5c1e604d6beb514f9e5b166fc0c2f452a7 Task-6379569
Chilean point-of-sale receipts with SII barcodes now print correctly instead of crashing during receipt generation. This ensures sales can be validated and customers can receive compliant receipts without interruption.
Original PR description
Steps to reproduce: - Have a Chilean company with DTE configured (a resolution number/date and a signed boleta/factura, so the order's move has an SII barcode) - Open a PoS session, pay an order and validate it Issue: The receipt fails to render and printing crashes with: `TypeError: ctx.image.l10n_cl_sii_barcode_image.to_base64 is not a function` Cause: Commit 0b50021bdae adapted this template as part of the BinaryValue migration (odoo/odoo#244421), calling `to_base64()` on the barcode image. However `l10n_cl_sii_barcode_image` is a computed `fields.Char` that already holds a base64 string (`_pdf417_barcode` returns `b64encode(...).decode()`), not a Binary, so it is never wrapped in a `BinaryValue`. Moreover, this template is also rendered client-side by the PoS QWeb engine, where the value loaded from the server is a plain string with no `to_base64` method either. opw-6389718 Forward-Port-Of: odoo/enterprise#124438
Service sale order lines created from field service planning now let Odoo calculate prices automatically. This ensures customer pricelists and product pricing rules are applied correctly instead of being bypassed by a fixed unit price.
Original PR description
Before this commit, in the method `_generate_service_sale_order_lines` the `price_unit` for sale order lines used an explicitly defined unit price. This prevented the pre-computation of the price. It may cause some issues, for example if there was a pricelist defined on the product, we didn't apply the prices from that pricelist. This commit removes explicit definition of the `price_unit` to let the sale order creation process handle it. [error-941068](https://runbot.odoo.com/odoo/error/941068)
Colombian electronic invoice XML imports now treat the listed price as the actual unit price, matching DIAN rules. This prevents incorrect negative discounts from appearing on vendor bills when imported products have quantities greater than one.
Original PR description
Problem: When importing XML files to generate vendor bills, the system uses UBL parser and assumes that the PriceAmount node needs to be divided by the BaseQuantity node to obtain the exact price…
Problem: When importing XML files to generate vendor bills, the system uses UBL parser and assumes that the PriceAmount node needs to be divided by the BaseQuantity node to obtain the exact price unit. However, in Colombia, the DIAN treats the PriceAmount node as the exact price unit. This was not flagged in the system so the parser incorrectly divides the PriceAmount by BaseQuantity, resulting in negative discounts to be added to match the subtotal. Solution: Extract the basis_qty logic into a helper method so other localizations can override when needed. Current behavior: When importing a Colombian XML with a product that has a BaseQuantity greater than 1, the PriceAmount gets incorrectly divided, resulting in negative discounts on the vendor bill. Expected Behavior: When importing a Colombian XML with a product that has a BaseQuantity greater than 1, the PriceAmount gets parses as the exact unit price with no negative discounts applied. task-6215466 Forward-Port-Of: odoo/enterprise#124567 Forward-Port-Of: odoo/enterprise#122313
This fix prevents an accounting dashboard filter from accidentally affecting document creation during Mexican electronic invoicing payment updates. It avoids an error that could block users from updating payments on CFDI invoices after reconciling bank transactions.
Original PR description
Issue: The `default_type` context can leak into documents creation with invalid values (e.g., 'sale' for documents.document.type), causing a ValueError. Steps to reproduce: - Use a Mexican company with CFDI credentials configured. - Install the documents_account module and create a folder for journals where you will place customer payments. - Create an invoice with "payment policy = PPD", and send it to CFDI. - Create a bank transaction and reconcile it with the invoice. - Go to the Accounting Dashboard, remove current filters, and group by "Type" (this injects default_type into the context). - From there, enter the "Sales" journal and open the invoice. - Click on the "Update Payments" button. - Result: `ValueError: Wrong value for documents.document.type: 'sale'` Fix: Clean context from the `default_*` keys when creating the attachment of the document. opw-6141172 Forward-Port-Of: odoo/enterprise#124578 Forward-Port-Of: odoo/enterprise#124074
9 changes
Enhancements to existing features
Updates the product code catalog so Peruvian e-invoices can include the required SUNAT product classifications for new 2026 validation rules. This helps avoid invoice rejections for affected goods while keeping Peru-specific codes limited to companies using the Peru localization.
Original PR description
SUNAT is updating its validation rules 2026-08-01, adding three mandatory annexes (25.1, 25.2, 25.3) to Product Catalog N25. E-invoices for these goods are rejected when the required UNSPSC code is not available in the database. Most of the required codes already exist and are active. The rest are handled here: two missing UNSPSC codes were added to the shared catalog, while the fourteen codes that exist but are inactive and the SUNAT-only code 11111111 (which is not part of the UNSPSC standard) are activated from the Peru localization instead. Doing the Peru-specific part in the l10n_pe_edi install hook and upgrade script, the way l10n_mx_edi and l10n_ke_edi_oscu do for their own codes, keeps these activations out of databases that do not use the Peruvian localization. Task-6366907 Forward-Port-Of: odoo/enterprise#124200 Forward-Port-Of: odoo/enterprise#123577
Resolved issues and error corrections
Fixed an issue where changing a product variant's cost could leave the displayed on-sale price one step behind when using cost-based pricelists. This helps sales teams and store operators see accurate pricing right away after cost updates.
Original PR description
When we create a product variant and have a pricelist which is based on the cost price, and change the cost price, the on_sale_price doesn't update correctly. It gets delayed by one update because the product._origin isn't getting updated with the new onchanged value. Steps to Reproduce: 1.Create a pricelist and add a line with "formula" price type, and based on "cost", 2.Create a product variant, and add the pricelist just created. 3.Change the "Cost". The "On Sale Price" updates based on the value before. To fix the issue, we need to update the product._origin for standard_price just like the lst_price before computing the on_sale_price opw-5947995 Forward-Port-Of: odoo/enterprise#122391 Forward-Port-Of: odoo/enterprise#119470
This fix prevents zero-priced combo parent items from being included in the Colombian electronic invoice data sent from Point of Sale. As a result, businesses using Colombian DIAN integration can process and report POS combo sales without rejection errors.
Original PR description
Issue: When ordering through POS combo items won't be accepted by DIAN. Steps to reproduce: Set company to Colombia and activate the DIAN module. Simulate a sell of an combo item with POS. Pay with card. Error will ensue. Cause: The XML sent to DIAN is not accepted because one of the items has 0 price (the combo item). Solution: Not sending lines that are combo items. opw-6232599 Forward-Port-Of: odoo/enterprise#123928 Forward-Port-Of: odoo/enterprise#119652
Bank reconciliation now correctly shows exchange difference entries again. This helps accounting users review and match bank transactions accurately when currency exchange differences are involved.
Original PR description
Fix a bug where the exchange moves are no more displayed in the bank reco widget. Bug introduced here: https://github.com/odoo/enterprise/pull/119557 no-task Forward-Port-Of: odoo/enterprise#124495
The preparation display now keeps restaurant orders in a stable order when staff interact with individual order lines. Orders only move in the queue when they change stage, reducing confusion for kitchen teams after a page reload.
Original PR description
**Steps to reproduce:** - Setup a preparation display - Go to the restaurant - Send an order to the kitchen, with 2 lines - Go to another table and send an order with 2 lines to the kitchen - On the display, click the first line of the first order - Reload the page - Order 1 and order 2 have swapped places **Why the fix:** We are currently sorting the orders based on their write_date, meaning that when we click a line, the write date is updated, and it goes to the end of the line. To prevent this, we are now using **last_stage_change** that is only updated when going from one stage to another. This means the cards will stay in the same order, and go to the back of the line once they change stage. To make it so that they are last when changing stage, we update the **last_stage_change** in the frontend as well when changing stage, because it was only done in the backend before this commit. opw-6361046 Forward-Port-Of: odoo/enterprise#124048
New US companies and branches now correctly inherit the journal settings on existing payroll structures during setup. This prevents missing payroll accounting configuration and reduces manual follow-up after creating a company.
Original PR description
Steps to reproduce: 1. A structure related to US, and set journal_id. 2. Create a new US company or branche of the existing company. 3. Go to the created structure, the journal_id is empty. Root cause: After creating a company, _configure_payroll_account should be triggered to finish the configuration. Setting the journal_id for the existing structures (with the same company country) is part of that configuration. The method responsible to call the configuration, is _load_payroll_accounts in account_chart_template.py (hr_payroll_account), and it should call the following method: _configure_payroll_account_generic_coa. This method was deleted in 19.3 and that was the problem. task-6394082
Colombian electronic invoice imports now treat the listed price as the actual unit price, matching DIAN rules. This prevents incorrect price reductions from appearing on vendor bills when imported invoice lines use quantities greater than one.
Original PR description
Problem: When importing XML files to generate vendor bills, the system uses UBL parser and assumes that the PriceAmount node needs to be divided by the BaseQuantity node to obtain the exact price…
Problem: When importing XML files to generate vendor bills, the system uses UBL parser and assumes that the PriceAmount node needs to be divided by the BaseQuantity node to obtain the exact price unit. However, in Colombia, the DIAN treats the PriceAmount node as the exact price unit. This was not flagged in the system so the parser incorrectly divides the PriceAmount by BaseQuantity, resulting in negative discounts to be added to match the subtotal. Solution: Extract the basis_qty logic into a helper method so other localizations can override when needed. Current behavior: When importing a Colombian XML with a product that has a BaseQuantity greater than 1, the PriceAmount gets incorrectly divided, resulting in negative discounts on the vendor bill. Expected Behavior: When importing a Colombian XML with a product that has a BaseQuantity greater than 1, the PriceAmount gets parses as the exact unit price with no negative discounts applied. task-6215466 Forward-Port-Of: odoo/enterprise#124567 Forward-Port-Of: odoo/enterprise#122313
Preparation tickets now load the needed styling again after a receipt printing refactor caused them to lose parts of their layout. The update also restores missing receipt details, improves related POS UI elements, and ensures customer notes print correctly.
Original PR description
..., pos_restaurant, pos_self_order, pos_urban_piper --- During the refactor of the receipt printing system, some CSS classes were no longer loaded with preparation tickets. As a result, preparation tickets lost part of their original styling. To restore the expected rendering, ensure all required classes are properly loaded while keeping the loading minimal. Additionally, some receipt data were missing after the refactor and some UI elements could be improved. This commit restores the missing data and improves the overall UI. It also fixes an issue where customer notes were not printed on the receipt. Templates checked: * point_of_sale.pos_order_change_receipt * point_of_sale.pos_order_change_receipt_line --- Task: https://www.odoo.com/odoo/project/1737/tasks/6133403 Refacto: https://github.com/odoo/odoo/pull/244395 Forward-Port-Of: odoo/enterprise#118782
Fixes an error that could block updating payments on Mexican electronic invoices after users grouped accounting dashboard records by type. The change ensures unrelated screen filters do not interfere when creating document attachments, making the payment update flow more reliable.
Original PR description
Issue: The `default_type` context can leak into documents creation with invalid values (e.g., 'sale' for documents.document.type), causing a ValueError. Steps to reproduce: - Use a Mexican company with CFDI credentials configured. - Install the documents_account module and create a folder for journals where you will place customer payments. - Create an invoice with "payment policy = PPD", and send it to CFDI. - Create a bank transaction and reconcile it with the invoice. - Go to the Accounting Dashboard, remove current filters, and group by "Type" (this injects default_type into the context). - From there, enter the "Sales" journal and open the invoice. - Click on the "Update Payments" button. - Result: `ValueError: Wrong value for documents.document.type: 'sale'` Fix: Clean context from the `default_*` keys when creating the attachment of the document. opw-6141172 Forward-Port-Of: odoo/enterprise#124578 Forward-Port-Of: odoo/enterprise#124074
11 changes
Enhancements to existing features
This update ensures required product classification codes are available for Peruvian electronic invoices ahead of SUNAT's 2026 validation changes. It helps prevent invoice rejections for affected goods while limiting Peru-specific code activations to companies using the Peruvian localization.
Original PR description
SUNAT is updating its validation rules 2026-08-01, adding three mandatory annexes (25.1, 25.2, 25.3) to Product Catalog N25. E-invoices for these goods are rejected when the required UNSPSC code is not available in the database. Most of the required codes already exist and are active. The rest are handled here: two missing UNSPSC codes were added to the shared catalog, while the fourteen codes that exist but are inactive and the SUNAT-only code 11111111 (which is not part of the UNSPSC standard) are activated from the Peru localization instead. Doing the Peru-specific part in the l10n_pe_edi install hook and upgrade script, the way l10n_mx_edi and l10n_ke_edi_oscu do for their own codes, keeps these activations out of databases that do not use the Peruvian localization. Task-6366907 Forward-Port-Of: odoo/enterprise#124200 Forward-Port-Of: odoo/enterprise#123577
Resolved issues and error corrections
This fix ensures Norwegian SAF-T exports use the correct official account grouping when account numbers are extended. It helps businesses avoid incorrect grouping codes in compliance reports submitted or reviewed for Norwegian accounting requirements.
Original PR description
Steps to reproduce: - change 1920 Banck account to 19204321 - go in general ledger and export to "SAF-T" Issue: The grouping code is 4321 Grouping code should match official grouping code. As a matter of fact the chart of account seems to match thos grouping account if we slice them correctly. opw-6285078 Forward-Port-Of: odoo/enterprise#122213 Forward-Port-Of: odoo/enterprise#121932
Colombian electronic invoice imports now read the unit price correctly when the XML includes a base quantity greater than one. This prevents incorrect negative discounts on vendor bills and helps imported bills match DIAN invoice totals.
Original PR description
Problem: When importing XML files to generate vendor bills, the system uses UBL parser and assumes that the PriceAmount node needs to be divided by the BaseQuantity node to obtain the exact price…
Problem: When importing XML files to generate vendor bills, the system uses UBL parser and assumes that the PriceAmount node needs to be divided by the BaseQuantity node to obtain the exact price unit. However, in Colombia, the DIAN treats the PriceAmount node as the exact price unit. This was not flagged in the system so the parser incorrectly divides the PriceAmount by BaseQuantity, resulting in negative discounts to be added to match the subtotal. Solution: Extract the basis_qty logic into a helper method so other localizations can override when needed. Current behavior: When importing a Colombian XML with a product that has a BaseQuantity greater than 1, the PriceAmount gets incorrectly divided, resulting in negative discounts on the vendor bill. Expected Behavior: When importing a Colombian XML with a product that has a BaseQuantity greater than 1, the PriceAmount gets parses as the exact unit price with no negative discounts applied. task-6215466 Forward-Port-Of: odoo/enterprise#124400 Forward-Port-Of: odoo/enterprise#122313
Colombian point-of-sale orders that include combo products can now be accepted by DIAN. The fix avoids sending zero-priced combo parent lines in the electronic document, preventing card-paid combo sales from failing validation.
Original PR description
Issue: When ordering through POS combo items won't be accepted by DIAN. Steps to reproduce: Set company to Colombia and activate the DIAN module. Simulate a sell of an combo item with POS. Pay with card. Error will ensue. Cause: The XML sent to DIAN is not accepted because one of the items has 0 price (the combo item). Solution: Not sending lines that are combo items. opw-6232599 Forward-Port-Of: odoo/enterprise#123928 Forward-Port-Of: odoo/enterprise#119652
This fix ensures Saudi GOSI social insurance contributions are calculated on the full eligible salary instead of being reduced incorrectly. It helps payroll teams produce more accurate payslips and accounting entries for Saudi employees.
Original PR description
task-id: 6380239 Forward-Port-Of: odoo/enterprise#124323 Forward-Port-Of: odoo/enterprise#124122
This fixes an issue where exchange rate adjustment entries were no longer shown in the bank reconciliation widget. Users can now see the relevant exchange moves again, helping accounting teams reconcile bank transactions accurately.
Original PR description
Fix a bug where the exchange moves are no more displayed in the bank reco widget. Bug introduced here: https://github.com/odoo/enterprise/pull/119557 no-task Forward-Port-Of: odoo/enterprise#124495
Preparation display orders no longer move around just because a kitchen line is clicked or refreshed. Orders now keep their position until they actually move to another preparation stage, making the restaurant workflow more predictable for staff.
Original PR description
**Steps to reproduce:** - Setup a preparation display - Go to the restaurant - Send an order to the kitchen, with 2 lines - Go to another table and send an order with 2 lines to the kitchen - On the display, click the first line of the first order - Reload the page - Order 1 and order 2 have swapped places **Why the fix:** We are currently sorting the orders based on their write_date, meaning that when we click a line, the write date is updated, and it goes to the end of the line. To prevent this, we are now using **last_stage_change** that is only updated when going from one stage to another. This means the cards will stay in the same order, and go to the back of the line once they change stage. To make it so that they are last when changing stage, we update the **last_stage_change** in the frontend as well when changing stage, because it was only done in the backend before this commit. opw-6361046 Forward-Port-Of: odoo/enterprise#124048
Payroll CFDI files now correctly include the employer CURP when the Mexican company record represents an individual. This prevents document generation errors for employers using fiscal regime 621 with a 13-character RFC.
Original PR description
Issue: ---------------------------------------- There is a fiscal regime where the company is actually an individual but is authorized to generate documents. Steps to reproduce:…
Issue: ---------------------------------------- There is a fiscal regime where the company is actually an individual but is authorized to generate documents. Steps to reproduce: ---------------------------------------- - Install "l10n_mx_hr_payroll_account_edi" - Change the current company fiscal regime to '621' - Add an VAT of length 13 to the current company - Add a CURP number on the current company - In Payroll generate a payslip, validate it - Post the Journal entry - On the payslip, click "Generate CFDI" - An error is returned, saying the Emisor:Curp applies to individuals Cause: ---------------------------------------- An RFC of length 13 means that the sender is an individual. It's intended with the fiscal regime '621'. We add the curp number in the CFDI XML only when `self.company_id.partner_id.is_company` is `False`. Since saas-19.1, `is_company` is computed to be truely if a VAT is present. So as soon as the VAT is entered, the CURP number is absent from the XML. Solution: ---------------------------------------- We change the condition to add the CURP number in the XML: A VAT number of length 13 means the contact is an individual (12 for companies). This is what is used to validate the XML: if the vat is of length 13, then the curp number should be present. opw-6351558 Forward-Port-Of: odoo/enterprise#124027
Studio approval rules that check restricted customer-related fields now work without causing access errors for users who lack accounting permissions. This prevents valid sales order confirmations from being interrupted while keeping the approval logic in place.
Original PR description
Issue: A studio.approval.rule.domain includes a related field that calls an access rights group that the user who used the action isn't apart of, Is blocked by the filtered_domain. To Replicate: 1) Install studio, sale, Accounting and make sure "account_followup" is installed 2) create a related field on the sales.order form related to "customer -> follow up status" 3) Save 4) Create a "Studio Approval Rule" (studio.approval.rule) with a domain using the new related studio field -> method : "action_confirm" -> approver:admin 5) create a test user with no accounting access rights 6) in an incognito browser try and create a sales order, and then confirm it. it will throw the access rights error Fix: add a sudo to the filtered_domain opw-6316069 Forward-Port-Of: odoo/enterprise#121856
Duplicating certain Sign templates with multiple documents, signers, and fields no longer fails due to repeated signer role handling. This helps users reliably reuse complex signing templates without manual recreation or support intervention.
Original PR description
Issue: This [loop](https://github.com/odoo-dev/enterprise/blob/55bb2cc570451361701d53583f019ed832a5e5d3/sign/models/sign_item.py#L59-L63) runs multiple times with the same approvers(sign.item.role), but doesn't take into account the already 'seen map' inside the base copy function for batching. If they are already seen they will return a non-iterable [None]. To replicate: 1) Sign -> Template -> upload PDF 2) Go into the template 3) Add 2 Documents, with 2 signers and multiple fields on both documents 4) Save -> gear Icon -> make into template 5) Go back to the list view of templates 6) Select the template -> Gear Icon -> Duplicate Fix: add an already seen check to skip if already seen. opw-6352408 Forward-Port-Of: odoo/enterprise#122667
This fix prevents an accounting view setting from interfering when Odoo creates document attachments for Mexican electronic invoicing. Businesses using CFDI payments can update payment information without encountering an unexpected error caused by the prior dashboard filter context.
Original PR description
Issue: The `default_type` context can leak into documents creation with invalid values (e.g., 'sale' for documents.document.type), causing a ValueError. Steps to reproduce: - Use a Mexican company with CFDI credentials configured. - Install the documents_account module and create a folder for journals where you will place customer payments. - Create an invoice with "payment policy = PPD", and send it to CFDI. - Create a bank transaction and reconcile it with the invoice. - Go to the Accounting Dashboard, remove current filters, and group by "Type" (this injects default_type into the context). - From there, enter the "Sales" journal and open the invoice. - Click on the "Update Payments" button. - Result: `ValueError: Wrong value for documents.document.type: 'sale'` Fix: Clean context from the `default_*` keys when creating the attachment of the document. opw-6141172 Forward-Port-Of: odoo/enterprise#124578 Forward-Port-Of: odoo/enterprise#124074
6 changes
Enhancements to existing features
Peruvian e-invoicing now includes the additional product classification codes required by SUNAT's upcoming validation rules. This helps businesses avoid invoice rejections for affected goods once the new requirements take effect.
Original PR description
SUNAT is updating its validation rules 2026-08-01, adding three mandatory annexes (25.1, 25.2, 25.3) to Product Catalog N25. E-invoices for these goods are rejected when the required UNSPSC code is not available in the database. Most of the required codes already exist and are active. The rest are handled here: two missing UNSPSC codes were added to the shared catalog, while the fourteen codes that exist but are inactive and the SUNAT-only code 11111111 (which is not part of the UNSPSC standard) are activated from the Peru localization instead. Doing the Peru-specific part in the l10n_pe_edi install hook and upgrade script, the way l10n_mx_edi and l10n_ke_edi_oscu do for their own codes, keeps these activations out of databases that do not use the Peruvian localization. Task-6366907 Forward-Port-Of: odoo/enterprise#124200 Forward-Port-Of: odoo/enterprise#123577
Resolved issues and error corrections
Odoo Studio now handles field labels written with non-Latin characters, such as Arabic, without creating an invalid internal field name. This prevents users from seeing an error when renaming custom fields in these languages, making Studio more reliable for multilingual teams.
Original PR description
Steps: - Install web_studio - Add any field (example char field) to any view - Rename it in arabic, example `السَّلَامُ عَلَيْكُمْ` - Error Custom field names cannot contain double underscores Webclient (view_editor_model) escape every non-alphabetic chars, so new label value contains nothing but a space which will be replaced by a _ this new label value will be concatenated to `x_studio_`. Resulting to the string `x_studio__`. A solution should be to prevent changing the technical name if the new label value (escaped) is empty. opw-6311027 Forward-Port-Of: odoo/enterprise#122094 Forward-Port-Of: odoo/enterprise#121343
Studio approval rules now work when their conditions reference fields that the acting user cannot directly access. This prevents sales order confirmations and similar actions from being blocked by an access rights error, improving reliability for users with limited permissions.
Original PR description
Issue: A studio.approval.rule.domain includes a related field that calls an access rights group that the user who used the action isn't apart of, Is blocked by the filtered_domain. To Replicate: 1) Install studio, sale, Accounting and make sure "account_followup" is installed 2) create a related field on the sales.order form related to "customer -> follow up status" 3) Save 4) Create a "Studio Approval Rule" (studio.approval.rule) with a domain using the new related studio field -> method : "action_confirm" -> approver:admin 5) create a test user with no accounting access rights 6) in an incognito browser try and create a sales order, and then confirm it. it will throw the access rights error Fix: add a sudo to the filtered_domain opw-6316069 Forward-Port-Of: odoo/enterprise#121856
Preparation display orders no longer jump around when staff interact with individual order lines. Orders now keep their position until they move to a new preparation stage, making kitchen workflows easier to follow after a refresh.
Original PR description
**Steps to reproduce:** - Setup a preparation display - Go to the restaurant - Send an order to the kitchen, with 2 lines - Go to another table and send an order with 2 lines to the kitchen - On the display, click the first line of the first order - Reload the page - Order 1 and order 2 have swapped places **Why the fix:** We are currently sorting the orders based on their write_date, meaning that when we click a line, the write date is updated, and it goes to the end of the line. To prevent this, we are now using **last_stage_change** that is only updated when going from one stage to another. This means the cards will stay in the same order, and go to the back of the line once they change stage. To make it so that they are last when changing stage, we update the **last_stage_change** in the frontend as well when changing stage, because it was only done in the backend before this commit. opw-6361046 Forward-Port-Of: odoo/enterprise#124048
Invoices marked as excluded from follow-up are now also left out of follow-up email attachments and printed follow-up letters. This prevents customers from receiving documents for invoices the business intentionally removed from collection reminders.
Original PR description
Steps to reproduce: 1. Install Accounting and create an invoice for a customer which has a due date in the past 2. Make sure the payment term for the invoice is "Immediate Payment" and Send the…
Steps to reproduce: 1. Install Accounting and create an invoice for a customer which has a due date in the past 2. Make sure the payment term for the invoice is "Immediate Payment" and Send the invoice. 3. Open the contact form and click on the Customer Statement smart button 4. Exclude the invoice using the 'No Follow-Up' toggle 5. In the Accounting tab in the contact form, click on send 6. Open the internal link of the Content Template, go to the options tab and select 'Print Follow-up Letter' in Dynamic Reports 7. Save the configuration and send the email Issue: Excluded invoices still appeared as PDF attachments in the follow-up email and were merged into the printed follow-up letter PDF. Why this happens: Both `default_get` in `account_followup.manual_reminder` and `_get_invoices_to_print` in `res.partner` traversed `unreconciled_aml_ids` without filtering out lines where `no_followup = True`, so excluded invoices were included regardless. opw-6310602 Forward-Port-Of: odoo/enterprise#124541 Forward-Port-Of: odoo/enterprise#122249
Email buttons for appointments and event registrations now use the website tied to the appointment or event instead of a generic or recently used website address. This prevents customers on multi-website setups from being sent to the wrong site when managing bookings or registrations.
Original PR description
In Multiwebsite settings, when the public user interactions needs email generation (appointment or event flow), the email links are generated with a base url that does not corresponds to the one from…
In Multiwebsite settings, when the public user interactions needs email generation (appointment or event flow), the email links are generated with a base url that does not corresponds to the one from which the request started. Case 1: - Have website A and website B - Create an appointment page website A - Log in via website B - As public user, make an appointment in Website A - Check the generated email Issue: button links in the email will redirect to the wrong website, so users will encounter an issue when managing the appointment. This occurs because when an user log in, the system parameter 'web.base_url' is updated with the current url. This parameter is then used as fallback when we need to retrieve the base url without an active record Case 2: - Have website A and website B - Create an event and assign it to website B - As public user, access the event and register to it - Check the generated email Issue: button links in the email will redirect to the wrong website, so users will encounter an issue when managing the event. This occurs because the record `event.registration` has no website_id field and the base url is taken from the company default website (website A) Backport with improvements of 15bae202d8f1b5bf70bbc63b2d89025e9237e6cf opw-4146760 opw-4336369 Forward-Port-Of: odoo/enterprise#124555 Forward-Port-Of: odoo/enterprise#122669
5 changes
Enhancements to existing features
Peruvian e-invoicing now includes the product classification codes required by SUNAT's upcoming 2026 validation rules. This helps businesses avoid rejected electronic invoices for affected goods once the new rules take effect.
Original PR description
SUNAT is updating its validation rules 2026-08-01, adding three mandatory annexes (25.1, 25.2, 25.3) to Product Catalog N25. E-invoices for these goods are rejected when the required UNSPSC code is not available in the database. Most of the required codes already exist and are active. The rest are handled here: two missing UNSPSC codes were added to the shared catalog, while the fourteen codes that exist but are inactive and the SUNAT-only code 11111111 (which is not part of the UNSPSC standard) are activated from the Peru localization instead. Doing the Peru-specific part in the l10n_pe_edi install hook and upgrade script, the way l10n_mx_edi and l10n_ke_edi_oscu do for their own codes, keeps these activations out of databases that do not use the Peruvian localization. Task-6366907 Forward-Port-Of: odoo/enterprise#124200 Forward-Port-Of: odoo/enterprise#123577
Resolved issues and error corrections
French VAT declarations now handle SIRET numbers entered with spaces, preventing avoidable submission failures. The process also checks bank account number formatting and warns users before sending if the details look incorrect.
Original PR description
This commit resolves an issue where VAT declarations failed when the provided SIRET number included spaces. Since check_siret verifies the format, we now strip all spaces from the input. Additionally, this commit introduces a validation for bank account numbers, ensuring that we warn the user if the account number is wrongly formatted. task-6253745 Forward-Port-Of: odoo/enterprise#124448 Forward-Port-Of: odoo/enterprise#120689
Invoices marked as excluded from follow-up are now also left out of follow-up email attachments and printed follow-up letters. This prevents customers from receiving documents for invoices the business intentionally removed from follow-up communications.
Original PR description
Steps to reproduce: 1. Install Accounting and create an invoice for a customer which has a due date in the past 2. Make sure the payment term for the invoice is "Immediate Payment" and Send the…
Steps to reproduce: 1. Install Accounting and create an invoice for a customer which has a due date in the past 2. Make sure the payment term for the invoice is "Immediate Payment" and Send the invoice. 3. Open the contact form and click on the Customer Statement smart button 4. Exclude the invoice using the 'No Follow-Up' toggle 5. In the Accounting tab in the contact form, click on send 6. Open the internal link of the Content Template, go to the options tab and select 'Print Follow-up Letter' in Dynamic Reports 7. Save the configuration and send the email Issue: Excluded invoices still appeared as PDF attachments in the follow-up email and were merged into the printed follow-up letter PDF. Why this happens: Both `default_get` in `account_followup.manual_reminder` and `_get_invoices_to_print` in `res.partner` traversed `unreconciled_aml_ids` without filtering out lines where `no_followup = True`, so excluded invoices were included regardless. opw-6310602 Forward-Port-Of: odoo/enterprise#124541 Forward-Port-Of: odoo/enterprise#122249
This fix prevents an unrelated screen filter from interfering when payment documents are updated for Mexican electronic invoices. It avoids an error that could block users from updating payments after reconciling invoices, improving reliability in the accounting workflow.
Original PR description
Issue: The `default_type` context can leak into documents creation with invalid values (e.g., 'sale' for documents.document.type), causing a ValueError. Steps to reproduce: - Use a Mexican company with CFDI credentials configured. - Install the documents_account module and create a folder for journals where you will place customer payments. - Create an invoice with "payment policy = PPD", and send it to CFDI. - Create a bank transaction and reconcile it with the invoice. - Go to the Accounting Dashboard, remove current filters, and group by "Type" (this injects default_type into the context). - From there, enter the "Sales" journal and open the invoice. - Click on the "Update Payments" button. - Result: `ValueError: Wrong value for documents.document.type: 'sale'` Fix: Clean context from the `default_*` keys when creating the attachment of the document. opw-6141172 Forward-Port-Of: odoo/enterprise#124074
Resetting a submitted tax return no longer removes the global tax lock date for everyone. This keeps closed VAT periods protected while still allowing authorized users to use temporary lock-date exceptions when corrections are needed.
Original PR description
To reproduce the issue: 1) Initialize a company in Belgium, create the tax returns 2) Submit the VAT return from January 3) Open the lock date wizard. The tax lock date is January 31st. 4) Add a lock…
To reproduce the issue:
1) Initialize a company in Belgium, create the tax returns 2) Submit the VAT return from January
3) Open the lock date wizard. The tax lock date is January 31st. 4) Add a lock date exception removing the tax lock date just for you, for 5 min. 5) Reset January's return
6) Reopen the lock date wizard.
====> Your exception is still there, but the tax lock date for everyone has been reset to December 31st.
This is plain wrong. Resetting a return should not automatically reopen the period for everyone. Lock dates exceptions/modifications are anyway required to reset the return ; they should pilot the whole flow. Nothing being magically hidden from the user means there can't be someone else mistakenly encoding something into the reopened period.
Another fix was required to make this one work: setting the tax lock date before submitting the return should work. In bigger environments, users might want to do that as a first step to reduce the number of people encoding data before actually doing the submission of the return. Therefore, the case where the tax lock date is already set at the date_to of the return when submitting it was supposed to be already supported, and allow the creation of the closing entry for that return, despite it being on the tax lock date. The test ensuring this was however badly written, and the feature didn't work: the closing was created at a later date than the lock date automatically, due to the Bills' Algorithm.4 changes
Resolved issues and error corrections
This fixes an invoicing issue for Argentine electronic invoices where using an unsupported ID type for a final consumer could cause a system error. Users will now receive a clear warning to use the correct identification type, helping prevent failed invoice confirmations and confusion.
Original PR description
After applying the community fix, a new issue appears in enterprise. **Steps to reproduce:** - Install the `l10n_ar_edi` module. - Go to Customers and create a new customer with: - Country: Argentina…
After applying the community fix, a new issue appears in enterprise. **Steps to reproduce:** - Install the `l10n_ar_edi` module. - Go to Customers and create a new customer with: - Country: Argentina - Identification Type: `Passport` - Identification Number: `1234567890a` - AFIP Responsibility Type: `Consumidor Final` - Create a new invoice for this customer with: - Journal: `Electronic Invoice (FE)` - Document Type: `(6) INVOICES B` - Try to confirm the invoice. **Error:** ValueError: invalid literal for int() with base 10: '1234567890a' **Expected behaviour:** For Argentinean contacts with AFIP Responsibility Type `Consumidor Final`, the identification type must be `DNI` or `CUIL/CUIT`. If another identification type is used, the user should receive a proper warning instead of a traceback. (see [1]) **Root Cause:** After the community fix, `_get_id_number_sanitize()` can return an alphanumeric value, which is later converted with `int()` at [2] and [3], causing an error. **Fix:** This commit adds an explicit validation for Argentinean contacts with AFIP Responsibility Type Consumidor Final before converting the identification number to an integer, ensuring the user receives the proper warning message. [1]: https://www.odoo.com/mail/message/1118392033 [2]: https://github.com/odoo/enterprise/blob/064812dd9f1074f287fee677ba35ea4aeef3ab3f/l10n_ar_edi/models/account_move.py#L780-L798 [3]: https://github.com/odoo/enterprise/blob/064812dd9f1074f287fee677ba35ea4aeef3ab3f/l10n_ar_edi/models/account_move.py#L927-L931 Related community PR: https://github.com/odoo/odoo/pull/272651 opw-6333998
Swiss QR-IBAN payment references are now cleaned before payment files are generated, removing unsupported characters such as the degree symbol. This helps prevent ISO 20022 bank payment files from being rejected by Swiss banks while keeping valid QR references intact.
Original PR description
**Steps to reproduce:** * Configure a Swiss company with the Swiss accounting localization. * Install `account_sepa`. * Configure a bank journal with a valid Swiss **QR-IBAN**. * Create a vendor with…
**Steps to reproduce:** * Configure a Swiss company with the Swiss accounting localization. * Install `account_sepa`. * Configure a bank journal with a valid Swiss **QR-IBAN**. * Create a vendor with a valid Swiss bank account. * Under **Accounting -> Configuration -> Settings** enable QR Payments. * Go to the vendor and enter the correct QR-IBAN number under the Accounting Section. * Navigate to **Accounting -> Configuration -> Journals** and in the **bank** journal, add the account number of QR-IBAN. * Create and post a vendor payment using the bank journal. * Set the payment reference (`ref`) to contain the `°` character. * Add the payment to a batch payment and generate the ISO 20022 payment file. * Inspect the generated XML. **Observed Behaviour:** The `°` character is preserved in the payment reference for QR-IBAN payments, producing an ISO 20022 file that may be rejected by Swiss banks because it does not comply with the EPC minimum character set. **Cause:** The QR-IBAN branch validates the structured reference before sanitizing it, allowing unsupported characters to remain in the generated XML. **Fix:** Sanitize the payment reference before validating it as a QR structured reference, ensuring invalid characters are removed while preserving valid QR references. opw - 6350931 Forward-Port-Of: odoo/enterprise#124105 Forward-Port-Of: odoo/enterprise#123267
Delivery guides for Chilean electronic stock documents no longer fail when a kit includes components measured in a different unit category than the kit itself. The system now prices those component lines from the product instead of forcing an incompatible sale order unit conversion, allowing users to print delivery guides successfully.
Original PR description
When a kit is delivered, each component move is linked to the kit's sale order line. Pricing the delivery guide in "sale order" mode converted the component quantity into the kit's sale UoM. For a component sold in a different UoM category than the kit, this cross-category conversion raises a UserError. Steps to reproduce: - Create a BoM for a kit product with a component in a different UoM category - Create a customer with Delivery Guide Price = "From Sale Order" - Sold the kit in a sale order and deliver it - On the delivery, print the delivery guide -> error This fix makes the guide price for a component move to be "product" if the component's product is different from the related sale line product, avoiding the cross-category UoM conversion. opw-6327895 Forward-Port-Of: odoo/enterprise#122776
This fixes an issue where updating payments for Mexican electronic invoices could fail after users grouped accounting records by type. The system now ignores unrelated default values when creating document attachments, preventing errors and allowing payment updates to complete normally.
Original PR description
Issue: The `default_type` context can leak into documents creation with invalid values (e.g., 'sale' for documents.document.type), causing a ValueError. Steps to reproduce: - Use a Mexican company with CFDI credentials configured. - Install the documents_account module and create a folder for journals where you will place customer payments. - Create an invoice with "payment policy = PPD", and send it to CFDI. - Create a bank transaction and reconcile it with the invoice. - Go to the Accounting Dashboard, remove current filters, and group by "Type" (this injects default_type into the context). - From there, enter the "Sales" journal and open the invoice. - Click on the "Update Payments" button. - Result: `ValueError: Wrong value for documents.document.type: 'sale'` Fix: Clean context from the `default_*` keys when creating the attachment of the document. opw-6141172 Forward-Port-Of: odoo/enterprise#124074
11 changes
Enhancements to existing features
Saudi Arabian currency rate updates now use the Saudi Central Bank as the dedicated source instead of the default xe.com provider. This improves alignment with official SAR exchange rates and avoids duplicate rate entries when several days of data are returned.
Original PR description
Added a new exchange rate provider for the Saudi Central Bank (SAMA) to fetch official SAR exchange rates. Saudi Arabia is removed from the xe.com default and mapped to this dedicated provider instead. Since the API response includes multiple days of data, duplicate currency entries are deduplicated by keeping the first (most recent) occurrence of each currency code. task-4422561
Customer notes now appear as warnings on billable helpdesk tickets and field service shift forms. This helps service teams see important sales or customer information before working on a ticket or scheduled visit.
Original PR description
- When there is a note on a customer, display it as a warning: - in the ticket form view, if the team is billable - shift form view - move `use_helpdesk_sale_timesheet` from `helpdesk_sale_timesheet` into `helpdesk_sale` --- Task-4910696
This improvement creates redirects from old product links to their new Odoo product pages when moving from another ecommerce platform. It helps businesses retain SEO value and avoid broken product links after transferring an old domain.
Original PR description
When switching from an ecommerce platform to another, a major issue is that all the links to your products change and so all of the SEO linked to those product links are lost. One way to mitigate this issue is to create redirects for each products. Once the old domain is transfered, the old product links are restored and redirect to the corresponding odoo products.
Obox remote debugging can now be enabled directly from the Obox form instead of asking customers to visit a special device URL. This makes support sessions easier to start by letting users provide the required Tailscale token in Odoo.
Original PR description
Before this commit, enabling remote debug for an Obox required accessing a specific URL on the Obox, which might be difficult to instruct clients to do. After this commit, there is a Remote Debug toggle in the Obox form view, just like the IoT box. A user simply needs to provide the Tailscale token to enable remote debug. task-6392868
The paid appointments module no longer creates a default booking fee product during installation, keeping databases cleaner for businesses that do not use paid appointments. A booking product is now created only when needed for paid appointment types, and unused unsold booking products can be removed.
Original PR description
# Purpose Installing the module "appointment_account_payment" creates a default product called "booking fees" used in paid appointment type. This auto-creation pollutes the DB of users that never uses such appointment types. Furthermore, the product couldn't be deleted once created. # Specs - Removed the creation of a default booking product upon module installation. - On the creation of a paid appointment type, will create a default product ready for edition by the user. - On manual checkbox activation, a product with a default price can be created through the dropdown menu. - Unused booking product that haven't been sold can be deleted. Task-6167887
Users can now apply common reconciliation actions to multiple selected bank statement lines at once. This reduces repetitive work by letting teams use the main action, assign partners, or set account numbers across several records in one step.
Original PR description
Added actions for multi select of bank statement lines in the list view to: - Use the primary action of all of the selected records - Set the partner for all of the selected records - Set the account number for all of the selected records task-6102308
Deleting an attachment linked to a document now moves the document to the Trash instead of removing it permanently. This protects business documents from being lost when attachments are deleted from related records such as vendor bills or chatter messages.
Original PR description
We replace the `documents.unlink.mixin`, which was previously applied only to specific models, with a generic mechanism that works regardless of the involved models. This new mechanism archives the…
We replace the `documents.unlink.mixin`, which was previously applied only to specific models, with a generic mechanism that works regardless of the involved models. This new mechanism archives the documents when their attachments are deleted, preventing their deletion. It does a little more than the mixin as the mixin was preveting the deletion of the document only when a record sharing a common attachment was deleted. Here, we also preserve the document if the attachment is deleted directly (for example from the chatter of a record). In that case, we also preserve the link between the document and the record (through the res_model and res_id of the document record). This change is motivated by use-cases similar to the following: - In document, click on the action "Create Vendor Bill" - On the chatter of the account.move, delete the attachment - Return to Documents Before, the document was deleted. Now, it has been moved in the Trash. To implement that feature, we remove the "ondelete cascade" on the attachment_id field of document and implement a custom version of it that move the associated documents (if any) in the Trash. Thanks to the api.ondelete decorator, we intercept all attachment deletion and if some of them are linked to a document we copy them and associate their copy with the documents before they are deleted. Note that the copy is cheap as odoo implements a deduplication of the store (see IrAttachment._file_write). Notes that we first have tried to preserve the attachment instead of duplicating it. But it was breaking other flow as they were expecting the attachment to be deleted. For example, when deleting a message with an attachment in the chatter, as the attachment was preserved it was still linked to the message even if it was not anymore directly linked to the model (ex.: lead) through res_model, res_id which caused the attachment to still appear in the chatter. Co-authored-by: Florian Charlier <flch@odoo.com> Task-5155496
Resolved issues and error corrections
Employees can now access and sign signature requests sent to their private email address. The request remains linked to the employee’s existing contact record, avoiding access problems while still delivering the email to the private address.
Original PR description
Before, when a signature request was sent to an employee's private email address, a new partner was created with the private email address and the signature request was linked to that new partner. Since there is a security rule where an employee cannot access a sign request item unless the partner on it matches partner for that employee, the employee is not able to see the sign request as the linked partner to the sign request item is an entirely new partner that is not linked to the employee. To fix the issue, the sign request is now linked to the employee's partner but the email itself is sent to the employee's private email. Task-5358107
Automatic bank reconciliation now retries failed statement lines once before discarding them. This helps avoid losing reconciliation work when temporary system issues, such as database conflicts, cause a failure.
Original PR description
The auto reconcile cron drops the lines whenever they raise an error which is an issue for things like serialization errors. Now the code retries failed lines once before dropping them to make sure it's an issue with the lines. task-6273202 Forward-Port-Of: odoo/enterprise#119383
This fix ensures Belgian payroll eco vouchers are calculated using the correct start and end date boundaries. It helps avoid incorrect voucher amounts for employees whose eligibility depends on precise payroll period dates.
Original PR description
Forward-Port-Of: odoo/enterprise#124073 Forward-Port-Of: odoo/enterprise#120166
Code cleanup and technical improvements
Obox report printing now uses Odoo's shared printer setup for report output, aligning it with other printer types such as ePOS, Zebra, and IoT. This should make printer management more consistent and reduce duplicate Obox-specific printing logic over time.
Original PR description
This commit adapts the Obox report printing to use the new report printing system, the common printer model for ePOS/Zebra/IoT. The Obox is added as a printer type, and the old Obox report logic removed. task-6328971 Community PR: https://github.com/odoo/odoo/pull/272451
8 changes
Enhancements to existing features
Audit check statuses now update automatically based on the status of their related accounts, reducing manual work and improving consistency. The interface also uses clearer wording, including "Last Comment" and past-tense status labels across working files and tax returns.
Original PR description
Before this commit, the status of an Audit Check (e.g., Fixed Assets) did not automatically reflect the status of its underlying accounts, forcing users to update it manually. Additionally, status labels used inconsistent tenses. This commit automates the Check status update based on the underlying account statuses: - If any account is To Review or Empty or Anomaly -> Check becomes 'To Review'. - If all accounts are Reviewed -> Check becomes 'Reviewed'. - If all accounts are Supervised -> Check becomes 'Supervised'. - If accounts are mixed (Reviewed + Supervised) -> Check becomes 'Supervised'. This commit also standardizes UI terminology by renaming the "Last Message" column to "Last Comment" and updating status labels to past tense (e.g., "Reviewed", "Submitted") across Working Files and Tax Returns. task-5388699
Peruvian e-invoicing now includes the product classification codes required by SUNAT's upcoming validation rules. This helps businesses avoid invoice rejections for affected goods when the new requirements take effect in August 2026.
Original PR description
SUNAT is updating its validation rules 2026-08-01, adding three mandatory annexes (25.1, 25.2, 25.3) to Product Catalog N25. E-invoices for these goods are rejected when the required UNSPSC code is not available in the database. Most of the required codes already exist and are active. The rest are handled here: two missing UNSPSC codes were added to the shared catalog, while the fourteen codes that exist but are inactive and the SUNAT-only code 11111111 (which is not part of the UNSPSC standard) are activated from the Peru localization instead. Doing the Peru-specific part in the l10n_pe_edi install hook and upgrade script, the way l10n_mx_edi and l10n_ke_edi_oscu do for their own codes, keeps these activations out of databases that do not use the Peruvian localization. Task-6366907 Forward-Port-Of: odoo/enterprise#124200 Forward-Port-Of: odoo/enterprise#123577
Resolved issues and error corrections
The barcode app now correctly finds manufacturing orders that were split into multiple related orders. This prevents users from seeing a false “not found” error when scanning the original manufacturing order name, keeping shop floor workflows moving smoothly.
Original PR description
### Steps to reproduce: - Create a product FP with a BOM: 1 X COMP (enough units in stock) - Create and confirm an MO for 3 units - Click on the cog wheel icon > Split the MO in 3 - On the barcode app > Operations > Manufacturing - Scan the name of your base MO #### > Error: No product or order found for barcode ... ### Expected behavior: Scanning an existing MO only adds its barcode as a `search_default_name`: https://github.com/odoo/enterprise/blob/598a8e335605fd68e3ceb5c1170864243426f994/stock_barcode_mrp/models/mrp_production.py#L162-L178 However, while this search is performed with an ilike, we only check the existence of an exact match before raising an error, which does not happen since our splitted MOs have a name: barcode-001, barcode-002, barcode-003,... opw-6376937
Invoices marked as excluded from follow-up are now consistently left out of follow-up email attachments and printed follow-up letters. This prevents customers from receiving documents for invoices the business has intentionally removed from follow-up actions.
Original PR description
Steps to reproduce: 1. Install Accounting and create an invoice for a customer which has a due date in the past 2. Make sure the payment term for the invoice is "Immediate Payment" and Send the…
Steps to reproduce: 1. Install Accounting and create an invoice for a customer which has a due date in the past 2. Make sure the payment term for the invoice is "Immediate Payment" and Send the invoice. 3. Open the contact form and click on the Customer Statement smart button 4. Exclude the invoice using the 'No Follow-Up' toggle 5. In the Accounting tab in the contact form, click on send 6. Open the internal link of the Content Template, go to the options tab and select 'Print Follow-up Letter' in Dynamic Reports 7. Save the configuration and send the email Issue: Excluded invoices still appeared as PDF attachments in the follow-up email and were merged into the printed follow-up letter PDF. Why this happens: Both `default_get` in `account_followup.manual_reminder` and `_get_invoices_to_print` in `res.partner` traversed `unreconciled_aml_ids` without filtering out lines where `no_followup = True`, so excluded invoices were included regardless. opw-6310602 Forward-Port-Of: odoo/enterprise#124541 Forward-Port-Of: odoo/enterprise#122249
French VAT declarations now handle SIRET numbers even when users enter spaces, reducing failed submissions. The update also checks bank account number formatting and warns users before incorrect details cause issues.
Original PR description
This commit resolves an issue where VAT declarations failed when the provided SIRET number included spaces. Since check_siret verifies the format, we now strip all spaces from the input. Additionally, this commit introduces a validation for bank account numbers, ensuring that we warn the user if the account number is wrongly formatted. task-6253745 Forward-Port-Of: odoo/enterprise#124448 Forward-Port-Of: odoo/enterprise#120689
Fixed an issue where emailing the Partner Ledger could fail for companies using different currencies. The email wizard now opens reliably in multi-currency setups, while single-currency setups are unchanged.
Original PR description
### Description of the issue/feature this PR addresses Sending the **Partner Ledger** report by email in a multi-currency setup (several companies using different currencies) crashes the send wizard…
### Description of the issue/feature this PR addresses Sending the **Partner Ledger** report by email in a multi-currency setup (several companies using different currencies) crashes the send wizard on opening with: ``` psycopg2.errors.UndefinedTable: relation "account_currency_table" does not exist ``` ### Current behavior before PR To compute the recipients, `AccountPartnerLedgerReportHandler._get_report_send_recipients` runs `_get_query_sums`, whose SQL joins the currency table. In a multi-currency setup that table is a **temporary** table that must be created beforehand by `AccountReport._init_currency_table`. Every regular rendering entry point calls `_init_currency_table` before running currency-table queries, but the report-sending path does not, so the query fails on a missing `account_currency_table` relation. ### Desired behavior after PR is merged `_init_currency_table(options)` is called before running the query, so the temporary table exists. It is a no-op in mono-currency setups (early return in `_init_currency_table`), so mono-currency behavior is unchanged. ### Steps to reproduce 1. Have several companies using different currencies. 2. Select more than one of them in the company switcher. 3. Open **Accounting > Reporting > Partner Ledger**. 4. Click **Send by email** → the wizard crashes on opening. Video: https://drive.google.com/file/d/1skpg7YDtxcY1PCtURyzk5PdFPi7ZPreG/view A regression test covering the multi-currency send-recipients path is included in `test_partner_ledger_report.py`. I've created the task #6362131 for this issue
This fix ensures Manufacturing Planning uses the product's Bill of Materials batch size even when no specific BOM is selected while adding the product. This helps planners get correct replenishment quantities and avoid under-planning production.
Original PR description
In MPS, if a product’s Bill of Materials (BOM) is not specified at the time of addition, the system will not correctly account for batch size. Steps to reproduce: ------------------- * Create a…
In MPS, if a product’s Bill of Materials (BOM) is not specified at the time of addition, the system will not correctly account for batch size. Steps to reproduce: ------------------- * Create a product with a bom that has a batch size of 2 * Open MPS * Add the product - without specifying the bom - Route Manufacture * Add 1 in the Forcast Demand -> the batch size from the bom it's not taken into account. Observation: ------------- When updating mps, it will call get_production_schedule_view_state: https://github.com/odoo/enterprise/blob/7092dd2cc3578c3f22d1fbc82d958d57e2f93553/mrp_mps/models/mrp_mps.py#L424 this function when calculating the quantity to resplenish will call _get_resplenish_qty: https://github.com/odoo/enterprise/blob/7092dd2cc3578c3f22d1fbc82d958d57e2f93553/mrp_mps/models/mrp_mps.py#L534 to know the quantity to resplenish it will need the batch size, in mps they will only consider the batch size from the bom registered: https://github.com/odoo/enterprise/blob/7092dd2cc3578c3f22d1fbc82d958d57e2f93553/mrp_mps/models/mrp_mps.py#L863-L865 Since there is no default value for bom_id, If there is no bom selected, there is no batch size. opw-6259956
Envia shipping rate requests now send insurance information in the format expected by the carrier API. This ensures quoted delivery prices reflect configured insurance coverage, avoiding underquoted rates for insured shipments.
Original PR description
Issue ----- Insurance request is not reflected on the rating given by Envia. Steps to reproduce ----- - Create a MX company - Set up Envia - Fedex Nacional Economico (ground) - Create a MX client - Create a product (with some weight) - Create a SO - Add the product - Add envia delivery and get a rate - Update Envia delivery method - Set insurance to 50% - Go back to the SO - Add envia delivery and get a rate > The rate is the same both times Cause ----- We are passing the insurance value as a `insurance` field on the shipment, which is not what the API expects. We should instead pass it in `additionalServices` as shown in the example of https://docs.envia.com/docs/additional-services#how-to-add-services-to-a-shipment Follow up of 7258e4a ----- Ticket: opw-5254952
8 changes
Enhancements to existing features
Online payment initiation now includes the payer's bank account details and account holder name when required by providers such as Powens. This helps more bank payments start successfully by giving providers the information some banks need upfront.
Original PR description
With Powens, some banks requires the payer's bank information such as bank account number and bank holder name. This commit adds those informations to the odoofin route to be sent to the payment providers. task-6373634
Resolved issues and error corrections
Non-SEPA bank journals now default to the older PAIN 003 payment file format instead of PAIN 009 when users cannot manually choose the version. This helps prevent bank rejections for international payments and improves payment processing reliability.
Original PR description
Before this PR: - The sepa version field is hidden on non-SEPA journals and defaults to the pain009. Banks often reject this version, and users cannot change it because the field is invisible. After this PR: - The logic defaults to PAIN 003 when the SEPA payment method is not present. This ensures bank compatibility for international payments where the version cannot be set manually. task-6085943
This fixes an error when printing Chilean delivery guides for kits whose components use different unit types than the kit product. The guide now uses the component product price when needed, preventing failed document generation for affected deliveries.
Original PR description
When a kit is delivered, each component move is linked to the kit's sale order line. Pricing the delivery guide in "sale order" mode converted the component quantity into the kit's sale UoM. For a component sold in a different UoM category than the kit, this cross-category conversion raises a UserError. Steps to reproduce: - Create a BoM for a kit product with a component in a different UoM category - Create a customer with Delivery Guide Price = "From Sale Order" - Sold the kit in a sale order and deliver it - On the delivery, print the delivery guide -> error This fix makes the guide price for a component move to be "product" if the component's product is different from the related sale line product, avoiding the cross-category UoM conversion. opw-6327895 Forward-Port-Of: odoo/enterprise#122776
Intercompany deliveries can now automatically remove package references before receipt, avoiding mismatched inventory records between companies. This helps keep intercompany stock balances clearer and reduces confusion from leftover package-based records.
Original PR description
Issue: Compare to lot and serial number package are not multi company. It means that the package don't pass from a company to the other. So when a company deliver to another. The delivery will create a quant with the package. However the receipt in the other company will create a new quant without package (or a new package). It means that the quants are never reconcile and it could become difficult to understand what remains in intercompany location and what are artifact from past movements. In order to fix it, we introduce a new system parameter to directly unpack after the delivery. This way the receipt is always without source package and will automatically decrease the quant. opw-6376983
Amazon Ground shipments created through Envia now include each product's weight in the label request. This prevents valid high-quantity shipments from being blocked by Amazon's weight validation error.
Original PR description
**Issue:** Envia API documentation is very bad. When trying to generate an Amazon Ground shipping with Envia, the API will sometimes reject the payload with the following error: `Total items weight…
**Issue:** Envia API documentation is very bad. When trying to generate an Amazon Ground shipping with Envia, the API will sometimes reject the payload with the following error: `Total items weight exceeds package weight. Please refer to API documentation for allowable limits. (D-703)` Even though the [Envia documentation](https://docs.envia.com/reference/create-shipping-label) doesn't include it, it seems that Amazon requires the weight for each product. If the payload doesn't include the per-item weight, Amazon will set a default weight, which will cause the error to show up if the delivery contains a high quantity. This can be a blocking issue for some customers. **Steps to reproduce on a fresh DB:** - Install Inventory, Sales, and Envia Shipping - Switch company to be based in India (need to provide an address to deliver from, I just used the Odoo India address - InfoCity Gate, Gandhinagar, Gujarat 382007) - Configure an Amazon delivery carrier with Envia (India seems to be the only country that supports Amazon with Envia) - Inventory > Configuration > Delivery Methods > Envia.com method - Must be in a Production environment (because Envia's sandbox server does not work for some reason?) - Add an Envia Production Access Token (will have to use one with some funds) - Change 'Ship From' to India - Configure the `Envia.com Service Name`, set Carrier and Service to AMAZON and AMAZON - Amazon Shipping Standard - Create a demo product, give it an arbitrary weight like 0.1 kg - Create a sales order to an Indian customer, include the demo product with a high quantity (like 20), confirm (might have to create a warehouse and configure the customer's information) - On the generated picking, set the Carrier to Envia.com on the Additional Info tab - When trying to Validate, it should throw the error **Fix:** When generating the payload in _get_shipping_lines() in envia_request, include the item weight in the dictionary. Related ticket: opw-6261682
The bank reconciliation report now correctly includes all unreconciled transactions up to the selected date, not just those from the latest statement. This helps accounting teams get a complete view of outstanding bank items and avoid missing older transactions during reconciliation.
Original PR description
The reconciliation report lists only the unreconciled transactions from the last statement instead of all of them Steps: - Create 4 statements with one statement line each with different dates - Go to the reconciliation report (via the three dot menu on bank journal kanban card) - select date as Today -> only the line from the last statement is displayed opw-6250370 Forward-Port-Of: odoo/enterprise#119386
Rental orders using custom make-to-order purchase routes now correctly create the expected return transfer. This prevents missing return operations when businesses rent products that must first be purchased from a vendor.
Original PR description
### Steps to reproduce: - In the settings enable: Multi-Steps Routes and rental transfers - Unarchive the MTO route - Create a rental product P with a buy route and a set vendor - Create a rental…
### Steps to reproduce: - In the settings enable: Multi-Steps Routes and rental transfers - Unarchive the MTO route - Create a rental product P with a buy route and a set vendor - Create a rental order for 1 x P and set the the MTO route on the sol - Confirm the order #### > The delivery as well as the purchase for 1 unit of P was generated but the return was not. ### Cause of the issue: The procurement generated to handle both the delivery and the return rental picking are handled by the `_create_procurements`: https://github.com/odoo/enterprise/blob/b0e48baaf99bdc4faefd2ffdd3bd5637fb548593/sale_stock_renting/models/sale_order_line.py#L353-L374 The `route_ids` set and used is the `mto_route` set on the sol: https://github.com/odoo/odoo/blob/0f061503e26ac8c441d62d91947419119e48c47a/addons/sale_stock/models/sale_order_line.py#L415-L422 https://github.com/odoo/odoo/blob/0f061503e26ac8c441d62d91947419119e48c47a/addons/sale_stock/models/sale_order_line.py#L282-L297 However, in the present case, the mto route does not contain any rule with a relevant `location_src_id` in the rental location so that the return will not be generated. opw-6361322
Uruguayan electronic export invoices that are fully offset by discounts can now be generated with the required discount details. This helps exporters issue valid zero-total export invoices for customs or trade requirements without validation errors.
Original PR description
## Problem When generating an export CFE (e-Factura Exportación) in the Uruguayan EDI module, invoices that include a discount line equal to the subtotal — resulting in a **total of 0.00** — were not…
## Problem When generating an export CFE (e-Factura Exportación) in the Uruguayan EDI module, invoices that include a discount line equal to the subtotal — resulting in a **total of 0.00** — were not handled correctly by the XML/CFE generation logic. This use case is valid and required by exporters who need to reflect the declared value of goods/services while invoicing at zero (e.g. to comply with customs or incoterm requirements such as FCA). In Uruware's validation portal, the "Descuentos y Recargos" (discounts & surcharges) section of the subtotal block must be correctly populated for the CFE to be accepted. **Example:** An invoice with a line of 648.00 UYU and a global discount of −648.00 UYU → Total: 0.00. The export value is still declared, taxes are zero, but the CFE must reflect the discount amount explicitly. <img width="592" height="679" alt="example_expo_invoice_discount" src="https://github.com/user-attachments/assets/aa83c158-e342-4da5-a251-fc209bbed5c4" /> ## Root Cause The CFE template (`cfe_template.xml`) and the move computation logic (`account_move.py`) did not account for the case where export invoices carry line-level or global discounts that zero out the total. The discount amount was either omitted from the XML nodes or computed incorrectly, causing Uruware validation to fail or the discount block to not render. ## Fix - **`l10n_uy_edi/models/account_move.py`** — Updated the export invoice computation to correctly include discount amounts in the CFE data dict, ensuring the `ValorDR` is filled with the value of the discount per line. - **`l10n_uy_edi/views/cfe_template.xml`** — Adjusted the template condition so `MntExpoyAsim` node accepts 0 as value. ## Steps to Reproduce (before fix) 1. Create an export invoice (e-Factura Exportación) for a foreign partner. 2. Add a product line with a unit price, e.g. 216.00 × 3 = 648.00 UYU. 3. Add a global discount of 648.00 (same amount) so the total is 0.00. 4. Confirm and send to Uruware — the CFE is rejected / discount block is missing. ## Verification After the fix, the same invoice generates a valid CFE accepted by Uruware with the discount correctly reflected in the `DscRcgGlobal` node and the discount line visible on the printed document.
1 change
Resolved issues and error corrections
This fix prevents payment document creation from failing when accounting views pass an unrelated document type value. If the incoming type is not valid for Documents, the system now uses the standard default so EDI payment updates can proceed normally.
Original PR description
In certain scenarios, a default_type context can be passed during document creation, and this value may not exist in the type selection field, as it may come from a type in another model. Steps to…
In certain scenarios, a default_type context can be passed during document creation, and this value may not exist in the type selection field, as it may come from a type in another model. Steps to reproduce using MX EDI update payment: - Setup a Mexican company with MX EDI - Install the documents_account module and create a folder for journals where you will place customer payments (ex: journal PAY/) - In accounting views, group journals by type, which will adds default_type = <journal type> when opening entries from this view - From this view, open the Customer Invoices journal, create and post an invoice - Register a payment, and then click on Update Payment button, which will triggers an EDI document creation with default_type="sale" in the context, causing the error 'ValueError: Wrong value for documents.document.type: "sale"' This fix falls back to the default document type if the type in the context is not in the selection, preventing the error and allowing the document to be created correctly. opw-5742850 opw-6182877