Friday, August 22, 2025
27 changes · saas-18.4
New functionality added to Odoo
Odoo now supports Swedish BBAN, Bankgiro, and Plusgiro payments, including XML export files for payment processing. This helps Swedish businesses handle local payment formats directly in their accounting workflows.
Original PR description
Enable generic Swedish BBAN and Bankgiro/Plusgiro payments and xml exports. Task: 3814018 Forward-Port-Of: odoo/enterprise#92584 Forward-Port-Of: odoo/enterprise#87850
Enhancements to existing features
Accounting now includes helpers to spread global discounts and returned merchandise across individual invoice lines for electronic invoicing. This improves compliance and accuracy for formats such as Mexico's CFDI, where discounts and returns need to be reflected line by line.
Original PR description
This commit also adds a new helper '_dispatch_global_discount_lines' that can be used to split the global discount lines across the others base lines. That way in EDI like Mexico, the global discount can be reported line by line as a discount per line and no longer a big discount applied on a single line. There is also another helper '_dispatch_return_of_marchandise_lines' that allows to dispatch negative lines using the quantity. For example, if you buy 3 times the same product but one is returned because broken, you will end up with a sell of 2 products instead of 3 but having a discount of 33.33%. This makes the difference when generating the mexican CFDI. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#223530
Resolved issues and error corrections
Spanish 0% EU and export sales taxes are now classified as exempt with the correct legal exemption reasons. This helps ensure Spanish electronic tax reporting uses the right tax treatment and removes older duplicate exempt tax entries that are no longer needed.
Original PR description
Currently 2 sales taxes are misconfigured.
They both should be marked as 'exento' ("Exento") instead of 'no_sujeto_loc' ("No Sujeto por reglas de Localization")
- "0% EU G"; with "Exempt Reason" E5 / "Art. 25"
- "0% EX G"; with "Exempt Reason" E2 / "Art. 21"
This commit updated those taxes
Due to this the following sales taxes become obsolete.
- "VAT Exempt (Art. 21)"
- "VAT Exempt (Art. 25)"
They are deleted in this commit.
opw-4850585
Forward-Port-Of: odoo/odoo#223829
Forward-Port-Of: odoo/odoo#223603Features or functions removed from Odoo
The website editor toolbar no longer offers a font family picker. This helps avoid expectations around custom web fonts, which can be complex to support without hurting website performance.
Original PR description
Because it is quite complex to enable non-websafe fonts in website without impacting the performances, it was decided to remove the possibility to change the font family with the toolbar within website to deter users from requesting this feature. This commit removes the font family picker from the toolbar when editing the website. task-4367641
Completing large batches of manufacturing work orders is now much faster. This reduces waiting time for production teams when confirming many work orders, especially when they belong to the same manufacturing order.
Original PR description
### Description: Improves the performance of `button_finish` when confirming many work orders. Previously, the method would update each work order individually, leading to slow performance. This PR changes the way the write is executed to do it by batch, which is much faster, especially when work orders share the same manufacturing order. ### Benchmark (in 18.0): | N° of work orders | Before | After | |-------------------|--------|-------| | 250 | 14s | 610ms | | 500 | 53s | 1s | ### Reference: opw-4957774 Forward-Port-Of: odoo/odoo#223588
This update improves how discounts and negative lines are distributed on Mexican electronic invoices and related POS invoices. It helps produce more accurate compliant invoice totals, especially for refunds or complex discount scenarios.
Original PR description
Forward-Port-Of: odoo/enterprise#92727
Manufacturing order overviews now calculate Bill of Materials costs using the correct unit of measure. This prevents costs from being overstated when products are manufactured in packs, giving users accurate production cost information.
Original PR description
Steps to reproduce:
- Create a storable product “P1”:
- UoM: Unit
- BoM:
- Pack of 6 of P1
- Components:
- C1: 6 units (price = $5)
- C2: 6 units (price = $10)
- Create a manufacturing order:
- 1 Pack of 6 of P1
- Confirm the MO
- Go to the MO overview
Issue:
- MO cost = $90 → ($5 * 6) + ($10 * 6) → correct
- BoM cost = $540 → ($5 * 36) + ($10 * 36) → wrong
Cause:
The BoM cost calculation uses `product_uom_qty` (6 units) of the production instead of computing the real quantity needed with the correct UoM.
As a result, component quantities are multiplied twice.
opw-4954953
Forward-Port-Of: odoo/odoo#223730This fixes an issue where older Saudi ZATCA Phase 1 invoice QR codes could disappear after the electronic invoicing module was installed. Businesses can now see the correct Phase 1 or Phase 2 QR code on invoices, helping keep Saudi invoicing documents complete and compliant.
Original PR description
Phase 1 ZATCA QR codes disappear when l10n_sa_edi is installed, there is a check for document submission to display the QR code for Phase 2 which older Phase 1 invoices will not pass as it doesn't use edi. Description of the issue/feature this PR addresses: Phase 1 ZATCA QR Code disappears once l10n_sa_edi is installed Current behavior before PR: Always hide Phase 1 ZATCA QR Code Desired behaviour after PR is merged: Showing Phase 1 and Phase 2 ZATCA QR codes based on the invoice task-5005304 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#222627 Forward-Port-Of: odoo/odoo#222285
This fixes a sales order issue where a customer's signature could be saved too early, leaving the order impossible to sign again if confirmation failed. The change ensures failed confirmations can roll back properly, so customers can retry signing after the underlying issue is resolved.
Original PR description
In this bug, sale order signature is commited before confirm, causing sale order not be able to be signed later, if confirm fails. To reproduce the bug: 1- Create a consumable product with `Buy` and `Dropship` routes enabled in the inventory tab 2- Do not put in any vendors in the purchase tab 3- Create a sale order with this product and uncheck the online payment option. 4- On an incognito browser, sign in as portal user and open the sale order 5- Click on the `Accept & Sign` button and confirm 6- We get an invalid operation error because of not having vendors 7- Reload the order. As you see, it is not possible to sign it To fix the issue, we use flush instead of commit, so when confirm fails it can rollback. Note: It is not easy to write a test for this case, because the `action_confirm` fails in a specific case when `purchase_stock` and `stock_dropshipping` are installed. opw-4864150 Forward-Port-Of: odoo/odoo#223610
Dragging certain website building blocks no longer loses the original drop spot when the block is the only visible item in its container. This makes page editing more reliable and keeps drop indicators looking consistent for users arranging content.
Original PR description
Steps to reproduce: - Drop the "Banner" snippet. - Click on the "Blockquote". - Start to drag it. => No dropzone appears where it was so we cannot drop it back. When starting the drag and drop of an element that is the only (visible) child of its parent, an invisible clone is created and added where the element was, in order to have a dropzone to drop it where it was. The issue here is that this clone is a simple `<div>`, and inner snippets cannot be dropped next to `<div>` elements, which is why no dropzone is appearing despite the clone being present. This commit fixes that by making this clone a real clone of the dragged element, so it always has valid classes and tagname to make the dropzone appear. In addition, by giving the clone the same dimensions as the element, it allows to have better looking dropzones (e.g. a vertical one when dragging the last column of the "Steps" snippet instead of a big horizontal one). task-4367641
Orders placed through self-ordering and paid online are now sent to the preparation display, matching the behavior of terminal payments. This helps kitchen or preparation staff see and fulfill paid orders without manual intervention or delays.
Original PR description
After this pr: https://github.com/odoo/odoo/pull/213493 the orders were not sent to the preparation display if the order was payed with and online payment method. This commit add the same logic as the terminal payments to send the order to the preparation display. Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#222648
This fix restores an optimization that avoids unnecessary image data loading when only file size information is needed. It can make product kanban and similar views load faster, especially when image storage has higher latency.
Original PR description
Since 7744886d6141ca7971d91807d0444c707e10fdf8, reading binary field with bin_size=True still reads the ir.attachment datas field, which is relatively slow with some storage backends. In the products kanban view this can easily add 1 sec to web_search_read, if there is a 10ms latency when reading images. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#223812 Forward-Port-Of: odoo/odoo#221270
This fixes an issue where replacing an image in the website editor could save the uploaded file without linking it to the correct page or content record. Images now use the nearest editable website content to keep attachments properly organized and reliable after saving.
Original PR description
[FIX] html_builder, *: save attachment with correct resource info *: html_editor, website Steps to reproduce the problem: - Add a "Text-Image" snippet on the website. - Replace the image. - Save. -> The `/html_editor/modify_image/` is called with the `res_model` and `res_id` parameter set to `null`. The problem appeared since the [website refactoring]. To solve the problem, the `res_model` and `res_id` parameters are set thanks to the information of the closest savable element from the image. Related to task-4367641 [website refactoring]: https://github.com/odoo/odoo/commit/9fe45e2b7ddbbfd0445ffe25a859e67a316d02b2
Point of Sale now shows the right checkout message when a takeaway or delivery order is missing required details such as a time slot, customer, or delivery address. This helps staff quickly fix the exact issue and avoids orders being blocked by misleading prompts.
Original PR description
STEPS TO REPRODUCE: ---------------- - Install `pos_restaurant`. - Set up a "Takeaway" preset with "identification = not required". - Remove all slots for today. - Try to place an order using "Takeaway" or "Delivery" without selecting a slot or address. ISSUE: ----------- - Only the "customer required" popup appeared, even if slot or address was missing. - For Delivery, missing address was not checked. CAUSE: ----------- - One single dialog was used for all checks, so it didn't check each thing separately. FIX: --------------- - Show specific popup depending on what is missing (customer, address, or slot). Task-4892105 Forward-Port-Of: odoo/odoo#222387 Forward-Port-Of: odoo/odoo#216216
Partial payment links on invoices now request the intended partial amount instead of the full invoice balance. This prevents customers from being asked to overpay when using a payment link and makes invoice payment flows more reliable.
Original PR description
Versions -------- - 18.0+ Steps ----- 1. Have an unpaid invoice; 2. generate a partial payment link; 3. open partial payment link; 4. click the Pay button. Issue ----- The invoice's full amount gets requested. Cause ----- Commit 5697493e0091 added `amount` as a named keyword parameter in an `_invoice_get_page_view_values` override, but failed to pass it along to the call to `super`. As the base method no longer receives an `amount` parameter, it defaults to the invoice total. Solution -------- Pass `amount` to the `super` call. opw-5013044 Forward-Port-Of: odoo/odoo#223554
This fix prevents a crash when users freeze and share a spreadsheet that contains an Odoo List. It ensures the spreadsheet is created with the right context so the sharing flow works reliably.
Original PR description
Steps to reproduce: - Install documents_spreadsheet (enterprise) - Create a spreadsheet with an Odoo List - Open the document view - Select the spreadsheet - Click on "Freeze and Share" => Boom Please see the enterprise PR for the test. Task: 5025331 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix ensures invoice journal line amounts are restored correctly when a user switches from a foreign currency to the company currency and back before saving. It prevents exchange rates from being applied twice or incorrectly, helping keep invoice accounting values accurate.
Original PR description
Steps to reproduce: - Enable a foreign currency with rate - Create an invoice in foreign currency - Switch to company currency, then back to foreign currency before saving - Check journal items values Issue: Amount currency and balance have been affected by the currency rate even if the original currency was restored before saving opw-4864994 Forward-Port-Of: odoo/odoo#222870
Fixed an issue where employees assigned to company-wide working schedules could be missed when creating timesheets for public holidays. This ensures holiday-related timesheet entries are generated consistently for employees using global schedules.
Original PR description
_*= project_timesheet_holidays Steps to Reproduce: --------------------------- 1. Create a global working schedule (company should be False). 2. Assign this working schedule to any employee. 3. Create a public time off (for all the working schedule). 4. You will notice that the timesheet entry is not generated for the public holiday for that employee. Issue: ------------------------------- - Employees who use the WS without a company are excluded from timesheet creation. Cause : -------------------------------- - When grouping employees by calendar global WS (with no company) were being excluded. - And the timesheets were not generated due to the check `calendars_dict[calendar_id].company_id != company` when the WS had no company Fix: ------------------ - We will add the domain to include the global WS and and we will check if the the WS has company id then only check the condition. task-4900941 Forward-Port-Of: odoo/odoo#219916
Turkish e-Dispatch XML files now use the main commercial customer for customer details and the specific delivery contact for the delivery address. This improves compliance and accuracy, including using customs ZIP information for non-Turkish customers and hiding XML generation when no delivery address is available.
Original PR description
Behaviour before this commit: - Previously, the picking partner was used for sending both the Delivery Customer and delivery address in the XML. - Secondly, ZIP was used in Delivery Customer regardless of the country of the partner (Turkish or Non-Turkish) Desired behaviour after this commit: - After this commit, the commercial partner of the picking partner will be used for sending the Delivery Customer data and picking partner itself will be used for sending the Delivery Address in the XML. - Additionally, if the commercial partner is non turkish, customs ZIP will be used in the Delivery Customer in the XML. - If the delivery is validated without giving Delivery Address, then the 'Generate e-Dispatch (XML)' button will be hidden. TaskID:4918748 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#223563 Forward-Port-Of: odoo/odoo#218096
The Attendance overview list now shows only employees who actually have attendance records when grouped by employee. This avoids clutter and makes attendance reporting easier to review without changing the Gantt view behavior.
Original PR description
To reproduce: ============= - Activate the "Attendances" app. - Go to Attendances > Overview. - Switch to list view. - Group by Employee. Issue: ====== The current domain fetches all employees…
To reproduce: ============= - Activate the "Attendances" app. - Go to Attendances > Overview. - Switch to list view. - Group by Employee. Issue: ====== The current domain fetches all employees matching the filter, regardless of whether they have attendance entries in the grouped model. https://github.com/odoo/odoo/blob/5b5f0bf795ca538e91f063f2b3185c12b1d0a992/addons/hr_attendance/models/hr_attendance.py#L677 Fix: ==== Restrict the employee list to only those linked to a resource that appears in the grouped data https://github.com/odoo/odoo/blob/5b5f0bf795ca538e91f063f2b3185c12b1d0a992/odoo/models.py#L2360-L2361 The problem is the behavior of gantt view will change it's behavior So we have to applied only to the list. there's something unique when we call it from the gantt which is `gantt_start_date` property that we will use it so we can differentiate between list and gantt view -- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#223594 Forward-Port-Of: odoo/odoo#223181
This update prevents the website editor from accidentally making protected page areas editable and improves how replaceable media is detected. It helps avoid unintended edits to content that should not be changed or saved, reducing editor confusion and preserving page integrity.
Original PR description
[FIX] html_builder: avoid setting contenteditable on some elements The goal of this commit is to prevent the system from setting the `contenteditable` attribute to true on elements located inside…
[FIX] html_builder: avoid setting contenteditable on some elements The goal of this commit is to prevent the system from setting the `contenteditable` attribute to true on elements located inside `.o_not_editable`. This behavior was lost since the [website refactoring]. Related to task-4367641 [website refactoring]: https://github.com/odoo/odoo/commit/9fe45e2b7ddbbfd0445ffe25a859e67a316d02b2 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- [FIX] html_builder: avoid editing non savable media The goal of this commit is to improve the handling of the `click` and `dblclick` events on elements inside the editable. The idea is that we want to do an action to replace the media (open a tooltip to show that the media is replaceable or open the media dialog) when the user clicks or double clicks on an editable media. To do so, the `mediaSelector` selector was built to remove the elements that had the branding (`data-oe` information) from the list of elements on which we want to do the action. The idea was that if the element itself had the branding, it was not savable (its content is savable but the element in itself is not) so we do not want to replace it. This is true but it is redundant of the `isReplaceableMedia` method. This commit removes the `mediaSelector` selector and improves the `shouldEditableMediaBeEditable` util function; a media that has the `o_editable_media` class is considered editable if it is a descendant of a savable element (an element that has the `o_editable` class) but is not a savable element itself. Indeed, attributes such as `src` are not saved on savable elements. Even if there are nothing failing before this commit, a test has been added for the sake of completeness Related to task-4367641
This fix prevents the product page editor from reloading too early when replacing a product’s main image, avoiding a crash during image selection. It also restores missing editor action dependencies so layout and width controls work reliably on product pages.
Original PR description
__Current behavior before commit:__ When trying to replace the main image on a product page, the iframe reloads before the user can choose an image in the dialog. Therefore, when the user chooses on an image the editing element is already removed, leading to a crash. __Description of the fix:__ Disable the automatic reload for `ProductReplaceMainImageAction` like it was done in saas-18.3. __Steps to reproduce the issue:__ 1. Go to a product page 2. Open the editor 3. Click on the "Replace" button next to "Main Image" 4. Click on an image in the dialog 5. Traceback: `TypeError: Cannot read properties of null (reading 'getComputedStyle')` opw-5010040
Fixes an accounting reconciliation issue where invoices and vendor bills involving different partners could be marked paid with the wrong partner on generated transfer lines. This helps keep partner-based financial reports, such as the Partner Ledger, accurate in workflows where customer invoices and vendor bills are reconciled together.
Original PR description
**Steps to reproduce:** - Install account_accountant - Create an invoice ($100) for Customer X - Create a bill ($100) for Vendor Y - From "Customer Invoices" journal in Accounting dashboard, open…
**Steps to reproduce:** - Install account_accountant - Create an invoice ($100) for Customer X - Create a bill ($100) for Vendor Y - From "Customer Invoices" journal in Accounting dashboard, open "Payments Matching" - Select the invoice and the bill - Reconcile them **Issue:** A move is created with 2 lines that will mark both invoice and bill as paid. However, on both created lines, the partner is "Vendor Y", which is wrong as it will generate incorrect reports (e.g. Partner Ledger). One line should have "Vendor Y" as partner and the other line should have "Customer X". This kind of reconciliation is apparently current in India. **Cause:** When reconciling lines from 2 accounts exactly, a transfer from one account to the other one is created. The transfer is made from the account where the absolute amount to move is the lowest. A transfer is made for each partner that has a move being reconciled with the source account. The transfer is crediting (or debiting) the source account and debiting (or crediting) the reconcile account with the same partner. This is working most of the time but it totally ignores all the partners linked to the moves with the reconcile account. **Solution:** Create one line of the transfer with the source account and the partner as before. For the line on the reconcile account, first check if there's one for the same partner, currency and sign (of the amount to transfer). If not, try to find another partner with the same currency and sign. Otherwise, fall back on the same partner as the line on the source account as it was done before. opw-4735147 Forward-Port-Of: odoo/enterprise#92909 Forward-Port-Of: odoo/enterprise#89972
Receipt validation now correctly prints lot or serial number labels when a required quality check is completed. This prevents missed labels during receiving workflows and also improves handling when receipts contain products with and without quality checks.
Original PR description
## Issue: When 'auto_print_lot_labels' is activated on Receipts Operation Type, and you received a product, the print action wasn't trigger when you validate before making the Quality Check The…
## Issue: When 'auto_print_lot_labels' is activated on Receipts Operation Type, and you received a product, the print action wasn't trigger when you validate before making the Quality Check The wizard is automatically opened but when you click on the Pass button, the wizard was closed without sending the print action ## Cause: The action wasn't return by the wizard function 'action_generate_next_window()' making the only action to be a 'act_window_close' ## Note: The state wasn't correctly set to done for all products when you validate pickings both with and without QCs in them at the same time, it should now be fix Enabling Delivery Slip for the Receipts will make the SN to not be print even after disabling the option ## Steps to reproduce: - Toggle the Lot/SN Labels option in the Hardware Tab for the Operation Type Receipts - Create a Product tracked by Unique Serial Number - Add a Quality Check for the Receipts operation - Create a New Receipt for the product - Mark as Done and Add the Serial Number - Validate the receipt and Pass the check - Before the fix, no document was downloaded opw-4790427 Forward-Port-Of: odoo/enterprise#92783 Forward-Port-Of: odoo/enterprise#90134
This fix ensures employee identification details are included when point-of-sale sessions sync after clocking actions. This prevents errors on other devices when they communicate with the Belgian fiscal blackbox, improving reliability for affected POS setups.
Original PR description
Before this commit, when clocking, the session was synchro with other devices but without the _employee_insz_or_bis_number custom field. _employee_insz_or_bis_number was thus not accessible after the device receives the websocket message and the pos was returning a traceback when trying to send a message to the blackbox. This commit fixes the issue. Forward-Port-Of: odoo/enterprise#92847
This fixes a timing mismatch that could cause Mexican electronic invoices to show a different CFDI date than the invoice posting time. It also keeps invoice records properly locked during sending, reducing the risk of inconsistent invoice processing.
Original PR description
`fecha_datetime` could be set to a different value than the `document_post_time` passed as parameter because of the `min`. We also must revert the `_cr.commit` during the sending because it removes the lock on records. Instead we set the invoice post time and commit before locking. task-none Forward-Port-Of: odoo/enterprise#92355
Regular users can now retrieve DHL shipping rates without being blocked by an access error on protected shipping account details. This keeps quotation workflows moving when DHL legacy delivery methods are used.
Original PR description
Versions -------- - saas-18.3+ Steps ----- 1. Have DHL (legacy) as a delivery method; 2. log in as demo user; 3. create a quotation with a shippable product; 4. click "Add shipping"; 5. select DHL; 6. click "Get rate". Issue ----- > Access Error: > You do not have enough rights to access the field "dhl_account_number" on Shipping Methods (delivery.carrier). Cause ----- The error gets thrown in the `_set_dct_bkg_details` method. In previous versions, the `dhl_account_number` field would still be in cache after `srm.check_required_value` was called, as this method checks whether the `carrier.dhl_account_number` field is non-empty in sudo mode. As of saas-18.3, field access is checked even if the value is available in cache, resulting in the access error. Solution -------- Use `sudo` to retrieve the `dhl_account_number`. opw-4899776 Forward-Port-Of: odoo/enterprise#92557