Daily updates from Odoo
Thursday, June 11, 2026
281 changes
13 changes
Resolved issues and error corrections
This update resolves a technical issue preventing users from successfully adding AI-generated images to product pages within the Enterprise edition. The fix corrects a mismatch in data handling, ensuring the system correctly processes multiple images when adding media. This ensures a smoother experience for users utilizing AI-generated content.
Original PR description
A traceback is produced when trying to add AI-generated images to a product using "Extra Media" -> "Add More". **Origin of the problem** The `ProductAddExtraImageAction` in `website_sale` always opens the Media dialog with `props.multiImages = true` and the save handler expects `loadResult.imgEls` to be an array. The `aiSave` method patched onto `ProductAddExtraImageAction` by `ai_website_sale` did not account for this, and called `apply()` with a single image element instead of an array, causing a traceback. **Fix** In `aiSave`, wrap `imgEls` in an array before calling `apply()`. task-6263899
This update resolves a recurring problem where payments at self-order kiosks using the Worldline terminal would get stuck. The fix allows the system to correctly handle terminal disconnections and provides more specific error messages based on the terminal's feedback, improving the kiosk payment experience.
Original PR description
This PR fixes some payments in pos kiosk being stuck with iot worldline terminal. It allows to succesfully interpret when the terminal is disconnected and adapts the error messages to the information received fromthe terminal instead of the current generic "An error has occurred" enterprise: https://github.com/odoo/enterprise/pull/107709 task-5946033 Forward-Port-Of: odoo/odoo#267541 Forward-Port-Of: odoo/odoo#249101
This update resolves an issue where the Balance Sheet report incorrectly displayed zero amounts when using multiple companies and lacking default journal groups. The fix ensures the 'Ledger' group is properly computed, allowing for accurate, company-specific reporting.
Original PR description
[FIX] account_reports: only restore horizontal group from previous_options when it's available The 'Ledger' group will only be available when in multicompany or using different journal groups. It was…
[FIX] account_reports: only restore horizontal group from previous_options when it's available
The 'Ledger' group will only be available when in multicompany or using different journal groups. It was still restored from previous options, even when it shouldn't have been available.
=============================================
[FIX] account_reports: properly compute Ledger group when there's no journal group
To reproduce the issue
1) Populate the db with some data impacting the Balance Sheet
2) Delete all the journal groups that would be created by default
3) Open the Balance Sheet, with multiple companies active.
4) Select the "Ledger" horizontal group
====> The report is displayed horizontally grouped by company, but all amounts are 0.
This happens because, when no journal group exists, the "Ledger" horizontal group creates a column group per company, applying a domain doing ('journal_id', 'in', []), so nothing matches. This is caused by the fact that, in this case, options['journals'] will require to match all journals, and will hence be an empty list. We fix it by properly searching for all journals to build the horizontal group's domain when options['journals'] is empty.This update fixes an issue where adding the base unit price to product labels caused layout problems and data loss. The changes adjust the label templates to ensure all product information, including barcodes and references, are consistently displayed, improving the clarity and accuracy of product labels.
Original PR description
Commit 5407449491e91 adds the base_unit_price on the product labels. This addition messed up a bit the existing labels layout. And loosing some data, like the barcode text, some part of the product reference, ... This commit adjust the template to: 1.remove the base_unit_price from the 4x12 layout as there is too few room to put it 2. make the base_unit_price less important by cropping it in case there are not enough room for the price and the barcode. 3.swap the price and the extra html in the 2x7 to make sure the price is printed completely all the time Task: 5213917 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 update streamlines spreadsheet document management by disabling versioning for spreadsheets and frozen spreadsheets. This reduces unnecessary data storage and improves performance when spreadsheets are created, copied, or edited, aligning with best practices for efficient data handling.
Original PR description
This PR consists of two commits. The first commit hides the Manage Versions action button for spreadsheet and frozen spreadsheet documents, since versioning is disabled for those records. The second commit is a backport of enterprise commit 0e319d0. It disables document versioning for spreadsheet and frozen spreadsheet documents, as spreadsheets already manage their history through spreadsheet revisions. This avoids creating unnecessary document history attachments when spreadsheet data is written or when a spreadsheet is copied. Task: [6236496](https://www.odoo.com/odoo/project/2328/tasks/6236496) Forward-Port-Of: odoo/enterprise#120013 Forward-Port-Of: odoo/enterprise#118484
This update fixes a potential issue where users could repeatedly click the 'release table' button while an order was being processed, leading to unintended actions. The change now blocks the UI during table unbooking and ensures a proper redirect, improving the user experience and preventing data inconsistencies.
Original PR description
When unbooking a table, the UI was not blocked, allowing the user to potentially spam the button or perform other actions while the order was being deleted. It also lacked a proper redirection. task-id: 5859460 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#246741
This update corrects a bug where products without lot/serial tracking incorrectly displayed expiration warnings. The fix ensures that products tracked by quantity don't trigger the expiration flow, aligning with intended usage. This prevents unnecessary alerts and simplifies product management.
Original PR description
A product can have expiration date (use_expiration_date) enabled after being changed from lot/serial tracking to no tracking (quantity). The issue this causes is that it can open the expiration popup…
A product can have expiration date (use_expiration_date) enabled after being changed from lot/serial tracking to no tracking (quantity). The issue this causes is that it can open the expiration popup since from saas-18.4 there is a line where if `ml.removal_date <= datetime.datetime.now()` the picking is expired. So, if the product previously met these conditions, it will still be able to enter this flow. And since this product doesn't use a lot_id it displays “You are going to deliver the product False, False which is expired or should at least be removed from stock” What should happen: When a product is not tracked, use_expiration_date should be False as expiration dates are intended to be managed through lots or serial numbers. Steps to reproduce 1. Enable Product Expiry. 2. Create a storable product with: - Tracking: By Lots - Use Expiration Date: enabled - Set a value greater than 0 for removal_time 3. Change the product tracking to By Quantity. 4. Create and validate a receipt for the product. Related Tickets: opw-6255673 Forward-Port-Of: odoo/odoo#268965 Forward-Port-Of: odoo/odoo#268135
This update resolves an issue where custom apps built with Odoo Studio were not displaying images alongside activity records. The fix now shows a placeholder icon when a module isn't found, ensuring consistent image representation for all activity types. This improves the user experience and visual clarity of activity records.
Original PR description
When creating an activity in a custom app made with studio, no image is shown, and instead the alt text is shown with a missing image. This fixes the issue by showing a placeholder icon if no module is found for the activity group. opw-6282451 Previous behavior: <img width="1315" height="568" alt="image" src="https://github.com/user-attachments/assets/a2cd6e7e-666f-434d-b849-3029835cc055" /> New behavior: <img width="1315" height="568" alt="image" src="https://github.com/user-attachments/assets/145cf519-5e4a-43f0-a5a1-cf4b4af75cb7" />
This update resolves an issue where unnecessary code was left behind during a recent port of a feature. The l10n_pe_reports module has been cleaned up, ensuring the system operates efficiently and accurately for Peruvian accounting reports. This fix improves the stability and performance of the Odoo Enterprise platform.
Original PR description
During the FW port of https://github.com/odoo/enterprise/pull/117891 We forgot to remove the unnecessary code opw-5978673 Forward-Port-Of: odoo/enterprise#120183
This update fixes an issue where custom product descriptions weren't appearing on manufacturing orders created from Point of Sale (POS) sales. The change ensures that all product descriptions, including those with 'always' attributes, are correctly displayed on manufacturing orders, regardless of their origin (POS or sale module).
Original PR description
**Steps to reproduce:** - Install pos_mrp - Make a BoM for a product - The product must have a custom attribute, of type always - Go to the PoS - Make a sale, with a customer, enable Ship Later - Go…
**Steps to reproduce:** - Install pos_mrp - Make a BoM for a product - The product must have a custom attribute, of type always - Go to the PoS - Make a sale, with a customer, enable Ship Later - Go to the created MO - The Custom Description field is not showing **Why the fix:** This fix was previously done by e53dae2 but it did not account for the other variants and only did the fix for the never attributes. This is because it seemed to work with other kinds of attributes until 19.0 We now also compute the move description if we have a custom attribute. We need the never variants to have a description as well, as it is done in the sale module. This commit basically aligns the behavior to the on done in the sale module. A test had to be changed, as we now write the description in a different way, to make it the same regardless of where the picking and moves were created from. We now won't see a difference on the MO between one created from the POS and one created through the sale module. opw-6169257 Forward-Port-Of: odoo/odoo#268713 Forward-Port-Of: odoo/odoo#263350
This update clarifies the 'via' information shown when a user signs a document on behalf of another. Previously, the display was inconsistent, but now it accurately reflects whether a user signed as themselves or on behalf of someone else, ensuring clearer record-keeping.
Original PR description
Before this commit, the signer status always displayed "On <date> via <sender>". Now the message only mentions "via <user>" when the document was actually signed by a different user (for example, when an admin is logged in and signs through a signer's link). When the signer uses their own link, only the date is shown. task-6216243 Forward-Port-Of: odoo/enterprise#117460
This change prevents excessively large PDF reports generated from the general ledger by limiting the length of invoice reference strings. Previously, long invoice references caused wkhtmltopdf to consume excessive system resources, leading to report failures. The fix limits the reference length to 200 characters, ensuring report stability and performance.
Original PR description
The display name of the account.report.line in the general ledger report has the format of: INVOICE NAME (invoice refs) In the case where a client has hundreds of sales orders batched to a single…
The display name of the account.report.line in the general ledger report has the format of: INVOICE NAME (invoice refs) In the case where a client has hundreds of sales orders batched to a single invoice, the ref can become extremely long, e.g.: INV/2026/00001 (S12123, S12152, S12159, S12140, S12165, S12161, S12162, S12110, S12099, S12124, S12145, S12128, S12114, S12131, S12097, S12185, S12154, S12133, S12190, S12118, S12116, S12102, S12155, S12153, S12158, S12150, S12100, S12142, S12121, S12122, S12111, S12187, S12172, S12177, S12095, S12117, S12144, S12137, S12092, S12138, S12186, S12182, S12112, S12148, S12183, S12101, S12178, S12119, S12169, S12115, S12146, S12093, S12126, S12160, S12163, S12129, S12098, S12151, S12096, S12174, S12120, S12130, S12147, S12180, S12191, S12164, S12141, S12105, S12136, S12139, S12109, S12106, S12104, S12103, S12175, S12179, S12188, S12113, S12173, S12167, S12171, S12134, S12094, S12184, S12166, S12170, S12125, S12135, S12143, S12176, S12189, S12156, S12181, S12107, S12157, S12132, S12149, S12127, S12108, S12168...) Because the length of the account.report.line is unchecked in account_general_ledger.py label builder, the pdf can clog to one or two account.report.lines per page, skyrocketing the pdf page length. As wkhtmltopdf processes the report from html to pdf it makes a system call openat() to the /tmp/report.footer.tmp.x.html file for EACH page of the pdf. You can see the TODO comment in the spoolTo function in wkhtmltopdf (both in Odoo and the original repo) saying that the header and footer need to be freed, on each page processing, not just null pointed. https://github.com/odoo/wkhtmltopdf/blob/2c884bd1545b8a639847de22f24754ee5a6fc44c/src/lib/pdfconverter.cc#L794 I verified that that the number of openat calls to the /tmp/report.footer.tmp.x.html file equals the exact number of pages in the pdf to be generated if the report HAD generated successfully by setting the footer input into _run_wkhtmltopdf to None, generating the report without footers, then separately running an strace on wkhtmltopdf when the report fails to generate. See related ticket linked at bottom. The linux machine used on sh instances has a ulimit -n of 1024 file descriptors. Because the footer file descriptors accumulate, once a pdf has about 1010+ pages (~a dozen fd's are allocated for other purposes), over 1024 file descriptors are opened and the system fails with: Wkhtmltopdf failed (error code: -6). Message: QEventDispatcherUNIXPrivate(): Unable to create thread pipe: Too many open files QEventDispatcherUNIXPrivate(): Can not continue without a thread pipe Since wkhtmltopdf is archived and Odoo has a replacement in development, I suggest that we limit the display_name of the account.report.line to 200 to keep the bloat minimized, preventing one account.report.line's name from taking up an entire page of the general ledger pdf. This allows many more batched invoices to be shown in the report and a much greater time range of data to be printed without hitting the fd limit. I suggest changing it at the general ledger report level rather than in the account.move.line _compute_display_name function, as we probably still want to see the full display_names at the invoice level. On runbot, the machine has different memory constraints than on sh / local, so it hits the following error before the one above: Wkhtmltopdf failed (error code: -11). Memory limit too low or maximum file number of subprocess reached. Message : Steps to Reproduce on 19.0 newdb: 1. newdb -n test_gl -v 19.0 2. ensure ulimit is set to 1024 in shell that runs odoo instance by running ulimit -n 1024 to mimic ulimit of sh environment 3. run db with python3 odoo-bin, ensuring high enough memory constraints to simulate multi worker sh instance, i.e. --limit-memory-soft=12884901888 --limit-memory-hard=1288490188 4. install sales, accounting, stock 5. install demo data 6. create invoices with 100+ associated sales orders 7. generate the pdf 8. Increase the amount of invoices till the general ledger page count hits ~1010+, where you will hit the error. Notes: opw-ticket-6201508 closes #118067 Forward-Port-Of: odoo/enterprise#120091 Forward-Port-Of: odoo/enterprise#118067
This update fixes an issue where Sales Order names weren't accurately reflecting the quotation date's time information when using date-based sequence prefixes. The fix ensures that the time component is correctly included in the generated sequence numbers, resolving a discrepancy in the order naming.
Original PR description
## Issue When using a prefix containing a time-based placeholder (`%(h24)s`, `%(h12)s`, `%(min)s`, `%(sec)s`) with *Subsequences per date\_range*, the time information are missing and consistently…
## Issue
When using a prefix containing a time-based placeholder (`%(h24)s`, `%(h12)s`, `%(min)s`, `%(sec)s`) with *Subsequences per date\_range*, the time information are missing and consistently set to 0 when interpolating the prefix.
## Steps to reproduce
1. Install *Sales* (`sale_management`)
2. In Settings > Technical > Sequences, update the `sale.order` sequence:
- Prefix: `S/%(y)s/%(month)s/`
- Suffix: `/%(h24)s/%(min)s/%(sec)s`
- Tick the *Use subsequences per date_range* checkbox and set a range for the current month
3. Create and confirm a SO
4. **The name of the SO correctly contains the Quotation date in the prefix, but the suffix is set to /00/00/00, even though the quotation date contains time information.**
## Cause
Commit https://github.com/odoo/odoo/commit/f7c330d83cc3 sets the `ir_sequence_date` to a `datetime.date` object in `IrSequence._next`. This leads to the time information missing from the interpolation dict:
https://github.com/odoo/odoo/blob/d58f4ed332af35f6de26a93f07adf05368731e20/odoo/addons/base/models/ir_sequence.py#L211-L214
## Fix
The context key `ir_sequence_date` should be set to a `datetime.datetime` object to correctly interpolate the time information in the prefix/suffix of a sequence. To do so, the `tzinfo` needs to be drop for the date to be interpretable by the `fields.Datetime.from_string` method:
https://github.com/odoo/odoo/blob/d58f4ed332af35f6de26a93f07adf05368731e20/odoo/orm/fields_temporal.py#L239-L244
The time is not cast to a specific timezone (e.g., UTC) before dropping the tzinfo, as doing so would lead to incoherent time information from the user's perspective. For example, creating a SO at 13:00 in Brussels (UTC+2) would result in `11` being used as the hour to interpolate the `%(h24)s` placeholder.
opw-6104485
Forward-Port-Of: odoo/odoo#2607827 changes
Resolved issues and error corrections
This update resolves an issue preventing authenticated users from submitting the donation page on databases with Cloudflare Turnstile enabled. The fix skips Turnstile attachment when a submit button isn't present, ensuring the donation process works correctly. This improves the user experience for donations.
Original PR description
Steps to reproduce: =================== 1. Configure a Cloudflare Turnstile site key on a 19.2 database. 2. Open `/donation/pay`. => Traceback. Cause: ====== On `/donation/pay` (and any page…
Steps to reproduce: =================== 1. Configure a Cloudflare Turnstile site key on a 19.2 database. 2. Open `/donation/pay`. => Traceback. Cause: ====== On `/donation/pay` (and any page embedding the donation snippet), the page crashes with `TypeError: Cannot read properties of null (reading 'classList')` in `TurnStile.disableSubmit`, breaking the form for authenticated visitors on databases with a Turnstile site key configured. The donation page wraps its editor-only custom-fields form in a `<section class="s_website_form">` (introduced by [1]) That inner form has no submit button of its own the actual donation submit happens in the surrounding `payment.form`. The `Form` interaction's selector (`.s_website_form form, form.s_website_form`) nevertheless matches it, so the cf_turnstile patch on `Form.start` runs, queries `.s_website_form_send` / `.o_website_form_send`, gets `null`, and crashes when reading `submitButton.classList`. Solution: ========== On master, we fixed this by adding `s_website_form_no_recaptcha`` to the donation section. For stable versions, since the view is noupdate, we used a JS workaround: if there is no submit button, simply skip attaching Turnstile. [1]: https://github.com/odoo/odoo/commit/dc0618014deace4757f35ee432629a2aa7ebe998 opw-6208466 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves an issue where the website rental planning module would crash when the quantity input field was removed from the product page. The change was due to a shift in how the system handles data evaluation, and this fix ensures the system gracefully handles the absence of the quantity field, preventing errors and maintaining functionality.
Original PR description
Steps to reproduce: 1. Install website_sale_renting_planning 2. In rental module, create a product that is of type service and can be sold 3. Go to the website and remove the quantity selector input…
Steps to reproduce: 1. Install website_sale_renting_planning 2. In rental module, create a product that is of type service and can be sold 3. Go to the website and remove the quantity selector input field from the page and save. Issue: `TypeError: Cannot read properties of null (reading 'dataset')` Why this happens: Following architectural changes in v19.1, the rental data evaluation logic was moved directly into the DaterangePicker component lifecycle. Commit 4e5f71d introduces a new method to where, during initialization (`willStart`), the component triggers `setAddQtyInputMax()` to update the dataset attributes of the quantity selector input box. If the quantity selector has been removed via the website customizer `querySelector` returns `null`, causing the assignment to crash. In v19.0, this logic lived in the `WebsiteSale` interaction, executing only during post-render UI event listener triggers which kept it safe. opw-6268945 Forward-Port-Of: odoo/enterprise#119574
This update resolves a visual glitch in the chatter interface where an empty rectangle appeared next to log notes during editing. The issue stemmed from a system that remembered the last position, causing it to stick to the left even when space was available. This change removes the memorization, ensuring suggestions are displayed correctly regardless of scrolling.
Original PR description
# How to reproduce - Go into any form view of a model with a chatter (e.g. Quotation) - Add multiple long log notes. You need to be able to scroll enough to not see the last log note - Click edit on…
# How to reproduce - Go into any form view of a model with a chatter (e.g. Quotation) - Add multiple long log notes. You need to be able to scroll enough to not see the last log note - Click edit on the last log note - Scroll down to the bottom # The problem An empty rectangle is displayed next to the log note in edit mode. # Cause The rectangle comes from the NavigableList Component, which is the list that displays suggestions when typing things like "@" or "#" : https://github.com/odoo/odoo/blob/1fd44c3bb11a79d5b6aa72bf7de5a83e6c45be46/addons/mail/static/src/core/common/composer.xml#L137 This components uses the `usePostion()` hook, which purpose is to try to find the most appropriate place to put the element. It will try different postions (e.g. on the left, below, above, etc.) and will pick the most appropriate one. It will then adjust the element's style to position it correctly. It is possible to ask for a preferred position using the options given to the hook. This position will be prioritized over the others if it is suitable. In the case of the NavigableList of the chatter, we give it either 'bottom-fit' or the 'top-fit' positions, wich means it will prefer to be displayed above or below the message : https://github.com/odoo/odoo/blob/dd84309df7fd39e9e97ed02d135d25b211085135/addons/mail/static/src/core/common/composer.js#L449-L459 But in our case, when we scroll back up, the position of the rectangle stays on the left, even though the below space is available. That is because of this commit that introduced a memorization of the last solution : https://github.com/odoo/odoo/commit/b2b8d2dbb8396d86492a3089db9b1b1545c8f13b https://github.com/odoo/odoo/blob/f2434aac74324a65ccd81aa18c7b0e8318e59fde/addons/web/static/src/core/position/position_hook.js#L59-L61 This means that when we scroll down, the bottom positions fails and so the left one is defaulted to. Since the position is memorized, it stays on the left. The issue with this left position is that another commit introduced some logic that made it so if the position is not "top" or "bottom", then we set the element's height to some value : https://github.com/odoo/odoo/commit/702748e2c8e895d372d07f9aeff273282d1b1a99 https://github.com/odoo/odoo/blob/f2434aac74324a65ccd81aa18c7b0e8318e59fde/addons/web/static/src/core/position/utils.js#L120-L124 And setting the height of the NavigableList makes it so it displayed even when there are no suggestions inside, because the hiding mechanism of the suggestion list relies on the fact that when there are no suggestions, the div is empty and has no height, so it is hidden. # Propose solution We introduce a settings in the options that will allow to skip the memorization of the last position. Since the left position will never be set in the options, no height will be defined. opw-6172407 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#262822
This update fixes a bug where sequence names weren't correctly displaying the time portion of dates when using date ranges. The fix ensures that sequence names accurately reflect the quotation date's time, resolving a discrepancy in the generated order names. This improves data consistency and accuracy.
Original PR description
## Issue When using a prefix containing a time-based placeholder (`%(h24)s`, `%(h12)s`, `%(min)s`, `%(sec)s`) with *Subsequences per date\_range*, the time information are missing and consistently…
## Issue
When using a prefix containing a time-based placeholder (`%(h24)s`, `%(h12)s`, `%(min)s`, `%(sec)s`) with *Subsequences per date\_range*, the time information are missing and consistently set to 0 when interpolating the prefix.
## Steps to reproduce
1. Install *Sales* (`sale_management`)
2. In Settings > Technical > Sequences, update the `sale.order` sequence:
- Prefix: `S/%(y)s/%(month)s/`
- Suffix: `/%(h24)s/%(min)s/%(sec)s`
- Tick the *Use subsequences per date_range* checkbox and set a range for the current month
3. Create and confirm a SO
4. **The name of the SO correctly contains the Quotation date in the prefix, but the suffix is set to /00/00/00, even though the quotation date contains time information.**
## Cause
Commit https://github.com/odoo/odoo/commit/f7c330d83cc3 sets the `ir_sequence_date` to a `datetime.date` object in `IrSequence._next`. This leads to the time information missing from the interpolation dict:
https://github.com/odoo/odoo/blob/d58f4ed332af35f6de26a93f07adf05368731e20/odoo/addons/base/models/ir_sequence.py#L211-L214
## Fix
The context key `ir_sequence_date` should be set to a `datetime.datetime` object to correctly interpolate the time information in the prefix/suffix of a sequence. To do so, the `tzinfo` needs to be drop for the date to be interpretable by the `fields.Datetime.from_string` method:
https://github.com/odoo/odoo/blob/d58f4ed332af35f6de26a93f07adf05368731e20/odoo/orm/fields_temporal.py#L239-L244
The time is not cast to a specific timezone (e.g., UTC) before dropping the tzinfo, as doing so would lead to incoherent time information from the user's perspective. For example, creating a SO at 13:00 in Brussels (UTC+2) would result in `11` being used as the hour to interpolate the `%(h24)s` placeholder.
opw-6104485
Forward-Port-Of: odoo/odoo#260782This update ensures that delivery orders created during multi-step manufacturing processes correctly reserve newly produced lots when the 'Store Finished Products' transfer uses a sublocation within the warehouse. Previously, the system incorrectly defaulted to using existing stock, leading to inaccurate inventory tracking. This fix corrects a logic error that prevented the MTO link from being maintained.
Original PR description
Steps to reproduce: - Create a storable product “P1” with Lot tracking - Enable routes: MTO + Manufacture - Create a BoM for the product: - Component: C1 - Configure the warehouse with 3-step…
Steps to reproduce:
- Create a storable product “P1” with Lot tracking
- Enable routes: MTO + Manufacture
- Create a BoM for the product:
- Component: C1
- Configure the warehouse with 3-step manufacturing
- Have on-hand stock in WH/Stock with Lot 001
- Confirm a Sales Order for the product
- Confirm the generated Manufacturing Order and produce Lot 002
- In the "Store Finished Products" transfer, change the destination location from WH/Stock to WH/Stock/Shelf 1 and validate
- Check the Delivery Order reservation
Problem:
The move is reserved with Lot 001 instead of 002
When using a 3-step manufacturing flow (MTO + Manufacture), if the user manually changes the destination of the "Store Finished Products" transfer to a sublocation of WH/Stock (e.g. WH/Stock/Shelf 1), the MTO link between the production and the delivery order was incorrectly broken, causing the delivery to reserve existing stock instead of the freshly produced lot.
Root cause: `_skip_push()` only skipped push logic when the downstream move's source was a child-or-equal of the current move's destination (`m.location_id._child_of(self.location_dest_id)`). When the destination was changed to a sublocation (WH/Stock/Shelf 1), this check failed, so `_push_apply()` ran, found the delivery's source (WH/Stock) was not a child of WH/Stock/Shelf 1, and called `_break_mto_link()`, clearing `move_orig_ids` on the delivery move. The delivery then fell back to make-to-stock reservation and picked an unrelated lot.
opw-6197212
Forward-Port-Of: odoo/odoo#268783This update resolves a bug where saving multiple forms could trigger errors due to a timing issue with cached data. Now, the system gracefully handles changes to record IDs, preventing crashes and ensuring data consistency when creating or editing forms. This improves the stability and reliability of the application.
Original PR description
* Open a new record form (the `onchange` RPC is cached). * Open a second new record form (it uses the cached `onchange` RPC). * Save the record before the `onchange` RPC returns. Before this commit, a race condition caused an error to be raised. When `web_save` is executed, it updates the record configuration with the new `resId` without reloading the view. When the pending `onchange` RPC finally returns, the cache callback misinterprets the data as a `web_read` result instead of an `onchange` result due to the updated ID, triggering a crash. Now, the callback safely does nothing if the resId has changed since the request was sent. runbot-243200 Forward-Port-Of: odoo/odoo#269415 Forward-Port-Of: odoo/odoo#268884
This update resolves an issue where scanning a package type alongside a regular package didn't correctly link the new package to the product, leading to missing product associations. The fix ensures that when a package type is scanned, the new package is properly linked to the relevant products and displayed within the barcode interface.
Original PR description
When scanning a package then a package type, from the point of view of the user nothing happend, and in the backend it will created a new package but it will not link it to the products nor will it…
When scanning a package then a package type, from the point of view of the user nothing happend, and in the backend it will created a new package but it will not link it to the products nor will it show any warning. Steps to reproduce: ------------------- * Install barcode and stock * Enable packages in settings * Open Inventory * Create a product, * Create a Package Type -> barcode PACKTYPE, * Create a Package linked to this package type -> PACK, * Add at least 2 unit of product to this package, * Create a delivery for 2 unit of the product, Open Barcode * Operation > Delivery orders > your delivery * Erase the destination package from the first line * Scan PACK ( don't click on the green line) * Scan PACKTYPE **Actual behavior** create a new package but does not link it to the new products **Expected behavior** create a new package and set it as destination package. Observation: ------------- When scanning the package (PACK), we will go through ```_processPackage``` -> ```async _processPackage``` where in the end the line is unselected: https://github.com/odoo/enterprise/blob/39d8a473fe03038ca0494a6a8165e3eb75bd8492/stock_barcode/static/src/models/barcode_picking_model.js#L2090 When we scan our package type (PACKTYPE), we will go to ``` _processPackage``` -> ```_processPackage```->```_processPackageType``` where we will obtains packagesIds checking that we have a source package: https://github.com/odoo/enterprise/blob/7cd9834d1d918f12dec43844cae6f112309e5772/stock_barcode/static/src/models/barcode_picking_model.js#L2123-L2132 and will send us to ```_putPackInPack```: https://github.com/odoo/enterprise/blob/7cd9834d1d918f12dec43844cae6f112309e5772/stock_barcode/static/src/models/barcode_picking_model.js#L2133-L2136 Where we will avoid the empty packageIds since we checked on the source package and not the destination package: https://github.com/odoo/enterprise/blob/2b887d094c66be7aebd92fbf735b1852f5dde4b5/stock_barcode/static/src/models/barcode_picking_model.js#L2296-L2299 and will call ```action_put_in_pack``` from the packaging model: https://github.com/odoo/enterprise/blob/2b887d094c66be7aebd92fbf735b1852f5dde4b5/stock_barcode/static/src/models/barcode_picking_model.js#L2301-L2306 In ```action_put_in_pack``` will create a new packaging and put it as a the new destination package, but since the ```previous_dest_package``` (saved in db) was itself, he will [erase the link](https://github.com/odoo/odoo/blob/cda011dc8590773f6c3a26f4ae9d5242a3147024/addons/stock/models/stock_package.py#L354-L363) he just made. Which means that in our case, we created a package without linking it to anything. Even if we avoid the function to erase the destination package, since the destination package shown in barcode is the one from move line : https://github.com/odoo/enterprise/blob/d0d0a3cf4a02bf24cf502b533e494fe7ca155eb3/stock_barcode/static/src/components/line.js#L115-L117 It will not show the new package in barcode opw-5449729 Forward-Port-Of: odoo/enterprise#104876
10 changes
Enhancements to existing features
This update ensures Odoo complies with Serbian accounting regulations by automatically fetching the official middle exchange rate from the National Bank of Serbia. This improves the accuracy of financial reporting and transactions for Serbian users.
Original PR description
[IMP] currency_rate_live: Fetch exchange rates National Bank Serbia To ensure compliance with the Serbian Law on accounting, fetch official middle exchange rate from the National Bank of Serbia task-6159555
Resolved issues and error corrections
This update resolves an issue where purchase order confirmations would fail when a delivery type didn't associate with a warehouse. The fix ensures that the system correctly identifies the default destination location when a warehouse isn't specified, preventing a type error and allowing purchase orders to be processed smoothly.
Original PR description
Bug introduced in: https://github.com/odoo/odoo/commit/e2efdf75f67e631ed7622bb01c127120e639f6c5 Steps to reproduce: Clear the Warehouse field (set it to False) Create a purchase order Set "Deliver…
Bug introduced in: https://github.com/odoo/odoo/commit/e2efdf75f67e631ed7622bb01c127120e639f6c5
Steps to reproduce: Clear the Warehouse field (set it to False) Create a
purchase order Set "Deliver To" to the operation type with no warehouse
Add any product Confirm the PO → TypeError is raised
Steps to reproduce the bug:
- Have at least 2 warehouses
- Go to Inventory > Configuration > Operation Types > Receipts
- Clear the Warehouse field (set it to False)
- Create a purchase order:
- Set "Deliver To" to the operation type with no warehouse
- Add any product
- Try to confirm the PO
Problem:
A traceback is triggered:
``` return self.parent_path.startswith(other_location.parent_path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: startswith first arg must be str or a tuple of str, not bool
```
`_get_final_location_record` computes `wh_stock_loc` from
`picking_type_id.warehouse_id.lot_stock_id`. When `warehouse_id`
is False (a valid configuration, operation types can be detached from
any warehouse), `lot_stock_id` short-circuits to False
Solution:
guard the _child_of call with not wh_stock_loc. When the
picking type has no warehouse, wh_stock_loc is falsy and there is
nothing to compare against, so the method falls back to
default_location_dest_id (the only destination available).
opw-6253817
Forward-Port-Of: odoo/odoo#268317This update optimizes how the system checks access rights when opening the reconciliation widget, particularly for large amounts of transactions. Previously, the process was slow due to individual checks being performed, leading to delays. This change improves the speed and responsiveness of the reconciliation feature.
Original PR description
When assigning a value in batch, the ORM doesn't manage to batch the call to `check_access` done in `write_batch`/`write_real` because each write is done individually when setting a value in the compute function. This field is especially annoying because it is read when opening the reconciliation widget on several lines. Forward-Port-Of: odoo/odoo#269063
This update corrects an issue where sequence names generated with time placeholders (like hour and minute) were consistently displaying as '00:00:00'. The change ensures that the time component of the sequence date is correctly included, resolving a discrepancy in generated order names. This improves data accuracy and consistency.
Original PR description
## Issue When using a prefix containing a time-based placeholder (`%(h24)s`, `%(h12)s`, `%(min)s`, `%(sec)s`) with *Subsequences per date\_range*, the time information are missing and consistently…
## Issue
When using a prefix containing a time-based placeholder (`%(h24)s`, `%(h12)s`, `%(min)s`, `%(sec)s`) with *Subsequences per date\_range*, the time information are missing and consistently set to 0 when interpolating the prefix.
## Steps to reproduce
1. Install *Sales* (`sale_management`)
2. In Settings > Technical > Sequences, update the `sale.order` sequence:
- Prefix: `S/%(y)s/%(month)s/`
- Suffix: `/%(h24)s/%(min)s/%(sec)s`
- Tick the *Use subsequences per date_range* checkbox and set a range for the current month
3. Create and confirm a SO
4. **The name of the SO correctly contains the Quotation date in the prefix, but the suffix is set to /00/00/00, even though the quotation date contains time information.**
## Cause
Commit https://github.com/odoo/odoo/commit/f7c330d83cc3 sets the `ir_sequence_date` to a `datetime.date` object in `IrSequence._next`. This leads to the time information missing from the interpolation dict:
https://github.com/odoo/odoo/blob/d58f4ed332af35f6de26a93f07adf05368731e20/odoo/addons/base/models/ir_sequence.py#L211-L214
## Fix
The context key `ir_sequence_date` should be set to a `datetime.datetime` object to correctly interpolate the time information in the prefix/suffix of a sequence. To do so, the `tzinfo` needs to be drop for the date to be interpretable by the `fields.Datetime.from_string` method:
https://github.com/odoo/odoo/blob/d58f4ed332af35f6de26a93f07adf05368731e20/odoo/orm/fields_temporal.py#L239-L244
The time is not cast to a specific timezone (e.g., UTC) before dropping the tzinfo, as doing so would lead to incoherent time information from the user's perspective. For example, creating a SO at 13:00 in Brussels (UTC+2) would result in `11` being used as the hour to interpolate the `%(h24)s` placeholder.
opw-6104485
Forward-Port-Of: odoo/odoo#260782A recent update inadvertently removed the duplicate and delete buttons from the page properties dialog in the website settings. This change was caused by a renaming of a configuration property. This update restores the functionality, ensuring users can properly manage their static website pages.
Original PR description
Steps to reproduce: 1. Go to Website. 3. Open the page properties dialog of any static page. Issue: The duplicate and delete page buttons are missing from the page properties dialog, although they were available until version 19.0. Cause: After the changes introduced in [1](https://github.com/odoo/odoo/pull/220325/changes), the `buttonTemplate` prop was renamed to `buttonDialogTemplate`. However, this new prop was not handled in the page properties dialog, causing the buttons to disappear. task-6171493
This update resolves an issue where users couldn't properly set prices for hybrid subscription products. Now, the system requires a plan to be selected for subscription products and correctly filters pricelist items to allow one-time sales when a plan is chosen. This ensures accurate and flexible pricing for all subscription types.
Original PR description
Before this commit:
1. Users could save a pricelist rule for a pure subscription product without assigning a plan.
2. Hybrid subscription products (where 'Allow One-Time Sale' is True) were filtered out of the pricelist item form when no plan was selected, preventing users from setting a one-time price.
After this commit:
- The `plan_id` field on the product template form is now mandatory if the product is a subscription and does not allow one-time sales.
- The `product_tmpl_id` domain on the pricelist item form is updated to `['|', ('recurring_invoice', '=', bool(plan_id)), ('allow_one_time_sale', '=', True)]`, allowing users to select hybrid products for one-time pricing.
task: 6164232This update corrects a bug where the Timesheet Assistant was incorrectly matching tasks and projects with disabled timesheets. The fix ensures the assistant only considers active timesheets, improving the accuracy of time tracking and reporting. This prevents wasted effort and ensures data integrity.
Original PR description
Currently, the Timesheet Assistant (ActivityWatch) can match events to projects or tasks that have timesheets disabled, either via Custom Rules or Historical Memory.
This commit resolves the issue across the entire pipeline:
- Backend: Updated `resolve_assistant_models_targets` to efficiently filter out records where `allow_timesheets` is False using a search domain.
- Frontend: Updated the `loadData` JS pipeline to intercept and wipe any project/task IDs rejected by the backend, ensuring they cleanly fall back into a single "Unmatched" group.
- Views: Added the `[('allow_timesheets', '=', True)]` domain to `project_id` and `task_id` fields in `aw.rule` views to prevent users from creating invalid rules.
Task: 6267401This update resolves an issue where the EC List XML reports generated for Belgium (l10n_be) incorrectly treated invoices with the same VAT number as separate entities. This resulted in rejection by the tax agency. The fix ensures that invoices with identical VATs are grouped together in the XML export, meeting tax agency requirements.
Original PR description
With l10n_be: - Create two contacts with the same VAT - Create an invoice for each that is EC List compatible - Generate the return and export the EC List XML In the generated xml the two partners with the same vat are treated as different partners, which causes a rejection by the tax agency. opw-6109585 Forward-Port-Of: odoo/enterprise#117702
This update corrects an assertion error related to product naming within the intercompany sales and purchase rules. The issue stemmed from a recent addition of product attributes, which caused inconsistencies in product names across different Odoo apps. This fix ensures consistent product naming during intercompany transactions.
Original PR description
**Step to reproduce** Reproducible in single app The "name" field make this assertion fails: ``` self.assertRecordValues(sale_order.order_line[0], [{ "product_id":…
**Step to reproduce**
Reproducible in single app
The "name" field make this assertion fails:
```
self.assertRecordValues(sale_order.order_line[0], [{
"product_id": no_variant_product_tmpl.product_variant_id.id,
"name": 'No Variant\nAttribute: Value 1',
```
**Observation**
The name will not be the same depending which app are installed, purchase_product_matrix, changes the name of the product if there is a attribute value of a never variant: https://github.com/odoo/odoo/blob/f399f99d4e0e562d25e1de32336e8d6a55199b9b/addons/purchase_product_matrix/models/purchase.py#L168-L174 Which will be passed to the purchase_order_line:
https://github.com/odoo/odoo/blob/f399f99d4e0e562d25e1de32336e8d6a55199b9b/addons/purchase/models/purchase_order_line.py#L630-L634 that will pass the information to the sale order:
https://github.com/odoo/enterprise/blob/bce04ce24b66fb1a2481274eb3aebdc30a62766e/sale_purchase_inter_company_rules/models/purchase_order.py#L114 https://github.com/odoo/enterprise/blob/bce04ce24b66fb1a2481274eb3aebdc30a62766e/sale_purchase_inter_company_rules/models/purchase_order.py#L125-L126
**Additional information**
Since this [commit](https://github.com/odoo/odoo/commit/b8ebb26553f8170061debc7532606fd4777f0fcd#diff-5684edced9bdfc98021a85de4c6cdf691ea7add74e56ab50334a1d7db9ef4224R90) product_no_variant_attribute_value_ids was directly added in the purchase module.
breaking commit : https://github.com/odoo/enterprise/commit/bf286a0005b8e22ffa717419cd2dfacff861a265
runbot-242362
Forward-Port-Of: odoo/odoo#268016This update resolves an issue where extraneous code was carried over during a recent update to the Odoo Enterprise platform. The fix ensures the reporting functionality for Peru (l10n_pe_reports) operates efficiently and without unnecessary overhead. This improves the overall stability and performance of the system.
Original PR description
During the FW port of https://github.com/odoo/enterprise/pull/117891 We forgot to remove the unnecessary code opw-5978673 Forward-Port-Of: odoo/enterprise#120183
3 changes
Resolved issues and error corrections
This update fixes an issue where the 'Due' button wasn't appearing on customer forms when balances existed only at the line level of journal entries. The fix ensures all customers with outstanding balances, regardless of how they're linked to journal entries, now have the 'Due' button visible, improving user experience and reporting accuracy.
Original PR description
Steps to Reproduce: 1. Install Accounting module (without Point of Sale). 2. Create a customer. 3. Create a journal entry with that customer set only at line level. 4. Post the journal entry. 5. Open…
Steps to Reproduce: 1. Install Accounting module (without Point of Sale). 2. Create a customer. 3. Create a journal entry with that customer set only at line level. 4. Post the journal entry. 5. Open the customer form. Issue: The Due smart button is not visible on the partner form even though an outstanding balance exists for the customer. Note: This issue does not reproduce when Point of Sale is installed, as the POS module overrides `_compute_has_moves` with its own implementation that checks the outstanding balance directly. Root Cause: The `_compute_has_moves` method queries only `account.move `for partner matching. When a partner is referenced only at the account.move.line level, the partner is never picked up by this query, resulting in `has_moves = False` and the Due button remaining hidden. Fix: Replaced the EXISTS-based implementation with a UNION-based approach as the EXISTS implementation evaluated the query per partner row, whereas UNION processes all partners in a single batch query. Additionally extended the UNION to also include account.move.line partner matching, ensuring partners referenced only at the line level, are correctly detected and has_moves is set to True. Result: The Due smart button is now correctly visible for all partners with an outstanding balance, regardless of whether the partner is set at the journal entry level or only at the line level. owp = 6243562 Forward-Port-Of: odoo/enterprise#119084
This update resolves an error that occurred when creating payment reports for Swiss companies. The issue was triggered when the required module ('hr_payroll_account_iso20022') wasn't installed. Now, the system correctly handles the report generation process, ensuring Swiss companies can generate their payment reports without errors.
Original PR description
*=l10n_ch_hr_payroll,hr_payroll_account_iso20022 When clicking the create payment report button on a payslip for a Swiss company, a traceback occurs if the ``hr_payroll_account_iso20022`` module is…
*=l10n_ch_hr_payroll,hr_payroll_account_iso20022 When clicking the create payment report button on a payslip for a Swiss company, a traceback occurs if the ``hr_payroll_account_iso20022`` module is not installed. Steps to reproduce the error: - Install ``l10n_ch_hr_payroll`` module - Switch to CH Company - Create an Employee and running contract for it - Go to Payroll > Payslip > All payslips > Create a new payslip > Set the employee > Confirm > Create payment report Traceback: ```py ValueError: Wrong value for hr.payroll.payment.report.wizard.export_format: 'iso20022_ch' ``` https://github.com/odoo/enterprise/blob/7792926504a823590fbbe574a96994002a92fc17/l10n_ch_hr_payroll/models/hr_payslip.py#L383 https://github.com/odoo/enterprise/blob/7792926504a823590fbbe574a96994002a92fc17/l10n_ch_hr_payroll/models/hr_payslip_run.py#L13 Here, ``iso20022_ch`` is passed as ``export_format``, However, ``iso20022_ch`` is added to the selection field in the ``hr_payroll_account_iso20022`` module at [1]. When that module is not installed, the selection value does not exist, leading to the above error. [1]: https://github.com/odoo/enterprise/blob/7792926504a823590fbbe574a96994002a92fc17/hr_payroll_account_iso20022/wizard/hr_payroll_payment_report_wizard.py#L11 sentry-7391832811 Forward-Port-Of: odoo/enterprise#119666 Forward-Port-Of: odoo/enterprise#113277
This update resolves a requirement from Luxembourg auditors regarding the classification of partners in our SAFT reports. Specifically, it ensures that less than 30% of transactions with payable or receivable accounts have missing supplier or customer IDs. The change adds partners to the appropriate lists based on transaction types and maintains compatibility with older report formats.
Original PR description
This PR is one of many triggered by responses from Luxembourg auditors. See PR #113316 for a full list of these PRs. As described in PR #117799, the \CustomerID and \SupplierID elements on…
This PR is one of many triggered by responses from Luxembourg auditors. See PR #113316 for a full list of these PRs. As described in PR #117799, the \CustomerID and \SupplierID elements on \Transaction\Line elements is determined by a partner's `customer_rank` and `supplier_rank`. This is a binary designation, one or the other. The Luxembourg FAIA report requires that less than 30% of \Transaction\Line elements with payable accounts (class 6) can not have \SupplierID. The same applies for \Transaction\Line elements with receivable accounts (class 7) and the \CustomerID element. TSB clarified that any partner on an receivable or payable line should be added to the Customer list or Supplier list respectively https://github.com/odoo/enterprise/pull/100749#issuecomment-3655127511. In addition, I verified that Luxembourg's analysis of four separate FAIA files (from ticket 5427296) aligns with this expectation. <img width="1322" height="690" alt="image" src="https://github.com/user-attachments/assets/1a82f99e-5b32-4dbb-96e1-1b25bab2629b" /> This commit adds partners to the \Supplier and \Customer lists if they have any payable or receivable lines, respectively. It also picks between the \CustomerID and \SupplierID based on a line's `account_type`. This logic is applied to `account_saft` and updates the other, country-specific SAFT reports where appropriate. It also retains the previous `customer_rank` and `supplier_rank` logic as a fallback for older XML reports and for accounts other than `asset_receivable` or `liability_payable`. opw-6118024 Forward-Port-Of: odoo/enterprise#119098 Forward-Port-Of: odoo/enterprise#118714
6 changes
Enhancements to existing features
This update introduces a new 'PINT' layer within the account_edi_ubl_cii module, streamlining the processing of UBL invoices. This layer aligns with European regulations (CEN_EN16931 and PINT-EU) for enhanced compliance and data exchange, particularly for PEPPOL transactions. It improves the handling of invoice data formats.
Original PR description
Add the layer PINT between UBL and BIS3. task: 5890887 Forward-Port-Of: odoo/odoo#260058
Resolved issues and error corrections
This update resolves an issue where purchase order confirmations would fail when a delivery type didn't associate with a warehouse. The fix ensures that the system correctly identifies the final destination location even when a warehouse isn't specified, preventing a type error. This improves the reliability of purchase order processing.
Original PR description
Bug introduced in: https://github.com/odoo/odoo/commit/e2efdf75f67e631ed7622bb01c127120e639f6c5 Steps to reproduce: Clear the Warehouse field (set it to False) Create a purchase order Set "Deliver…
Bug introduced in: https://github.com/odoo/odoo/commit/e2efdf75f67e631ed7622bb01c127120e639f6c5
Steps to reproduce: Clear the Warehouse field (set it to False) Create a
purchase order Set "Deliver To" to the operation type with no warehouse
Add any product Confirm the PO → TypeError is raised
Steps to reproduce the bug:
- Have at least 2 warehouses
- Go to Inventory > Configuration > Operation Types > Receipts
- Clear the Warehouse field (set it to False)
- Create a purchase order:
- Set "Deliver To" to the operation type with no warehouse
- Add any product
- Try to confirm the PO
Problem:
A traceback is triggered:
``` return self.parent_path.startswith(other_location.parent_path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: startswith first arg must be str or a tuple of str, not bool
```
`_get_final_location_record` computes `wh_stock_loc` from
`picking_type_id.warehouse_id.lot_stock_id`. When `warehouse_id`
is False (a valid configuration, operation types can be detached from
any warehouse), `lot_stock_id` short-circuits to False
Solution:
guard the _child_of call with not wh_stock_loc. When the
picking type has no warehouse, wh_stock_loc is falsy and there is
nothing to compare against, so the method falls back to
default_location_dest_id (the only destination available).
opw-6253817
Forward-Port-Of: odoo/odoo#268317This update resolves an issue where negative amounts in Mexican VAT reports weren't consistently including the 'global_discount' field. This fix ensures accurate VAT reporting and compliance with Mexican tax regulations, preventing potential discrepancies and financial errors. The change impacts the l10n_mx_edi module.
This update resolves a requirement from Luxembourg auditors regarding the classification of partners in our SAFT reports. Specifically, it ensures that less than 30% of transactions with payable or receivable accounts have missing supplier or customer IDs. The changes add partners to the relevant lists and prioritize the correct ID based on transaction type, maintaining compatibility with older reports.
Original PR description
This PR is one of many triggered by responses from Luxembourg auditors. See PR #113316 for a full list of these PRs. As described in PR #117799, the \CustomerID and \SupplierID elements on…
This PR is one of many triggered by responses from Luxembourg auditors. See PR #113316 for a full list of these PRs. As described in PR #117799, the \CustomerID and \SupplierID elements on \Transaction\Line elements is determined by a partner's `customer_rank` and `supplier_rank`. This is a binary designation, one or the other. The Luxembourg FAIA report requires that less than 30% of \Transaction\Line elements with payable accounts (class 6) can not have \SupplierID. The same applies for \Transaction\Line elements with receivable accounts (class 7) and the \CustomerID element. TSB clarified that any partner on an receivable or payable line should be added to the Customer list or Supplier list respectively https://github.com/odoo/enterprise/pull/100749#issuecomment-3655127511. In addition, I verified that Luxembourg's analysis of four separate FAIA files (from ticket 5427296) aligns with this expectation. <img width="1322" height="690" alt="image" src="https://github.com/user-attachments/assets/1a82f99e-5b32-4dbb-96e1-1b25bab2629b" /> This commit adds partners to the \Supplier and \Customer lists if they have any payable or receivable lines, respectively. It also picks between the \CustomerID and \SupplierID based on a line's `account_type`. This logic is applied to `account_saft` and updates the other, country-specific SAFT reports where appropriate. It also retains the previous `customer_rank` and `supplier_rank` logic as a fallback for older XML reports and for accounts other than `asset_receivable` or `liability_payable`. opw-6118024 Forward-Port-Of: odoo/enterprise#119098 Forward-Port-Of: odoo/enterprise#118714
This update fixes an issue where users without HR access rights saw a placeholder image instead of their avatar in the timesheet grid view. The fix ensures that all users can see their avatar, improving the user experience and visual clarity of the timesheet reporting.
Original PR description
Steps to reproduce: ------------------- - Install the hr_timesheet module - Create a user without HR access rights - Create a timesheet - Log in with the above user - Open the kanban view Issue: ------- Instead of showing the employee's avatar, a placeholder image is displayed. Reason: ---------- The user does not have access to the hr.employee model. Fix: ----- In this commit, if the user does not have access to hr.employee,we fetch the image from the hr.employee.public model. task: 4461272 Forward-Port-Of: odoo/enterprise#119881 Forward-Port-Of: odoo/enterprise#83574
This update resolves an issue where Odoo's UBL bill import process would fail if the vendor's invoice contained an empty 'EndpointID' field. The fix ensures the import process is more robust and reliable when encountering this common data format, preventing import failures.
Original PR description
**Description:** Importing a UBL file (vendor bill) fails if it contains an empty "EndpointID" node. It assumes the node always contains text content to sanitize, but if it is empty, it crashes with: AttributeError: 'NoneType' object has no attribute 'strip'. **Steps to reproduce:** 1. Import a UBL as a bill, with an empty EndpointID node of the other party. 2. The import fails with the AttributeError. opw-6246515
2 changes
Resolved issues and error corrections
This update resolves a requirement from Luxembourg auditors regarding the classification of partners in our SAFT reports. Specifically, it ensures that less than 30% of transactions with payable or receivable accounts have missing supplier or customer IDs. The changes add partners to the appropriate lists based on transaction type and maintain compatibility with older report formats.
Original PR description
This PR is one of many triggered by responses from Luxembourg auditors. See PR #113316 for a full list of these PRs. As described in PR #117799, the \CustomerID and \SupplierID elements on…
This PR is one of many triggered by responses from Luxembourg auditors. See PR #113316 for a full list of these PRs. As described in PR #117799, the \CustomerID and \SupplierID elements on \Transaction\Line elements is determined by a partner's `customer_rank` and `supplier_rank`. This is a binary designation, one or the other. The Luxembourg FAIA report requires that less than 30% of \Transaction\Line elements with payable accounts (class 6) can not have \SupplierID. The same applies for \Transaction\Line elements with receivable accounts (class 7) and the \CustomerID element. TSB clarified that any partner on an receivable or payable line should be added to the Customer list or Supplier list respectively https://github.com/odoo/enterprise/pull/100749#issuecomment-3655127511. In addition, I verified that Luxembourg's analysis of four separate FAIA files (from ticket 5427296) aligns with this expectation. <img width="1322" height="690" alt="image" src="https://github.com/user-attachments/assets/1a82f99e-5b32-4dbb-96e1-1b25bab2629b" /> This commit adds partners to the \Supplier and \Customer lists if they have any payable or receivable lines, respectively. It also picks between the \CustomerID and \SupplierID based on a line's `account_type`. This logic is applied to `account_saft` and updates the other, country-specific SAFT reports where appropriate. It also retains the previous `customer_rank` and `supplier_rank` logic as a fallback for older XML reports and for accounts other than `asset_receivable` or `liability_payable`. opw-6118024 Forward-Port-Of: odoo/enterprise#119098 Forward-Port-Of: odoo/enterprise#118714
This update prevents a previous error that occurred when multiple projects were edited simultaneously. The fix addresses a technical issue related to how project names were updated, ensuring a smoother experience for users managing multiple projects. This resolves a potential disruption to project workflows.
Original PR description
Currently, an error will occur when user multi edits name of projects. Steps to replicate: - Install `documents_project` and open any project's settings using kebab menu (3 dots). - Click new > name…
Currently, an error will occur when user multi edits name of projects. Steps to replicate: - Install `documents_project` and open any project's settings using kebab menu (3 dots). - Click new > name `Test` > open settings page and unselect `Documents` > Save. - Click new > name `Test1` > Save. - From the list view select `Test` and `Test1` and edit their name. Error: ``` ValueError: Expected singleton: project.project(9, 10) ``` Cause: - During `multi-edit`, self contains multiple project records. - When only one of the selected projects has a documents folder (i.e. `use_documents` enabled), `self.documents_folder_id` contains that single folder, making `len(self.documents_folder_id.project_ids) == 1` to be True [1]. - The condition then proceeds to access `self.name` on the `multi-recordset`, raising singleton. Solution: - Avoided accessing `self.name` on a `multi-recordset` during multi-edit. - Filtered projects individually and updated the document folders using the name in vals. [1]: https://github.com/odoo/enterprise/blob/3c2985ca6011700c271ed14e40e08c89be822753/documents_project/models/project_project.py#L101 sentry-7452096418
18 changes
Enhancements to existing features
This update refines how timesheet assistant rules handle interruptions like quick messages. Previously, a short event could randomly change the associated project. Now, a 'short_lived' attribute helps ensure rules accurately track activity, preventing unnecessary project switches and improving timesheet data accuracy. This change also includes updates to Google Meet, Sheets, and Slides rules to better capture these events.
Original PR description
Before this commit: Events like Discord discussions are treated as key events, but they are not linked to a fixed project. Instead, they vary daily based on manual matching. This means a short interruption (e.g., replying to a quick message) can switch the project, even if the main work continues afterward. In this commit: - Add a 'short_lived' attribute to aw.rule. - When enabled, the rule sets the project/task for its own activity but does not update the next events (unless it was previously null). task-6198024
This update changes the URL structure for our spreadsheet integration with mydb.com, making it more stable and predictable. Previously, the spreadsheet ID was a simple name ('sheet1'), but it's now a unique, short identifier (UUID) to avoid potential issues. This ensures consistent access to the spreadsheet data.
Original PR description
…e default sheet id The sheet is now part of the url: mydb.com/spreadsheet/331?sid=sheet1 The current id for the default sheet is sheet1. It would be better if it was an id like others (small uuid). before: mydb.com/spreadsheet/331?sid=sheet1 after: mydb.com/spreadsheet/331?sid=918fd8b1-b6b0 task-6276062
This update adjusts payroll calculations in Odoo Enterprise to comply with Belgian social security regulations. Specifically, it updates salary thresholds based on employee age (under 30 vs. 30+) for restructuring reduction amounts. This ensures accurate social security reporting through DMFA files, maintaining legal compliance.
Original PR description
### Why: To comply with Belgian social security regulations, the restructuring reduction amount ($133.33$ per month) is subject to specific gross salary thresholds that differ based on the employee's age (above or below 30 years old). Updating these parameters ensures that payroll calculations are legally accurate and that the resulting social security contributions are correctly reported in the DMFA files using the appropriate technical codes. ### What: - Added new parameter values for the basic salary threshold, split by age categories (under 30 and 30+). - Configured the DMFA mapping for the restructuring amount to ensure compliant electronic reporting. task-6175186
This update clarifies how work accident leaves are processed for non-workers within the Odoo Enterprise system. It ensures accurate splitting of these leaves and provides a clearer view of how they are allocated. This improves the accuracy of payroll calculations and reporting related to employee absences.
Original PR description
Correctly splitting non-workers' work accident leaves and showing how it will be split. task-6274956
This update improves the softphone's call logging functionality by allowing users to record calls even without a specific contact. Now, when logging a call, the call automatically links to the relevant document, regardless of whether a contact was initially specified. This simplifies call documentation and improves workflow efficiency.
Original PR description
Make it possible to log on calls without contacts on softphone. When no contact, you should be able to log to any documents. Task-[6204798](https://www.odoo.com/odoo/5778/tasks/6204798)
This update simplifies payment processing by replacing the 'state' field with 'is_live', streamlining the system's payment status tracking. Additionally, marketplace menus have been reorganized for better navigation. These changes improve the user experience and operational efficiency related to payment processing and subscription management.
Original PR description
The `state` field is replaced with `is_live`. Marketplace menus are moved into a separate menu category. id-5722033
This update allows employees in Hong Kong to specify a postal address for IRD reports, ensuring accurate data submission. The system now includes postal addresses and ZIP codes in the generated reports, improving compliance and data quality. A cleanup of demo data addresses has also been performed.
Original PR description
Before this commit: - Employees only had a private/residential address for HK IRD reports. - The postal address fields in IR56 XML exports were always left empty, and the PDF reports displayed the postal address label without any value. - ZIP codes were not included in the residential or postal address lines used by IRD XML/PDF reports. After this commit: - A new optional postal address block is available on HK employee forms. - When enabled, this address is used to fill the postal address section in IRD XML and PDF reports, while keeping the residential address unchanged. - Residential and postal ZIP codes are included in the generated IRD address data, including `RES_ADDR_LINE3`, `POS_ADDR_LINE3`, and the PDF address strings. Task-6119163
This update simplifies AI agent configuration by unifying provider selection and response styles. It now supports multiple AI models (Gemini and GPT) for both general conversation and image generation, enhancing flexibility and performance. This change also includes improvements to error handling and UI styling.
Original PR description
This commit aims to simplify the agent configuration process by abstracting llm_model selection. Configuration: - Replaced `llm_model` with `provider` and `response_style` (4 styles). - Agent model is selected based on provider, response_style, and whether agent is called for image generation or website builder. Models: - Defaulted to Gemini-3-Flash/3.1 Pro and gpt-5.4-mini/gpt-5.4. - Image generation uses Gemini-3.1-flash-image and gpt-5.4 series. Service Mapping: - Reworked AIProvider to map directly to provider-specific AIApiService classes, simplifying the addition of future providers. Logic: - Implemented reasoning-based timeouts (up to 120s for medium/high reasoning). - Refined error handling for 429 quotas exceeded. - Various adaptation for tests. UI: - Improved agent card alignment and configuration view styling. task id: 5411094 upgrade PR: https://github.com/odoo/upgrade/pull/9751
This update optimizes the automatic scheduling process by prioritizing shifts based on importance. Now, the system allocates resources to the most critical shifts first, ensuring maximum coverage for high-priority tasks. This prevents lower priority shifts from being assigned when capacity is limited.
Original PR description
This commit orders open shifts by priority (most important ones first) before assigning resources to it (i.e., auto-plan). This ensures resources are allocated to the most important shifts first, leaving lower priority ones unassigned if maximum capacity is reached. task-6176328
This update simplifies the Helpdesk ticket interface by moving the 'Convert to Opportunity/Lead' option to the action menu. Previously, this button was always visible, creating unnecessary clutter and a less intuitive experience. This change improves the overall usability of the Helpdesk module.
Original PR description
Right now, the “Convert to Opportunity” button is always visible on Helpdesk tickets, even when it is not really relevant. It feels a bit inconsistent compared to other actions, and adds unnecessary clutter to the interface. Hence, this commit moves the convert to opportunity/lead to the action menu of helpdesk tickets. Related: odoo/upgrade#10018 task-6119255
This update enhances the Gantt view's ability to fold non-working hours when open shifts are used. Previously, open shifts were treated as always available, preventing the Gantt view from simplifying schedules for companies with fixed working times. Now, the system dynamically adjusts to accommodate both fixed and flexible schedules, improving the visual clarity of the Gantt chart.
Original PR description
### Purpose: The Gantt view has a visual feature that automatically folds non-working days (like nights and weekends) to avoid bloating the interface. However, the Planning app does not benefit from…
### Purpose: The Gantt view has a visual feature that automatically folds non-working days (like nights and weekends) to avoid bloating the interface. However, the Planning app does not benefit from this when open shifts are present, as these unassigned shifts are treated as fully flexible (24/7). This prevents the entire view from folding for companies with fixed schedules. ### Cause: In the `_gantt_unavailability` method, open slots (identified by `False`) were hardcoded to return an empty array of unavailabilities, forcing the Gantt renderer to keep those columns unfolded. ### Solution: Introduce dynamic flexibility checking for open shifts: - If all employees currently in the view have a fixed schedule, open shifts will adopt the company's default working calendar's unavailabilities. This allows the Gantt view to successfully fold weekends/nights. - If any employee in the view has a flexible schedule, open shifts will remain flexible (no unavailabilities), preserving scheduling freedom for flexible workforces. task-6189622
Resolved issues and error corrections
This update addresses a previous issue where unmapped mobile carrier codes (MCCs) caused expense transactions to be rejected, leading to user confusion. Now, a warning is displayed in settings if MCCs are missing, guiding users to correctly map them and preventing future transaction rejections. This ensures smoother expense reporting and accurate financial data.
Original PR description
Before this commit: - If the default expense category was deleted or MCC mappings were manually modified, some MCC codes remained unmapped. - Transactions with unmapped MCC codes were refused without clearly indicating that the issue was due to a missing configuration. - Users could misinterpret the behavior as a feature bug, while it was actually a setup issue. After this commit: - When the Expense Card feature is activated and the account is verified, ensure that all MCC codes are mapped to an expense category. - If any MCC is not mapped, display a warning in the settings. - Clicking on 'Open MCC' should open the MCC list view filtered to show only records where “Expense Category to Use” is not set. - If a transaction is refused because of an unmapped MCC, we create the expense at the refused state without any category set, and show the refused expense message on Chatter. task-5932712
This update resolves an issue preventing users from customizing the font style of headings on the appointment page. By wrapping the heading tag in a div, the system now correctly recognizes font style changes, allowing for consistent branding and design adjustments. This ensures a better user experience for appointment scheduling.
Original PR description
*: appointment Before this commit: The page title ("Choose your appointment") on controller page "/appointment" is a bare `<h1>` element at the root of an editable arch section, and it does not offer…
*: appointment
Before this commit:
The page title ("Choose your appointment") on controller page
"/appointment" is a bare `<h1>` element at the root of an editable arch
section, and it does not offer the Font Style selector in the website
builder, preventing users from changing their headings.
The Font Style option is intentionally hidden on such elements by the
`isRetaggingSafe` check. Retagging the section root (h1 -> h2/...) is
not safe because `replace_arch_section` only saves the content of an
editable section, never its root element (see 4469b36, "only save view
section content"). As a result, a root node tag change would not be
persisted and would silently revert on save.
After this commit:
The `<h1>` is wrapped in a `<div>`. The div becomes the OE directive
section root (kept intact on save) and the inner `<h1>` becomes part of
the editable content. As a result a Font Style change becomes a child
mutation rather than a root node change.
Community PR: https://github.com/odoo/odoo/pull/261797
Upgrade PR: https://github.com/odoo/upgrade/pull/10322
Upgrade Util: https://github.com/odoo/upgrade-util/pull/441
task-[6170946](https://www.odoo.com/odoo/project/974/tasks/6170946)This update ensures that the annual salary warning appears correctly on employee forms when using a fixed wage. Previously, this warning was only shown for certain wage types. This change improves accuracy and compliance by consistently displaying the warning for all fixed wage employees.
Original PR description
On employee's forms, only display the annual salary below threshold warning when the wage type of the version is set on fixed wage. task-6292248
This update removes a duplicate field, "Notice Period Real End", from employee and departure views. This simplifies the process of managing departure dates, especially when "Notice Respect" is set to "Partially", allowing the standard "Departure Date" to be edited.
Original PR description
Remove the redundant "Notice Period Real End" field from both the departure view wizard and employee view, as it duplicated "Departure Date". Now, when notice respect is set to "Partially", the standard "Departure Date" field becomes editable. Task: 6237636
This update corrects a technical issue in the VAT record book export that was incorrectly displaying '01' for invoices with 'No Sujeto por reglas de localización' taxes (like Portuguese VAT). The fix ensures the correct '17' operation code is used, aligning with Spanish VAT regulations and SII reporting requirements. This ensures accurate VAT reporting.
Original PR description
**Steps to reproduce:** * Install the **l10n_es_edi_sii** module. * Create a **Portuguese customer**. * Go to **Settings** and enable **EU Intra-community Distance Selling**, then refresh the tax…
**Steps to reproduce:** * Install the **l10n_es_edi_sii** module. * Create a **Portuguese customer**. * Go to **Settings** and enable **EU Intra-community Distance Selling**, then refresh the tax mapping. * Create a customer invoice with a **"No Sujeto por reglas de localización"** tax (e.g. **23.0% PT VAT**). * Go to **Accounting → Reporting → Tax Report → OSS Sales**. * Export the **VAT Record Books (XLSX)** file and open it. **Observed behavior:** * The "Clave de Operación" column shows "01" for lines with no_sujeto_loc taxes instead of "17". * The SII JSON for the same invoice correctly shows "ClaveRegimenEspecialOTrascendencia": "17". **Cause:** * In `_l10n_es_libros_get_common_line_vals()`, `operation_code` was computed manually as `'02' if exempt_reason else '01'`, which only handled the E2 exempt case and defaulted everything else to "01". * This missed OSS/no_sujeto_loc taxes (e.g. FR VAT, PT VAT) that should produce "17" per the Spanish VAT regime code table. **Fix:** * Extract operation code computation into a new dedicated method `_l10n_es_libros_get_operation_code()`. * For customer invoices, delegate to the existing `_l10n_es_get_regime_code()` method already used by SII, which correctly returns "17" for OSS-tagged taxes, "02" for E2 exempt, and "01" otherwise. * For vendor bills, mirror the SII logic by checking whether the invoice taxes include tags from `mod_303_casilla_10_balance` or `mod_303_casilla_11_balance` (intra-community indicators), returning "09" if so and "01" otherwise. opw-6197141,6216485 Forward-Port-Of: odoo/enterprise#119467 Forward-Port-Of: odoo/enterprise#117236
This update resolves an issue where portal users couldn't access photos attached to completed field service reports. The fix ensures that non-internal users can now view these images within the portal, improving the customer experience and providing more complete service records. This aligns with our commitment to providing a fully functional portal for our customers.
Original PR description
Photos were not accessible in the portal field service report for non-internal users. **Steps to reproduce** - Create a planning slot, set a portal user as the customer and mark the slot as "Completed". Add an image in the chatter. - Logged in with the customer's portal user account, access the field service report in the portal. The "Photos" section displays the name of the picture, but it is not possible to view it. <img width="888" height="320" alt="image" src="https://github.com/user-attachments/assets/523d1d1a-7c9c-4c9a-85f5-acd4df86d7ff" /> **Change** Similar to what is done in `project/controllers/portal.py` to give access to attachments to non-internal users from the portal, generate the necessary access tokens. opw-6236038 Forward-Port-Of: odoo/enterprise#118672
Features or functions removed from Odoo
This update removes a redundant function used to manage export options within several Odoo reporting modules. This simplification improves code maintainability and reduces potential complexity. The change ensures a cleaner and more efficient system for generating reports.
Original PR description
To keep the code as clean as possible, avoid using a function called _get_export_options() that simply puts the export_mode parameter. task-6190808
8 changes
Resolved issues and error corrections
This update ensures that orders configured with 'pay after meal' are automatically sent to the preparation display as soon as they are placed, regardless of payment status. Previously, the display wasn't updated until payment was made, which wasn't aligned with the customer's expected workflow. This change improves the user experience and operational efficiency for self-order systems.
Original PR description
When using a self order configuration with "pay after meal" and a valid online payment method. The order would not be sent to the preparation display until the order was paid. This is not expected because the customer is expected to pay after the meal. Steps to reproduce: ------------------- * Setup a self order with pay after meal and a valid online payment method * setup a preparation display linked to the same PoS configuration * Open the PoS and the self order * Make an order with any product and validate it without paying > Observation: The order is not sent to the preparation display Why the fix: ------------ When the configuration is set to "pay after meal", we always send the order to the preparation display. opw-6238352
This update fixes an issue where the shop floor displayed excessive decimal places for component quantities, leading to inaccurate readings. The change prevents floating-point precision errors during quantity calculations, ensuring more reliable data display for finished goods. This improves the accuracy of shop floor reporting.
Original PR description
**Issue** In the shop floor, floating-point values may display excessive decimals. **Steps to reproduce** - Create a BoM for a product, with a component tracked by lots - Set the component to be…
**Issue** In the shop floor, floating-point values may display excessive decimals. **Steps to reproduce** - Create a BoM for a product, with a component tracked by lots - Set the component to be consumed in a work order operation - Create several lots for the component, per ex 2: - LOT01 with 16.528 units - LOT02 with 10,000.00 units - Create an MO for 220.800 units of the finished product - Click on the shopfloor icon - Click to register the component consumption for the component. - Choose the first lot - Then choose the remaining units from the second lot -> This will display the quantity consumed as 220.79999999999998, even if the decimal accuracy is set to only 2 digits. **Cause** Since, there are 2 `moveLines`, one for each lot, the getter `quantityDone` add 2 floating point together: https://github.com/odoo/enterprise/blob/d7ab7ee1287342638006e290ede20b955aae8370/mrp_workorder/static/src/mrp_display/mrp_record_line/stock_move.js#L63-L69 inducing a floating-point precision error. The result is rendered directly in the XML template: https://github.com/odoo/enterprise/blob/d7ab7ee1287342638006e290ede20b955aae8370/mrp_workorder/static/src/mrp_display/mrp_record_line/stock_move.xml#L8-L14 without rounding. opw-6243804
This update resolves an issue where report customizations made in Odoo's Studio were incorrectly applied to shared layouts, leading to unexpected behavior and potential rendering problems. The fix ensures that report edits are now saved within the report's specific document view, preventing these issues and improving Studio's reliability.
Original PR description
Report edits could be applied on shared layouts such as web.basic_layout instead of the report-specific document view. This caused Studio customization diffs to affect unrelated reports and could also lead to rendering errors when report-specific fields were evaluated in a different report context. The issue occurred because content was inserted directly into the shared layout article section instead of the nested report document view. Steps to reproduce: 1. Open Studio on any module and create or edit a report. 2. Select any of the External, Minimal, or Blank report types. 3. Add content to the report body and save the report. 4. Open another module and create a report using the same report type. 5. Observe that the previous customization is already present. Before this fix, the generated diff could inherit from web.basic_layout. After this fix, body edits are kept inside the report-specific document view. Related Ticket: opw-6245485
This update fixes an issue where both units involved in a quality control failure were incorrectly moved to the designated failure location. The fix ensures that the destination of moved goods is accurately determined based on remaining demand, preventing unintended misdirection of inventory. This improves the reliability of the quality control process.
Original PR description
Version: ---------- - 18.0+ Steps to reproduce: ------------------- 1. Install *quality_control* module. 2. Go to *Settings* and enable *Storage Locations*. 3. Open Quality module go to the Quality…
Version:
----------
- 18.0+
Steps to reproduce:
-------------------
1. Install *quality_control* module.
2. Go to *Settings* and enable *Storage Locations*.
3. Open Quality module go to the Quality control -> Quality points
4. Create a *Quality Point* with:
* *Product* set.
* *Control per* set to *Quantity*.
* *Operation* set to *Receipts*.
* *Failure Location* set to *WH/Stock/Shelf1*.
5. Create a *Receipt* with demand of *2 units* for the product used in QP.
6. Mark the quality check as *To Do*.
7. Update the *Done Quantity* to *1*.
8. Open the quality check and click *Fail*.
9. Update the *Done Quantity* back to *2* and save.
10. Open the quality check again, click *Pass*, and validate the receipt.
11. Open the *Detailed Operations* to inspect move lines.
Issue:
------
* Both units (failed and passed) are moved to the *failure location*.
Cause:
------
When a user fails a move line via the QC wizard, the flow is:
do_fail() → show_failure_message() → confirm_fail()
→ check._move_to_failure_location(failure_location_id, failed_qty)
Inside `_move_to_failure_location`, when `failed_qty == move_line.quantity`,
the condition:
https://github.com/odoo/enterprise/blob/a33f580455a54a81d89a848f7b493d9dcc9ba2b2/quality_control/models/quality.py#L458
e.g. 1 == 1
was True even when `move.product_uom_qty = 2` (demand still 2). It only
compared the done quantities, ignoring that unfulfilled demand remained.
As a result, `move.location_dest_id` was set to the failure location.
Later, when the user increases the quantity from 1 to 2 on the move form,
the flow is:
_set_quantity → process_increase → _set_quantity_done → _prepare_move_line_vals
In `_prepare_move_line_vals` :
'location_dest_id': self.location_dest_id.id,
https://github.com/odoo/odoo/blob/47bf284e1e9d8be0d4255418e0a3f67c74fa5114/addons/stock/models/stock_move.py#L1688
The new move line inherits `move.location_dest_id` directly, which at this
point is already the failure location.
When the user then calls `do_pass()` on the second unit, `do_pass()` only
writes `quality_state = 'pass'` and never touches `location_dest_id`. So
the second (passed) move line silently retains the failure location.
Solution:
---------
Add the guard `move.product_uom_qty <= move_line.quantity` to the condition
so the entire move's destination is only redirected when there is genuinely
no remaining unfulfilled demand:
When demand > done qty, the else-branch runs instead: it reduces the
original move's demand and creates a new separate move pointing to the
failure location, leaving the original move's `location_dest_id` pointing
to stock. Any subsequent move lines created on the original move therefore
correctly inherit the stock destination.
---
opw-6080871
Forward-Port-Of: odoo/enterprise#120041
Forward-Port-Of: odoo/enterprise#112859This update corrects a bug where worked-time leave entries could be duplicated when overlapping with public holidays, particularly with flexible work schedules. The fix ensures public holidays are prioritized, preventing the creation of multiple work entries for the same period and improving payroll accuracy.
Original PR description
Issue: When work entries are generated from Attendances, a worked-time time off created by the Indian sandwich rule can overlap a public holiday and generate duplicate work entries for the same day.…
Issue: When work entries are generated from Attendances, a worked-time time off created by the Indian sandwich rule can overlap a public holiday and generate duplicate work entries for the same day. Steps to reproduce: - Create an employee with Work Entry Source set to Attendances - Use a flexible working schedule on the employee - Configure a public holiday on a scheduled day with work entry type (Paid time off) - Create a time off type with Count as set to Worked Time - Generate time off for the period so the public holiday entry exists (maybe a day before and a the public holiday and the day after) - Open Payroll > Work Entries (Observe the date of the public holiday will have more than 8h entry) Cause: In `_get_version_work_entries_values()`, calendar leaves are split by `hr_holidays` `time_type` into: - leaves: absences and public holidays - worked_leaves: worked-time time off For attendance-based contracts, both sets were turned into work entries without removing overlap between a public holiday and a worked-time leave on the same period. https://github.com/odoo/odoo/blob/3a088e23d3e563c39cdcb252edc8c7cc74981de4/addons/hr_work_entry/models/hr_version.py#L222-L226 For non-flexible calendar: Public holidays and worked-time leaves are both clipped to the static working schedule (e.g. 8h per working day). overlap was kept in both result sets. https://github.com/odoo/odoo/blob/3a088e23d3e563c39cdcb252edc8c7cc74981de4/addons/hr_work_entry/models/hr_version.py#L260 For flexible calendar: The one-day intervals are kept as the actual interval (often 00:00-23:59 for a public holiday). The worked-time on that day is schedule-shaped (e.g. 8h). Subtracting intervals on a full-day public holiday left a 16h fragment instead of removing the public holiday entry. https://github.com/odoo/odoo/blob/3a088e23d3e563c39cdcb252edc8c7cc74981de4/addons/hr_work_entry/models/hr_version.py#L242-L249 Solution: We need to make regular leaves take priority over worked-time leaves, compute the real regular leave intervals first, then remove those intervals from the worked-time leave intervals before work entries are created: - for fully flexible employees, subtract regular leaves from worked leaves; - for flexible calendars, keep one-day regular leaves as is and subtract them from worked-time leaves - for non-flexible attendance-based calendars, clip regular leaves on the static schedule, then subtract them from worked-time leaves clipped on the same schedule. This means that when a sandwich worked-time leave overlaps a public holiday, the public holiday consumes that period first. The overlapping part is then removed from `real_worked_leaves`, so no second worked-time entry is generated for the same public holiday period. opw-6237163 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update corrects a bug in the website editor for renting products. Previously, removing the quantity field caused an error. This fix ensures the system handles scenarios where the quantity field is not present, preventing the error and maintaining functionality. This change was introduced in version 19.0.
Original PR description
Before this commit, the function below assumes `this.el.querySelector("input[name='add_qty']");` will always be present but you can change this in the website editor.
https://github.com/odoo/enterprise/blob/c1d47899c90fcfa426e1863887111d3ea9f6f15e/website_sale_renting_planning/static/src/interactions/website_sale.js#L18-L39
Steps to reproduce issue:
Runbot 19.0
Open renting -> Products
Select a product (preferably one created by default runbot setup) Click the smartbutton to go to this products web page Open the website editor
Click Edit
Under the styles tab, de-select the quantity field See error message
**Only happens in 19.0**
Introduced in https://github.com/odoo/enterprise/commit/89962571c246caf05e669bb63ad933e67e74ab61
[Ticket](https://www.odoo.com/odoo/project/49/tasks/6294612)
opw-6294612This update resolves an issue where unnecessary code was inadvertently carried over during the port of a previous feature. The fix ensures the l10n_pe_reports module aligns with the requirements of Odoo Enterprise version 19.0, streamlining the reporting functionality for Peruvian users.
Original PR description
During the FW port of https://github.com/odoo/enterprise/pull/117891 We forgot to remove the unnecessary code opw-5978673
This update resolves a technical issue that caused the account reports audit tour to fail in complex Odoo environments. Specifically, the tour now waits for the Kanban view to be active before opening the necessary reports, preventing a premature trigger and ensuring a smoother user experience.
Original PR description
The account_reports_audit tour was failing at the "Balances" button step due to a race condition in the preceding steps. In environments with many modules, the "Open the working file" step was triggered prematurely while still on the return checks view, because its selector was too broad. This commit narrows the selector for "Open the working file" to ensure it only triggers once the Kanban view is actually active. [runbot-938920](https://runbot.odoo.com/odoo/runbot.build.error/938920)
9 changes
Resolved issues and error corrections
This update resolves a technical issue where the Urbanpiper order ticket screen incorrectly displayed customer information even after the customer was removed. The fix ensures that customer details are only shown when a customer is actually linked to the order, improving the user experience and preventing error messages.
Original PR description
Steps to reproduce: ==== - Place an order through Urbanpiper. - Edit the order and remove the customer. - Open the ticket screen and click the info button. - A traceback occurs. Cause: ==== - Customer details were rendered even when no customer was linked to the order. Fix: ==== - Display customer details only when a customer is present on the order. task-6233812
This update resolves a bug that occurred when reloading a chart of accounts, specifically when an account's XMLID still referenced its original company. The fix ensures the system correctly verifies the account belongs to the target company before reloading, preventing errors and ensuring accurate account data.
Original PR description
When reloading a chart of accounts, `_pre_reload_data` resolves an account via its xmlid and then evaluates: ```py re.match(f'^{values["code"]}0*$', account.code) ``` `account.code` is a non-stored…
When reloading a chart of accounts, `_pre_reload_data` resolves an account via its xmlid and then evaluates:
```py
re.match(f'^{values["code"]}0*$', account.code)
```
`account.code` is a non-stored computed field that reads from the company-dependent field `code_store`. If the resolved account has no `code_store` entry for the target company (e.g. the account was originally set up under a different company but its xmlid was prefixed with the current company id), `_compute_code` returns False instead of a string, causing a TypeError in re.match.
```py
File "/home/odoo/src/odoo/19.0/addons/account/models/chart_template.py", line 442, in _pre_reload_data
if not account or not re.match(f'^{values["code"]}0*$', account.code):
File "/usr/lib/python3.10/re.py", line 190, in match
return _compile(pattern, flags).match(string)
TypeError: expected string or bytes-like object
```
```sql
apan_4342860=> SELECT
aa.id,
aa.code_store,
imd.module,
imd.name
FROM account_account aa
JOIN ir_model_data imd
ON imd.res_id = aa.id
AND imd.model = 'account.account'
WHERE aa.id = 1056;
id | code_store | module | name
------+-----------------+---------+-----------------
1056 | {"2": "510500"} | account | 1_co_puc_510500
(1 row)
```
This situation arises when a customer moves or reassigns an account between companies but the xmlid retains the original company prefix.
**Fix:**
After resolving the account via xmlid, check whether it actually belongs to the target company using filtered_domain with _check_company_domain. If it does not pass the check, unlink the stale ir.model.data entry and treat the account as not found, allowing the reload to re-establish the correct xmlid linkage via the code-based lookup that follows.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThe 'Fill' option on the /shop page now correctly adjusts product image sizes based on the selected 'cover' or 'contain' mode. Previously, the toggle had no effect. This change resolves a visual inconsistency and ensures the product images display as intended.
Original PR description
**Problem:** On the /shop page, the "Fill" option in the web editor (cover/contain toggle on product card images) appears clickable but has no visible effect on the product thumbnails. **Steps to…
**Problem:**
On the /shop page, the "Fill" option in the web editor (cover/contain toggle on product card images) appears clickable but has no visible effect on the product thumbnails.
**Steps to reproduce:**
1. Install website_sale and open /shop.
2. Open the web editor and select the shop page.
3. Locate the "Fill" button group in the right panel (with the two svg icons).
4. Click the alternate option to switch between cover and contain.
5. Observe that the product card thumbnails do not change appearance.
**Current behavior:**
The toggle flips the `o_wsale_context_thumb_cover` class on the products table (and the activation of the `products_thumb_cover` view), but the product images keep rendering with `object-fit: contain` regardless of the toggle state.
**Expected behavior:**
The image fill mode follows the toggle:
- "cover" option active → product image uses `object-fit: cover`
- "cover" option inactive → product image uses `object-fit: contain`
**Cause of the issue:**
The product image template renders the img with the `object-fit-contain` utility class, and the local SCSS rule declares
`.object-fit-contain { object-fit: contain !important; }`. The CSS variable `--o-wsale-card-thumb-fill-mode` (set to `cover` by `.o_wsale_context_thumb_cover`) does cascade down to the img, but the non-variable, `!important` rule on the utility class always wins, so the variable-driven rule
`object-fit: var(--o-wsale-card-thumb-fill-mode, contain)` is silently overridden and the toggle becomes inert.
**Fix:**
Making the `.object-fit-contain` rule read the same CSS variable lets the existing toggle mechanism take effect without changing any template or removing the utility class. Outside the `.o_wsale_context_thumb_cover` context the variable is undefined, so the `var(..., contain)` fallback preserves the prior `contain` behavior for any other consumer of the class. This keeps the change to a single SCSS line, with no XML touched and no other CSS class semantics altered.
opw-6231432
Forward-Port-Of: odoo/odoo#266717This update fixes an issue where refunding a partially paid Point of Sale order incorrectly displayed the total and line amounts. Previously, the system showed the original order's total, even after multiple refunds. This change ensures accurate refund calculations are reflected in the PoS system, improving financial reporting and order management.
Original PR description
When refunding an order that has already been partially refunded, the line amount and total amount where incorrect. They would be the total amount of the original order. Steps to reproduce: ------------------- * Open PoS and make an order with 3 quantity of a product. * Close the session * In the backend, refund 1 quantity of the order and validate the refund * Refund again the same order with the 2 remaining quantities > Observation: The total amount and line amount are not correct opw-6215019 Forward-Port-Of: odoo/odoo#265322
This update fixes an issue where Odoo cron workers weren't efficiently managing database connections. By introducing a new configuration setting, we can now tailor the memory limits for cron workers, preventing unnecessary database cycling and improving overall performance. This ensures cron jobs run smoothly and efficiently.
Original PR description
The configuration option `registry_lru_size` does not exist and does not work at all in recent versions. Defining odoo-specific environment variables to handle: - ODOO_REGISTRY_LRU_SIZE: the default registries size - ODOO_REGISTRY_LRU_SIZE_CRON: overwrite for cron workers Cron workers have often a different workload than HTTP workers and we may set a different limit there. If the limit is lower than the number of databases, a cron job will not reuse registries because it cycles through all known ones - in such cases, we can set a lower limit to keep the memory lower. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#268587
This update corrects a restriction in the Odoo accounting module that prevented valid vendor bills from being created. The system previously blocked certain document types based on company VAT affiliation, which was incorrect for purchase invoices. Now, all legally valid document types are supported for purchase invoices, ensuring accurate recording of vendor bills.
Original PR description
Currently, the system restricts fiscal document types for both sales and purchases based on the company’s VAT affiliation, which prevents valid vendor bills from being recorded. **Steps to…
Currently, the system restricts fiscal document types for both sales and purchases based on the company’s VAT affiliation, which prevents valid vendor bills from being recorded. **Steps to reproduce:** - Install the `l10n_gt_edi` module and switch to a `GT company`. - Navigate to Accounting > Vendors > Bills. - Create a vendor bill. - Try to select a document type such as `FPEQ` or `FCAP`. **Observation:** The system hides valid vendor document types (e.g., `FPEQ`, `FCAP`) if they do not match the company’s VAT affiliation. **Root Cause:** At [1], the method `_compute_l10n_gt_edi_available_doc_types` filters document types using the company’s VAT affiliation (`l10n_gt_edi_vat_affiliation`) for all move types. This logic is correct for sales (where the company is the issuer), but incorrect for purchases (where the vendor determines the document type). As a result, valid purchase document types are wrongly excluded. **Fix:** This commit updates the computation logic to: - Apply affiliation-based filtering only for sales (`out_*`). - Bypass the restriction for purchases (`in_*`), allowing all valid document types. This ensures that vendor bills can include any legally valid document type regardless of the company’s affiliation, while preserving the existing restrictions for sales workflows. [1]: https://github.com/odoo/enterprise/blob/7792926504a823590fbbe574a96994002a92fc17/l10n_gt_edi/models/account_move.py#L162-L166 opw-6099863
This update resolves a technical issue where VoIP registration would fail with an error message when a user left a session open and inactive. The fix ensures that the registration process is reliably restarted and handled, preventing frustrating error dialogs and maintaining consistent VoIP functionality. This improves the user experience by ensuring stable call connectivity.
Original PR description
Leaving a session open and idle (page open, no activity at all) eventually pops an error dialog: UncaughtPromiseError > RequestPendingError REGISTER request already in progress, waiting for final…
Leaving a session open and idle (page open, no activity at all) eventually pops an error dialog:
UncaughtPromiseError > RequestPendingError
REGISTER request already in progress, waiting for final response
at Registerer.register (sip.js)
at Registerer.register (registerer.js)
at UserAgent.attemptReconnection (user_agent_service.js)
When the WebSocket transport drops while a REGISTER is in flight (which happens on an idle tab: SIP.js sends a periodic re-REGISTER before the registration expires, and the socket may be closed by an idle timeout or by the machine going to sleep in the meantime), the final response never comes back. SIP.js only clears its internal `waiting` flag from the REGISTER response callbacks (onAccept/onReject/onRedirect); it is never reset on transport loss or request timeout. The Registerer is then stuck `waiting` forever, and every subsequent register() rejects with a RequestPendingError.
On top of that, our wrapper's register() did not return the SIP.js promise, and attemptReconnection() called it without awaiting, so the rejection escaped the surrounding try/catch and surfaced as an unhandled promise rejection. Worse, the WebSocket error was resolved right after, so the user appeared reconnected while VoIP registration was actually dead until the page was reloaded.
This commit makes register() recreate the underlying SIP.js Registerer when it is stuck `waiting` (a clean instance starts with waiting=false), and return the promise so callers can await it. attemptReconnection() now awaits it, so any rejection goes through the existing retry/back-off logic instead of bubbling up as an uncaught error.
The recreation is intentionally conditional: disposing a healthy registerer would send an unregister (REGISTER expires=0) racing with the fresh register (expires=600) and could leave us unregistered, so we only recreate when a request is actually stuck.
Forward-Port-Of: odoo/enterprise#119701This update resolves a crash in the HTML editor when pasting tables containing header cells (like those from Word). Previously, selecting these headers caused an error. Now, the editor handles tables with headers correctly, ensuring a smooth user experience when pasting and editing HTML fields.
Original PR description
Description of the issue/feature this PR addresses: Current behavior before PR: When a pasted table contains <th> header cells (common from Word paste), selecting them and triggering a toolbar refresh crashes because closestElement(node, "td") returns null for headers and the code then calls getBoundingClientRect() on null. Match "td, th" instead and bail out early when no cell ancestor is found. Desired behavior after PR is merged: No errors when selecting or drag/drop Steps to reproduce: 1. Open a record with an HTML field (e.g. a sales order Terms and Conditions). 2. Paste a table that has <th> cells in the first row (copy from Word or use raw HTML). 3. Select text across the header cells and drag/drop or click outside. 4. Expected: nothing happens. Actual: TypeError "Cannot read properties of null (reading 'getBoundingClientRect')". --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves an issue where the Chilean DTE module incorrectly marked invoices as rejected when the SII (tax authority) reported a server error (status 99). Previously, status 99 always triggered a rejection, leading to duplicate invoices and manual correction. Now, status 99 is handled specifically, allowing for safe retries and clear communication to the user about the SII response.
Original PR description
**Description of the issue/feature this PR addresses:** When sending a Chilean DTE to SII, if SII returns status code 99 (internal server error), the invoice is incorrectly marked as rejected.…
**Description of the issue/feature this PR addresses:**
When sending a Chilean DTE to SII, if SII returns status code 99 (internal server error), the invoice is incorrectly marked as rejected. According to the SII specification, code 99 means the server had an internal error and it is unknown whether the DTE was actually received — it is not a rejection.
This causes fiscal issues: the DTE may have been validly registered at SII, but Odoo marks it as rejected. If the user retries the send, SII rejects it as a duplicate. If the user creates a new invoice for the same document, a duplicate fiscal document is generated. Recovery requires manual intervention.
_This issue is also tracked in the following Odoo task: https://www.odoo.com/es_ES/my/tasks/5374459_
**Current behavior before PR:**
Any `STATUS` code other than 0 or 5 falls through to:
```
else:
self.l10n_cl_dte_status = 'rejected'
```
This includes code 99, which does not mean the DTE was rejected — it means the outcome is unknown.
**Desired behavior after PR is merged:**
Status 99 is handled explicitly: the invoice keeps its not_sent status so it can be safely retried. The chatter still logs the SII response so the user is informed.5 changes
Resolved issues and error corrections
This update corrects a bug that prevented users from saving purchase order lines when a specific one2many field was added through Studio. The fix bypasses security record rules during the inverse cache domain filtering process, allowing the save operation to complete successfully. This ensures proper functionality when using Studio to configure related fields.
Original PR description
Steps to reproduce 1. Add a one2many field on product.product targeting purchase.order.line with relation_field product_id (e.g. through Studio). 2. Set its domain to [('state', 'in', ('purchase',…
Steps to reproduce
1. Add a one2many field on product.product targeting purchase.order.line with relation_field product_id (e.g. through Studio).
2. Set its domain to [('state', 'in', ('purchase', 'done'))].
3. Ensure the "Purchase Order Line multi-company" rule (purchase.purchase_order_line_comp_rule) is active.
4. Create a new RFQ with one product line and save.
Issue
Saving the RFQ raises an AccessError. When product_id is assigned on the new line, Many2one._update_inverses walks every inverse one2many of product_id and calls records.filtered_domain(invf.get_domain_list(...)) to know which lines belong in the inverse cache (see https://github.com/odoo/odoo/blob/ee82034be1fa720577508ffbc7be41a198be7588/odoo/fields.py#L3215). For the Studio-added one2many, the domain references `state`, a stored related field on purchase.order.line. Resolving it through filtered_domain (https://github.com/odoo/odoo/blob/ee82034be1fa720577508ffbc7be41a198be7588/odoo/models.py#L6257) ends up consulting ir.rule on purchase.order.line, and the multi-company rule rejects the read in this transient state, which aborts the save.
Native one2many fields don't carry this kind of stored-field domain on the inverse side, so the issue only surfaces once such a field is declared (typically via Studio).
Solution
Run the inverse-cache domain filter in sudo. _update_inverses only updates the in-memory cache of the inverse one2many; it is not a security boundary and the records being filtered are the ones the user is currently writing, so they already have access. Sudo'ing the predicate evaluation lets the bookkeeping run without being blocked by record rules on the comodel side.
opw-6057361This update fixes an issue where the Peppol XML export incorrectly included vendor deferred dates in invoices. These dates were irrelevant for the customer and were causing export problems. The change now prevents the creation of these deferred entries and removes them from the exported invoices.
Original PR description
The current implementation of the Peppol XML export incorrectly populates the <cac:InvoicePeriod> nodes with internal deferred entry dates. These dates are intended for the vendor's revenue recognition process, and the customer has nothing to do with these dates. This commit ensures that: - deferred entries are never created when importing vendor bills. - <cac:InvoicePeriod> is no longer exported in invoices (for now). task-6014315 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update fixes a minor issue where loading email templates in Odoo would incorrectly mark the template as 'dirty'. This change ensures a smoother experience when previewing and discarding email templates without immediately saving them to the database. It prevents potential interruptions during template editing.
Original PR description
Before this commit, when create a new email marketing and load a template, the isDirty() is true. Because we use the same isDirty function from the html field After this commit, when create a new email (not saved to db) and load a template, we consider the html field in the mass_mailing is not dirty. This is to prevent interruption when discarding after this PR: https://github.com/odoo/odoo/pull/145902 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves an issue where users remained suggested recipients after unsubscribing from a mail thread. The fix ensures that the current user is completely removed from the list of suggested recipients when they click 'Unfollow,' improving the user experience and preventing unwanted notifications. This was a minor bug fix.
Original PR description
### Steps to reproduce: - Open any mail thread in chatter - Click the "Send To" button once - Click "Unfollow" - You will be a suggested recipient ### Cause of Issue: The suggested recipient generation did not filter out the current user. After unsubscribing, the current user could still be returned by `_message_get_suggested_recipients` because the user is not on the following list. https://github.com/odoo/odoo/blob/23398d24e108875b2838715d4b366df265d53234/addons/mail/models/mail_thread.py#L1881-L1907 ### Fix: Since followers are excluded from suggested recipient candidates in the mail thread, and the current user should be excluded when they unfollow, the current user is excluded altogether. opw-6122351
This update fixes an issue where invoices generated with very small product prices (e.g., $0.00003) were being incorrectly formatted in the UBL electronic invoice file. The change ensures the PriceAmount field in the UBL file adheres to the required format, preventing potential errors in electronic invoice processing. This ensures accurate and compliant invoice generation for PEPPOL transactions.
Original PR description
**STEP TO REPRODUCE** 1. Go in debug mode to increase product price decimal precision to 5. 2. Create an invoice with a product of price 0.00003 3. Send the invoice using peppol to generate the ubl file. 4. Opening the file, notice the PriceAmount is 3.33333e-05 which is not a valid string for a float in ubl. opw-6188947