Daily updates from Odoo
Tuesday, June 23, 2026
206 changes
24 changes
Resolved issues and error corrections
This update resolves a critical issue where VoIP registration would fail due to a delayed response when a user left a session open and inactive. The fix ensures a new registration attempt is made when the initial request times out, preventing error dialogs and restoring VoIP functionality. It improves the reliability of the VoIP service for users.
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#120487
Forward-Port-Of: odoo/enterprise#119701This update resolves an issue where the FEC export wizard was generating empty lines with zero balances for certain accounts. The fix ensures accurate reporting of opening balances, particularly when prior-year entries result in zero balances, improving the reliability of financial data exports for French companies using the l10n_fr_account module.
Original PR description
Steps to reproduce: - Use a French company (l10n_fr_account installed) - Post prior-year entries so that an account/partner nets to zero at the start of the next fiscal year (e.g. a customer invoice fully paid the same year, or a misc entry debiting and crediting the same balance-sheet account), and keep another account/partner with a non-zero opening - Open the FEC export wizard, set Start Date to the first day of the next year - Generate the FEC file and look at the "Balance initiale" (OUVERTURE) lines Issue: One of the exported line in as empty one with `...|0,00|0,00|..`` opw-6083991 Forward-Port-Of: odoo/odoo#270658 Forward-Port-Of: odoo/odoo#268510
This update resolves an issue where the payment authorization process would fail if a required address field was left blank. The fix ensures that empty address fields are now handled gracefully by setting them to empty strings, preventing errors and improving data accuracy. This enhances the reliability of payment transactions.
Original PR description
Fix bug introduced by commit https://github.com/odoo/odoo/pull/267592/changes/c4556637e8eeef07ce6e3cc3b3b4cf28fa10e468 that caused an error if an address field was not set, due to trying to cut a False field. Now, unset fields are set to empty strings. Forward-Port-Of: odoo/odoo#270295
This update ensures that prettified links in portal chatter messages remain functional after a page refresh. Previously, a refresh would break these links. The fix involves sending the correct thread name to ensure the links are properly formatted and displayed to users.
Original PR description
Before this commit, a message link posted on a portal chatter would lose it's prettified link (introduced in [1]) upon page refresh. This happens because `prepareMessageBody` needs the thread's `displayName` to create the prettified message link, which is not sent on portal chatter init. This commit fixes the issue by sending the thread's `display_name`. [1] https://github.com/odoo/odoo/pull/221069 task-6204819 Forward-Port-Of: odoo/odoo#270032 Forward-Port-Of: odoo/odoo#263488
This update fixes an issue where the spreadsheet filter dropdown remained open even when the filter value hadn't changed. The fix ensures the dropdown automatically closes after a filter selection, providing a more consistent and user-friendly experience. This improves the overall usability of the spreadsheet dashboard.
Original PR description
Current behavior before PR: - In b4d5d1f, added early return when filter value is unchanged. - However, the dropdown was not closed in this case, leaving it open after clicking the filter button, resulting in inconsistent and unexpected UX. Desired behavior after PR is merged: - Ensure the dropdown is closed even when the filter value remains unchanged, restoring consistent and expected behavior. Task: [6304213](https://www.odoo.com/odoo/project/2328/tasks/6304213) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271298 Forward-Port-Of: odoo/odoo#270225
This update resolves a technical issue related to how Odoo handles direct debit mandates for SEPA accounts. The change adds a constraint to ensure the correct bank account is linked to the mandate, improving the reliability of direct debit payments. This ensures accurate and secure processing of payments.
Original PR description
Forward-Port-Of: odoo/enterprise#121236 Forward-Port-Of: odoo/enterprise#120901
This update resolves an issue where manually adding serial-tracked by-products to manufacturing orders caused errors when closing production. The fix ensures that all move lines, including those with manually assigned serial numbers, are correctly processed within the shopfloor workflow, preventing user error messages.
Original PR description
**Issue** Adding a serial-tracked by-product manually on a Manufacturing Order whose BOM does not define it, can lead to inconsistencies when assigning serial numbers in the shopfloor application.…
**Issue** Adding a serial-tracked by-product manually on a Manufacturing Order whose BOM does not define it, can lead to inconsistencies when assigning serial numbers in the shopfloor application. **Steps to reproduce** - Activate by-product in the settings - Create a product with an empty BOM (final product) - Create another product tracked by serial number (by-product) - Create and confirm a MO for the final product with 1 unit of the by-product - Go to Miscellaneaous -> operation Type -> shopfloor - Activate the option "Pre fill lot/serial numbers in shop floor" - Return to the MO and open the shopfloor view - Click on the '+' button next to the by-product and assign a serial number - Try to close the production -> A user error is raised stating that the by-product requires a serial number. **Cause** When the by-product is added manually on the MO, a stock move is created with an initial move line that does not contain any serial number. Later, when assigning a serial number from the shopfloor view: https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/mrp_workorder/models/stock_move.py#L121-L122 a new move line containing the serial number is created: https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/mrp_workorder/models/stock_move.py#L116-L119 However, the original empty move line is not removed (the issue): https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/mrp_workorder/models/stock_move.py#L124-L125 Because `self.picking_type_prefill_shop_floor_lots` is True, but `self.byproduct_id` is an empty recordset since: https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/addons/mrp/models/mrp_production.py#L1304-L1311 https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/addons/mrp/models/mrp_production.py#L1279 Indeed, `byproduct_id` is only populated from BOM-defined by-products. As a result, while confirming the production, there is 2 sml and among them, the original one without SN, which triggers the error: https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/addons/stock/models/stock_move_line.py#L590 https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/addons/stock/models/stock_move_line.py#L634-L635 https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/addons/stock/models/stock_move_line.py#L658-L659 https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/addons/stock/models/stock_move_line.py#L661-L669 opw-6223158 Forward-Port-Of: odoo/enterprise#120493 Forward-Port-Of: odoo/enterprise#118792
This update adjusts the accounting classification for a specific inventory account (502040) within the Philippine localization module (l10n_ph). The account type has been changed from 'Expenses' to 'Current Assets' to align with updated accounting standards and reporting requirements. This ensures accurate financial reporting.
Original PR description
Update the account type of 502040 Inventory/Stock Variation account from ` Expenses` to `Current Assets`. task-6299228
This update corrects a technical issue related to barcode scanning tests within the Point of Sale and POS Stock modules. The test steps for a specific EAN-13 barcode pattern have been moved to the `pos_stock` module where the relevant rules are defined. This ensures more accurate and reliable barcode scanning functionality.
Original PR description
In this commit:
=
- The test steps covering the EAN-13 barcode pattern `21.....{NNDDD}` have been moved from `point_of_sale` to `pos_stock` because the rule for this barcode pattern is defined in `stock`.
runbot-error-242912This update resolves an issue where a key test partner wasn't consistently loaded during demo data setup. By renaming the test partner to 'A Partner Full', the system now guarantees it's included, ensuring consistent and reliable testing of the Point of Sale (POS) functionality. This improves the accuracy of test results and reduces potential issues during development.
Original PR description
Issue:
=
* The test partner name ("Partner Full") was not guaranteed to be loaded with demo data because only the first 100 partners are loaded, and the record could fall outside that limit.
Fix:
=
* Rename the test partner from "Partner Full" to "A Partner Full" to ensure it is included with demo data too.
runbot-error- 243063, 939228This update fixes an issue where preparation times weren't correctly calculated when order stages changed and ensured the preparation time report only displayed data for the active company. This improves the accuracy of order processing times and reporting, leading to better business insights.
Original PR description
Issues: - Preparation time for order lines was not computed when the preparation order stage changed. - Preparation time report aggregated orders across all companies instead of showing records for the active company only. Fixes: - Ensure preparation time is properly recomputed when the order stage changes. - Add company domain filtering to the preparation time report. Task-6250974 Forward-Port-Of: odoo/enterprise#118738
This update significantly speeds up appointment scheduling, particularly when managing multiple resources like tables in a restaurant. The change optimizes how the system checks resource availability, resulting in faster loading times and quicker auto-assignment processes. This improves the overall user experience and efficiency.
Original PR description
In the current code, for each slot, and for each "available" resource, we check if the resource is available on the slot, based on availability values. Then, we check the remaining capacity of that…
In the current code, for each slot, and for each "available" resource, we check if the resource is available on the slot, based on availability values. Then, we check the remaining capacity of that resource. Also, linked resources information is added when computing the original resource remaining capacity. If many linked resources exist, this will be done several times and is not useful. This commit makes that loop disappear. We now check all resources at once in terms of availability, and linked resources that could be selected (in the appointment resources, in the slot resources (if any restricted resource)) at the same time. Then, the total capacity is the sum of the resource remaining capacity and the ones of available linked resources. Therefore, _slot_availability_is_resource_available is renamed to _slot_available_resources, as it now takes more than one resource and returns all resources among 'resources' that are valid on the slot, based on the availability_values, slot restrictions and booking lines. A noticeable difference is mainly seen when using many resources (and linked resources). For instance, a restaurant with a lot of small tables will have their slot availability check much shorter. BENCHMARK, LOCAL (time only, as number of requests does not change) Only appointment installed For a restaurant with - 10 tables of 2 - 5 tables of 2 linked, 2 times - 10 tables of 4 - 2 table of 2 - time then auto assign On loading /appointment/id: ~ 3.1s -> ~ 1.6s On selecting any number of people (1 to 10): [2s, 2.5s] -> [0.6s, 0.8s] Task-4144524 Forward-Port-Of: odoo/enterprise#121212 Forward-Port-Of: odoo/enterprise#107711
This update resolves a confusing warning message that appeared during bill editing, related to vendor history. The fix prevents temporary data inconsistencies from triggering these warnings, creating a smoother and more intuitive editing process for users. The warning is now only calculated when the bill is saved, ensuring a better user experience.
Original PR description
Abnormal bill warnings are based on vendor history read from the saved move in the db, while a bill is being edited the form uses a temporary record; after changing the vendor, that temporary value differs from the vendor still stored on the saved move. This makes the warning use the old vendor's history while showing the new vendor's name. Only compute these warnings for saved records, while editing hide them and let them be recomputed once the bill is saved. task-6263829 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270515
This update corrects a technical issue within the spreadsheet module that was preventing data hover functionality from working correctly. The fix resolves a previous bug that masked the problem, ensuring accurate and reliable data visualization for users. This improves the overall user experience when working with charts and data in the spreadsheet.
Original PR description
### [FIX] spreadsheet: fix arguments of `onDataSetHover` The arguments of `onDataSetHover` were wrong. It was not apparent because there was another bug that caused the function to never be called. Task: [6233312](https://www.odoo.com/web#id=6233312&cids=1&menu_id=4720&action=333&active_id=2328&model=project.task&view_type=form) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves an issue where event titles were sometimes saved as "(no title)" when users quickly saved events using the alt+c keyboard shortcut. The fix ensures that all event titles are correctly saved, regardless of how the event was created, improving the user experience and data accuracy.
Original PR description
When creating an event using the quick create form from the calendar view if the user saves the record while the title is still being edited (using alt+c) the record will be saved with the default title: "(no title)" The code currently relies on the record data being up to date by the time onRecordSave is reached. However in the case of a text field, it is only saved when blurred. While there is a mechanism to blur the field when saving using a hotkey, it is completely asynchronous from the save logic of the form. To ensure all fields have comitted their data at save time, the framework has a mechanism to "request changes" which notifies all fields to update the record with their latest value and waits for them to do so. We can simply reuse this mechanism to ensure the data is up to date at recordSave time already, as we don't expect fields to have any changes after it. task-6321702
This update fixes an access error that prevented users from viewing employee type information within the payroll module. The change ensures users with the correct payroll group permissions have full access, resolving a potential disruption to payroll processes. This was identified during upgrades to version 19.3.
Original PR description
The field `employee_type_id` in models `hr.version` and `hr.employee` is used by the `hr` module. The group is overriden in `hr_payroll`, but the model can still be accessed by users without the required group `hr_payroll.group_hr_payroll_user`, triggering an `AccessError`.
To reproduce:
- On 19.3, install `hr_payroll`.
- Remove any Payroll access from the current user.
- Go to Employees > Configuration > Employee > Employee Types.
```
File "/home/odoo/src/odoo/saas-19.3/odoo/orm/models.py", line 2732, in check_field_access
raise AccessError(error_msg)
odoo.exceptions.AccessError: You do not have enough rights to access the field "employee_type_id" on Employee Contract (hr.version). Please contact your system administrator.
Operation: read
User: 6
Groups: allowed for groups 'Payroll / Assistant'
```
Found during upgrades to 19.3This update resolves an issue where the table of contents would obscure headings when the status bar was sticky. The fix dynamically adjusts the table of contents' position to avoid overlapping sticky elements, ensuring headings are always visible and easily accessible. This enhances the user experience when navigating long documents.
Original PR description
Since [1] when the `o_form_statusbar` status bar was made `sticky` the table of content scrolls to a given heading without taking it into account. Because of this, when scrolling upwards the heading ends up behind the status bar. This commit fixes this by finding top-aligned sticky elements within the closest scrollable element impacted by the table of content. Steps to reproduce: - Go to a To do note - Define some headings - Have sufficient content so that reaching a heading requires scrolling - Define a table of content with `/toc` - Click on a heading => The heading ended up behind the status bar. [1]: https://github.com/odoo/odoo/commit/a3c63413825cf3492a10ade77a2c571c4eeb33a6 task-6302762 Forward-Port-Of: odoo/odoo#270043
This update fixes an issue where Odoo was incorrectly selecting unavailable couriers from Shiprocket. The change now filters out 'blocked' couriers, ensuring only serviceable options are considered for rate calculations and shipment selection. Additionally, the system is more robust to handle potential errors in Shiprocket's data, preventing shipment delays.
Original PR description
Shiprocket provides an odablock flag in the courier serviceability response. Couriers with odablock=True are not serviceable for the requested route and should not be considered for rate calculation or selection. Before this change, Odoo selected the first courier returned by Shiprocket regardless of its ODA status. As a result, unavailable couriers could be proposed to users and selected for shipments. The fix filters out ODA-blocked couriers before evaluating available services, ensuring that only serviceable couriers are considered. Additionally, freight charge parsing is hardened to gracefully handle non-numeric values returned by Shiprocket, preventing errors during AWB assignment and price computation. FYI: Shiprocket uses odablock=False for serviceable routes and odablock=True for routes that are blocked for a given courier. opw-6288768,6152279 Forward-Port-Of: odoo/enterprise#120374
This update fixes an issue where the number of comments displayed on course slides wasn't accurately reflecting the actual number of comments. The change adjusts how comments are calculated to account for recent updates to the platform's messaging system. This ensures a more accurate and reliable view of course discussions.
Original PR description
Steps to reproduce: - Open a slide of a course in non fullscreen mode (website). - Go to the comments tab and add a comment in the chatter. - The comments count does not change in the tab. - The same thing happens when a comment is deleted. - Another way to see the incorrect counter is to add a note in the slide form view (backend). Before this change, `website_slides` used `website_message_ids` to calculate the comments. Since #138233 the old portal chatter has been replaced with the mail chatter and the way messages are displayed on the portal has changed. For example notes are no longer considered portal messages and also deleted messages should not be displayed or counted as such. This change ensures that comments calculations are based on a domain that considers those changes meaning that comments will be synced with the actual number of available comments. Forward-Port-Of: odoo/odoo#271247 Forward-Port-Of: odoo/odoo#260376
This update fixes a problem where self-order receipts lacked important company information like the logo, address, and contact details. Now, all relevant company and PoS settings are included on self-order receipts, improving customer experience and providing consistent branding.
Original PR description
Before this commit: ---------------- - Order receipts generated from self-orders were missing several company and PoS configuration details, such as the company logo, receipt address, phone number, email, and website. After this commit: ---------------- - Order receipts generated from self-orders now include all relevant company and PoS configuration details. Task-6271261 Forward-Port-Of: odoo/odoo#268789
This update resolves an issue where text entered into SelectMenu fields (like Campaign or Source) would intermittently disappear. The fix ensures the input field accurately reflects user typing, even after autocomplete suggestions are refreshed. This improves the user experience when searching within these fields.
Original PR description
Step to reproduce: 1. Install `website_link` 2. Open Website > Site > Link Tracker 3. Type in text into any pre-defined field (Campaign, Medium, Source) 4. Observe that the input is not showing all…
Step to reproduce: 1. Install `website_link` 2. Open Website > Site > Link Tracker 3. Type in text into any pre-defined field (Campaign, Medium, Source) 4. Observe that the input is not showing all the typed characters Issue: - It's randomly removing characters, for example, type "1234567890" and observe Cause: - SelectMenu updates its internal searchValue only inside the debounced onInput handler `debouncedOnInput`. When an autocomplete callback reloads choices before that debounce fires, the component rerenders with a stale searchValue and writes that outdated value back into the controlled input, overwriting newer characters already typed by the user. Solution: - Update searchValue immediately on every raw input event and keep only the search callback debounced. - Also reset searchValue to null when a required single-select is blurred while empty, so the input falls back to the selected choice label instead of staying visually cleared. opw-6000540 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#267974 Forward-Port-Of: odoo/odoo#255819
This update corrects a technical issue within the Odoo’s Danish accounting module (l10n_dk) where an account was listed twice. Removing this duplication ensures accurate financial reporting and data integrity. This change improves the reliability of financial transactions for Danish businesses using Odoo.
Original PR description
In the list 'dk_coa_7630 ', the account has been used in the list twice. Removing the duplication from the list. [Reference](https://github.com/odoo/odoo/blob/17.0/addons/l10n_dk/migrations/1.4/end-migrate.py#L14) Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270865 Forward-Port-Of: odoo/odoo#270573
This update resolves an issue where sign templates with auto-filled fields would incorrectly display placeholders instead of the actual values, or fail to generate documents. The fix ensures falsy values from auto-fields are properly preserved during the signing process, preventing errors and guaranteeing accurate document generation.
Original PR description
Version: - 19.0 Steps to reproduce: - Create a sign template with a readonly sign item linked to an auto field. - Use a reference record where the linked field value is empty or False. - Send the…
Version: - 19.0 Steps to reproduce: - Create a sign template with a readonly sign item linked to an auto field. - Use a reference record where the linked field value is empty or False. - Send the document for signing. - Complete the signing flow. Issue: - Readonly sign items linked to auto-filled values could not properly handle falsy values. Empty values could trigger the error "Some required items are not filled" and completed sign requests displayed the sign item placeholder instead of the actual auto-filled value. - completed document generation could fail when rendering falsy values for textarea sign items. Cause: - Falsy auto-filled values were ignored during constant item population and replaced by the sign item placeholder. Additionally, readonly constant items were included in required field validation and completed sign requests continued to display placeholders when the stored value was empty. - document rendering assumed sign item values were always strings for textarea sign items but when auto field is empty it value can be False. Fix: - Preserve falsy values when populating readonly constant items, exclude constant items from signer validation, and hide placeholders for empty auto-filled constant items when displaying completed sign requests. - Normalize falsy values to prevent crashes and allow completed documents to be generated correctly. Forward-Port-Of: odoo/enterprise#121255 Forward-Port-Of: odoo/enterprise#121009
This update fixes issues where mass email campaigns were failing due to incorrect server selections. Specifically, personal email servers were being inadvertently used, causing campaigns to get stuck in the queue. The changes ensure that personal servers are excluded from mass mailing selections, improving campaign delivery reliability.
Original PR description
A personal outgoing mail server is an `ir.mail_server` that belongs to one user. The system only lets that user send through it. Mass mailings do not always respect this, which can cause a few…
A personal outgoing mail server is an `ir.mail_server` that belongs to one user. The system only lets that user send through it. Mass mailings do not always respect this, which can cause a few problems: 1. Admins cannot duplicate a personal server. The copy keeps the same owner, and the rule that says one user can own only one server stops the save. 2. In *Email Marketing > Settings*, the "Dedicated Server" picker offers every server, even personal ones. If an admin picks a personal one, all campaigns get stuck. The cron job runs as Odoobot, the personal server rejects it, and the mailing stays in the queue. 3. When no dedicated server is set, the fallback selection can still land on a personal server (for example because its `from_filter` matches the sender). The cron sends through it and gets rejected. One commit per problem: 1. **mail**: duplicating a personal server now produces a copy with no owner. 2. **mass_mailing**: the picker in the settings hides personal servers. Setting an owner on a server that is already used for mass mailing now raises a clear error that names the campaign blocking the change. 3. **mass_mailing**: personal servers are skipped when the fallback selection runs, so only shared servers are considered. opw-6086077 Forward-Port-Of: odoo/odoo#271115 Forward-Port-Of: odoo/odoo#261537
15 changes
Resolved issues and error corrections
This update prevents users from incorrectly increasing refund quantities when processing gift card or e-wallet orders in the ticket screen. Previously, clicking these orderlines would lead to unintended quantity adjustments. This change ensures accurate refund processing and improves the overall reliability of the point-of-sale system.
Original PR description
Before this commit: =================== - Clicking an e-wallet or gift card orderline in the ticket screen increased the refund quantity. After this commit: ================== - Gift card and e-wallet products are now restricted from refund quantity increments in the ticket screen. Task - 6200888
This update fixes an issue where preparation times weren't accurately calculated when order stages changed and where the preparation time report incorrectly included data from all companies. The changes now ensure preparation times are correctly updated and that reports only show data for the active company, improving the accuracy of order preparation tracking.
Original PR description
Issues: - Preparation time for order lines was not computed when the preparation order stage changed. - Preparation time report aggregated orders across all companies instead of showing records for the active company only. Fixes: - Ensure preparation time is properly recomputed when the order stage changes. - Add company domain filtering to the preparation time report. Task-6250974 Forward-Port-Of: odoo/enterprise#118738
This update clarifies the appearance of the cursor when hovering over scrollbars in the HTML editor's syntax highlighting. Previously, a text cursor was shown, which was confusing. Now, the default cursor is displayed, providing a clearer visual indication that the scrollbar is for scrolling only.
Original PR description
Current behavior before PR: - When a syntax highlighting block contained a scrollbar, hovering over the scrollbar displayed a text cursor. This was misleading because the text cursor suggests text interaction, while the scrollbar is only used for scrolling. Desired behavior after PR is merged: - The default cursor is now shown when hovering over the scrollbar, avoiding this confusion. task- 6295899 Forward-Port-Of: odoo/odoo#269728
This update resolves a confusing warning message that appeared during bill editing, related to vendor history. The fix prevents temporary data discrepancies from triggering these warnings, resulting in a smoother and more intuitive editing process. The warnings are now only calculated when the bill is saved, ensuring a better user experience.
Original PR description
Abnormal bill warnings are based on vendor history read from the saved move in the db, while a bill is being edited the form uses a temporary record; after changing the vendor, that temporary value differs from the vendor still stored on the saved move. This makes the warning use the old vendor's history while showing the new vendor's name. Only compute these warnings for saved records, while editing hide them and let them be recomputed once the bill is saved. task-6263829 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270515
This update fixes an issue where the sandwich rule incorrectly excluded public holidays from leave calculations. Now, when 'Include Public Holidays as Working Day' is selected, the system accurately determines the correct leave duration, including weekend days as part of the calculation. A new test case has been added to ensure this fix.
Original PR description
Problem: When a time off type is configured with "Include Public Holidays as Working Day", the sandwich rule was still treating public holidays as non-working days. This caused the sandwiched weekend days to not be included in the leave duration. Example: Employee applies leave from May 15 (Friday, Public Holiday) to May 18 (Monday). Expected duration is 4 days since May 15 is a working day and May 16-17 (weekend) should be sandwiched. Instead, only 1 day was calculated. Fix: Now when "Include Public Holidays as Working Day" is enabled, the correct number of days are calculated in the sandwich rule. Also added a test case to verify that public holidays are correctly treated as working days during sandwich rule evaluation. Task-4570118 Forward-Port-Of: odoo/odoo#270254 Forward-Port-Of: odoo/odoo#266624
This update resolves an issue that prevented efficient processing of invoices with multiple related documents (specifically those related to Mexican tax filings - CFDI). By using a specialized index, the system now handles complex cancellation scenarios and large volumes of data more effectively, ensuring smoother invoice workflows.
Original PR description
The field `l10n_mx_edi_cfdi_origin` can contain a large number of associated UUIDs, especially in complex cancellation scenarios. The default B-tree index fails when this field exceeds 2704 bytes, which occurs after approximately 20 UUIDs. By switching to a trigram index, we avoid the entry size limit of PostgreSQL's B-tree nodes. This ensures that invoices with many related documents can be processed while maintaining efficient search performance for partial matches on this field. **Video before the fix:** https://youtu.be/24u0HbxwIH8 **Video after the fix:** https://youtu.be/sUelv1HZMvI Forward-Port-Of: odoo/enterprise#118868
This update corrects a previous issue where Odoo was incorrectly selecting unavailable couriers from Shiprocket. The fix now filters out 'blocked' couriers, ensuring only service-eligible options are considered for shipping rates and selections. Additionally, the system is more robust to handle potential errors in Shiprocket's data.
Original PR description
Shiprocket provides an odablock flag in the courier serviceability response. Couriers with odablock=True are not serviceable for the requested route and should not be considered for rate calculation or selection. Before this change, Odoo selected the first courier returned by Shiprocket regardless of its ODA status. As a result, unavailable couriers could be proposed to users and selected for shipments. The fix filters out ODA-blocked couriers before evaluating available services, ensuring that only serviceable couriers are considered. Additionally, freight charge parsing is hardened to gracefully handle non-numeric values returned by Shiprocket, preventing errors during AWB assignment and price computation. FYI: Shiprocket uses odablock=False for serviceable routes and odablock=True for routes that are blocked for a given courier. opw-6288768,6152279 Forward-Port-Of: odoo/enterprise#120374
This update corrects a technical issue within the Odoo's Danish accounting module (l10n_dk) where an account was listed twice. Removing this duplication ensures data accuracy and prevents potential errors in financial reporting. This change improves the reliability of the accounting processes for Danish businesses using Odoo.
Original PR description
In the list 'dk_coa_7630 ', the account has been used in the list twice. Removing the duplication from the list. [Reference](https://github.com/odoo/odoo/blob/17.0/addons/l10n_dk/migrations/1.4/end-migrate.py#L14) Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270865 Forward-Port-Of: odoo/odoo#270573
This fix resolves an issue where extra prices were incorrectly applied to products with 'always' attributes when creating point-of-sale combos. The update ensures that extra prices are now set on the combo creation page for 'always' attributes, aligning with how the system should calculate prices for these product variations.
Original PR description
## Steps to reproduce - Create an attribute A, of type always, with 2 values, one should have an extra price - Create an attribute B, of type never, with 2 values - Create a product that has both…
## Steps to reproduce - Create an attribute A, of type always, with 2 values, one should have an extra price - Create an attribute B, of type never, with 2 values - Create a product that has both those attributes - Create a combo with that product with both values for A - Go to the PoS and order that combo with the value that has an extra price for A - The extra price is added ## Why the fix: For variants of type always, a product is created, meaning we can chose which products of this variants to have in our combo. As we can chose this, it means that we can and should chose the extra price on the combo creation page, not on the attribute page. It does not make sense to take the attribute extra price into account, as we do not take the unit price of combo items into account, so this extra price should be set on the combo page and we should ignore the attribute's extra price if the type is "always". The variants are then considered as different products, as they should in this case. If the type of the attribute is never, we can't chose which one gets an extra price on the combo page, so we should still take the attribute's extra price in this situation, as we have no other way to set it. We need to have both an always and a never attribute in order to reproduce this bug because if we only have "always" values, the configuration of the combo item is bypassed and is undefined, so **attribute_value_ids** will be undefined in this code and we won't get any value for the extra price in this code: https://github.com/odoo/odoo/blob/c09e8b2fc24ee75495fc947924e29cf5c601506f/addons/point_of_sale/static/src/app/models/utils/compute_combo_items.js#L44-L49 We now ignore the attribute's extra price if it's type is always, otherwise, it the behavior stays the same. opw-6262431 Forward-Port-Of: odoo/odoo#270894 Forward-Port-Of: odoo/odoo#268567
This update corrects a technical issue where the system incorrectly rejected zero measurement values received from caliper devices via IoT. This ensures that zero readings are now properly recorded, providing a more complete and accurate picture of product quality. The update also includes a minor typo correction.
Original PR description
Fix a check on the IoT response that incorrectly rejected valid measurements of 0 from caliper devices Also fix a typo opw-6184669 Forward-Port-Of: odoo/enterprise#121116
This update resolves an issue where recurring plans would disappear from the website when a product's quantity was increased. The original fix only worked on the initial page load, but this change ensures the recurring plan selection remains accurate even after updates to the product's price or variant. This improves the user experience for subscription customers.
Original PR description
# Introduction note This PR fixes two bugs introduced by the same commit : https://github.com/odoo/enterprise/commit/106d70a1ef0ddbd61a74b7cac82dfce1e316beaa The original commit fixed multiple issues…
# Introduction note This PR fixes two bugs introduced by the same commit : https://github.com/odoo/enterprise/commit/106d70a1ef0ddbd61a74b7cac82dfce1e316beaa The original commit fixed multiple issues regarding the display of recurring plans when the One-time purchase option was enabled, but it also introduced new ones. Theses new issues are due to multiple new checks on `allow_one_time_sale`, but this variable only indicates that the One-time purchase option is available to the user, not that it is actually selected. So the fixes of the original commit works when first loading the page, but fails when the content of the page is updated. # Shared steps - Activate Subscriptions & eCommerce modules - Create a subscription product, enable 'Accept One-Time' and publish it on the website # Bug 1 ## How to reproduce - Add atleast two recurring plans to the product - Go to the product page on the website - Select one of the recurring plans - Increase the quantity of the product ## The problem The recurring plan selection is removed ## Cause The condition `!combination_info.allow_one_time_sale` was added on the `t-att-checked` of the recurring plan selection display. This correctly fixed the issue when first loading the page, but when the user changes the price or the variant, the recurring plan are recomputed and rerendered : https://github.com/odoo/enterprise/blob/0b408acbadb2cfcbc844521f3244a06b7ae7be22/website_sale_subscription/static/src/interactions/product_page.js#L37-L40 When that is the case, that condition blocks the proper display of the selected recurring plan. ## Proposed Solution When loading the recurring plan selection, what defines wich plan is selected is the `subscription_default_pricing_plan_id` variable, which is based on the `plan_id` value given in the request to the server : https://github.com/odoo/enterprise/blob/0b408acbadb2cfcbc844521f3244a06b7ae7be22/website_sale_subscription/models/product_template.py#L222 We make it so if no `plan_id` is sent to the server and `allow_one_time_sale` is enabled, then the server does not give back any `subscription_default_pricing_plan_id` opw-6131532 # Bug 2 ## How to reproduce - Add an attribute with values A & B for the product - Define atleast two recurring plans for the variant with attribute B - Publish the product - Go to the product page - Select the variant with attribute B ## The problem The recurring plan is not displayed. If the order of the attribute is reversed, then it works as expected. ## Cause The pricings are correcly sent to the front-end but they are not added to selection because of the check on `allow_one_time_sale` : https://github.com/odoo/enterprise/blob/0b408acbadb2cfcbc844521f3244a06b7ae7be22/website_sale_subscription/static/src/interactions/product_page.js#L42-L50 opw-6132160 Forward-Port-Of: odoo/enterprise#120873 Forward-Port-Of: odoo/enterprise#115446
This update fixes a bug in the stock valuation calculation that incorrectly displayed product values when multiple companies and currencies were involved. The fix ensures that values are accurately converted to the main company's currency (USD) for a correct total value calculation. This impacts how stock values are reported across different company setups.
Original PR description
**Steps to reproduce:** - make sure your main company (company 1) has dollars as its main currency - create second company (company 2) and a warehouse in this second company - set euro has the main…
**Steps to reproduce:** - make sure your main company (company 1) has dollars as its main currency - create second company (company 2) and a warehouse in this second company - set euro has the main currency in the company 2 From company 1: - set an exchange rate of 1$ = 0.5 eur on the euro currency - create a storable product with a cost of 10$ and an on-hand quantity of 1 From company 2: - set the cost to 10 eur and set an on-hand quantity of 1 with both company selected and company 1 as the main company selected: - open the stock view and look for your product **Current behavior:** the total value is 20$ **Expected behavior:** with conversion rate, it should be 30$ **Cause of the issue:** when computing the total value we do not apply a conversion rate from the value of the company to the main company selected https://github.com/odoo/odoo/blob/8759429547e42e9f63b15a7c80475be46ef437e2/addons/stock_account/models/product.py#L273 opw-6280108 Forward-Port-Of: odoo/odoo#270575
This update resolves a bug where overtime was incorrectly generated when using timing rules with employer tolerances. The fix ensures that attendance limits are accurately considered, preventing unnecessary overtime calculations. This improves the accuracy of employee time tracking.
Original PR description
**Version:** - 19.0 **Steps to reproduce:** - Create a rule of Timing type. - Add a tolerance for the employer. - Set the ruleset on the employee. - Add an attendance of less than the tolerance. **Issue:** - When using a Timing type rule with employer tolerance, overtime is still created even if the attendance is below the tolerance limit. **Cause:** - The timing rule calculation was missing the tolerance check that exists in the quantity rule calculation. **Fix:** - Added the missing tolerance check in the timing rule calculation. - Removed employee tolerance from view for timing rules. **Task-6064081** Forward-Port-Of: odoo/odoo#257079
This update resolves an issue where attendees received duplicate email notifications when rescheduling a meeting. The problem stemmed from a technical error in how the system handled date changes, leading to unnecessary email sends. The fix ensures that attendees only receive one notification for meeting updates.
Original PR description
Steps to reproduce: 1. Install CRM, Calendar, and Contacts. 2. Create a contact with an email address you can receive emails on. 3. Configure an outgoing email server. 4. Open a CRM lead and create a…
Steps to reproduce: 1. Install CRM, Calendar, and Contacts. 2. Create a contact with an email address you can receive emails on. 3. Configure an outgoing email server. 4. Open a CRM lead and create a meeting activity using the calendar. 5. Add the created contact as an attendee of the meeting. 6. Return to the lead and click the Reschedule button on the activity. 7. Select the same meeting and change its start date to a future date. Issue: - Attendees receive the meeting date-change email twice. Root cause: - When a calendar event linked to an activity is rescheduled, the event write syncs the new start date to the related activity through `_sync_activities`. That activity write was not marked as calendar-originated after commit https://github.com/odoo/odoo/commit/bc090486bd7810b1b0af1bae398255a2d6615f09, so `mail.activity.write` treated the updated deadline as an activity-originated change and wrote back to the same calendar event. https://github.com/odoo/odoo/blob/8cbb0fe91a35fcdb4a7e4e1a7e8afe40b1691f11/addons/calendar/models/calendar_event.py#L779 https://github.com/odoo/odoo/blob/8cbb0fe91a35fcdb4a7e4e1a7e8afe40b1691f11/addons/calendar/models/mail_activity.py#L24-L33 - This created a nested calendar event write. Both the nested write and the original write then triggered attendee date-change notifications, resulting in duplicate emails. Solution: - Pass the existing `calendar_event_meeting_update` context flag when syncing calendar event changes to linked activities. This prevents the activity sync from writing back to the event while preserving activity-to-event rescheduling. opw-6209956 Forward-Port-Of: odoo/odoo#266675
A recent update caused the Point of Sale system to incorrectly add the 'S' variant when scanning a barcode for the 'M' variant of a product with dynamic attributes. This fix ensures that the correct variant is always added, improving the accuracy of sales transactions. The change corrects a logic error in how the system handles product variants with dynamic attributes.
Original PR description
Steps to reproduce ------------------ 1. Create a product with two attributes: - Size with values S and M (Variants Creation: "Instantly") - a second attribute with a single value (Variants Creation: "Dynamically") 2. Set a different barcode on the S and the M variant. 3. Open PoS, scan the barcode of M. -> The S variant is added instead. Why the issue ------------- In 390b48a1ba24, when a product has a single-value attribute set to "dynamic", we look for the first variant that has this value and use it instead of the preselected variant. This is wrong when several variants share this value: in our case both S and M have it, so scanning M is overridden by the first variant, S. The fix ------- We now keep the preselected variant if it already has this value, and only look for or create one otherwise. opw-6272739 Forward-Port-Of: odoo/odoo#268590
6 changes
Resolved issues and error corrections
This update removes a redundant step in a test used for validating account edi invoices. Previously, the test required manually removing a bank account to prevent incorrect partner matching. With the system's improved partner identification using VAT numbers (since saas-18.3), this step is no longer needed, streamlining the testing process.
Original PR description
Since `saas-18.3`, the partner is correctly found using the VAT number, so the test no longer needs to remove `partner_1`'s bank account to avoid a wrong match. Remove the unnecessary `self.partner_1.bank_ids.unlink()` from `test_xml_ubl_au.py`. Forward-Port-Of: odoo/odoo#269993
This update fixes an issue where preparation times weren't accurately calculated when order stages changed and where the preparation time report incorrectly included data from all companies. The changes now ensure preparation times are correctly updated and the report displays data specific to the active company, improving reporting accuracy.
Original PR description
Issues: - Preparation time for order lines was not computed when the preparation order stage changed. - Preparation time report aggregated orders across all companies instead of showing records for the active company only. Fixes: - Ensure preparation time is properly recomputed when the order stage changes. - Add company domain filtering to the preparation time report. Task-6250974 Forward-Port-Of: odoo/enterprise#118738
This update clarifies the appearance of the cursor when hovering over scrollbars in the HTML editor's syntax highlighting. Previously, a text cursor was shown, which was confusing. Now, the default cursor is displayed, providing a clearer visual indication that the scrollbar is for scrolling only.
Original PR description
Current behavior before PR: - When a syntax highlighting block contained a scrollbar, hovering over the scrollbar displayed a text cursor. This was misleading because the text cursor suggests text interaction, while the scrollbar is only used for scrolling. Desired behavior after PR is merged: - The default cursor is now shown when hovering over the scrollbar, avoiding this confusion. task- 6295899 Forward-Port-Of: odoo/odoo#269728
This update resolves a confusing warning message that appeared during bill editing, related to vendor history. The fix prevents the warning from appearing while a bill is being edited, instead recomputing it when the bill is saved. This creates a smoother and less disruptive user experience.
Original PR description
Abnormal bill warnings are based on vendor history read from the saved move in the db, while a bill is being edited the form uses a temporary record; after changing the vendor, that temporary value differs from the vendor still stored on the saved move. This makes the warning use the old vendor's history while showing the new vendor's name. Only compute these warnings for saved records, while editing hide them and let them be recomputed once the bill is saved. task-6263829 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270515
This update resolves an issue that prevented efficient processing of invoices with multiple related documents (specifically those involving Mexican tax cancellations). By using a different database index, the system now handles a greater volume of invoices without performance slowdowns, ensuring smoother operations for our Mexican customers. This change improves the reliability of the l10n_mx_edi module.
Original PR description
The field `l10n_mx_edi_cfdi_origin` can contain a large number of associated UUIDs, especially in complex cancellation scenarios. The default B-tree index fails when this field exceeds 2704 bytes, which occurs after approximately 20 UUIDs. By switching to a trigram index, we avoid the entry size limit of PostgreSQL's B-tree nodes. This ensures that invoices with many related documents can be processed while maintaining efficient search performance for partial matches on this field. **Video before the fix:** https://youtu.be/24u0HbxwIH8 **Video after the fix:** https://youtu.be/sUelv1HZMvI Forward-Port-Of: odoo/enterprise#118868
This update corrects a previous issue where Odoo was incorrectly selecting unavailable couriers from Shiprocket. The change now filters out 'blocked' couriers, ensuring only valid options are considered for shipping rates and selections. Additionally, the system is more robust to handle unexpected data from Shiprocket, preventing errors in pricing.
Original PR description
Shiprocket provides an odablock flag in the courier serviceability response. Couriers with odablock=True are not serviceable for the requested route and should not be considered for rate calculation or selection. Before this change, Odoo selected the first courier returned by Shiprocket regardless of its ODA status. As a result, unavailable couriers could be proposed to users and selected for shipments. The fix filters out ODA-blocked couriers before evaluating available services, ensuring that only serviceable couriers are considered. Additionally, freight charge parsing is hardened to gracefully handle non-numeric values returned by Shiprocket, preventing errors during AWB assignment and price computation. FYI: Shiprocket uses odablock=False for serviceable routes and odablock=True for routes that are blocked for a given courier. opw-6288768,6152279 Forward-Port-Of: odoo/enterprise#120374
4 changes
Resolved issues and error corrections
This update fixes an issue where preparation times weren't accurately calculated and reports incorrectly combined data across all companies. Now, preparation times are correctly updated when order stages change, and reports only show data for the active company, leading to more reliable and accurate order management.
Original PR description
Issues: - Preparation time for order lines was not computed when the preparation order stage changed. - Preparation time report aggregated orders across all companies instead of showing records for the active company only. Fixes: - Ensure preparation time is properly recomputed when the order stage changes. - Add company domain filtering to the preparation time report. Task-6250974 Forward-Port-Of: odoo/enterprise#118738
This update fixes an issue where Odoo was incorrectly selecting unavailable couriers from Shiprocket. The change now filters out ‘blocked’ couriers, ensuring only serviceable options are considered for rate calculation and shipment selection. Additionally, the system is more robust to handle potential errors in Shiprocket’s data, preventing shipment delays.
Original PR description
Shiprocket provides an odablock flag in the courier serviceability response. Couriers with odablock=True are not serviceable for the requested route and should not be considered for rate calculation or selection. Before this change, Odoo selected the first courier returned by Shiprocket regardless of its ODA status. As a result, unavailable couriers could be proposed to users and selected for shipments. The fix filters out ODA-blocked couriers before evaluating available services, ensuring that only serviceable couriers are considered. Additionally, freight charge parsing is hardened to gracefully handle non-numeric values returned by Shiprocket, preventing errors during AWB assignment and price computation. FYI: Shiprocket uses odablock=False for serviceable routes and odablock=True for routes that are blocked for a given courier. opw-6288768,6152279 Forward-Port-Of: odoo/enterprise#120374
This update resolves a crash that occurred when users tried to view Instagram videos within Odoo. The fix now displays the video link instead of attempting to render the video as an image, ensuring a stable preview experience. This improves usability for Instagram integration.
Original PR description
Purpose ======= When we have a real on Instagram, we try to show the video as an image. When clicking on the broken image, the previewer crash. To fix that issue, we know show the link of the video in the message. Task-5491124 Forward-Port-Of: odoo/enterprise#121176 Forward-Port-Of: odoo/enterprise#113487
This update fixes an error in the generation of CFDI documents for payments made in foreign currencies. Previously, the rate used was incorrect, leading to inaccurate amounts displayed on the CFDI. The fix ensures the correct payment amount and rate are used, improving the accuracy of financial reporting for Mexican businesses.
Original PR description
The rate and payment amount shown on the CFDI document generated after updating payments was wrong when the payment was made in a foreign currency. Steps to reproduce: ------------------- * Create a journal that use USD as currency and set the rate to 20 MXN for 1 USD * Create an invoice in MXN and make sure it is set to PPD * Add any product to the invoice for 300$ and post it * Send the invoice to CFDI (a first document should be generated) * Create a payment of 15 USD in the new journal and reconcile it with the invoice * Go back to the invoice and click on "Update payments" to generate the second CFDI document > Observation: The payment document shows an amount of 300 USD with a rate of 1 instead of 15 USD with a rate of 20. Why the fix: ------------ We make sure to use the amount from the statement line when there is one. opw-5974519 Forward-Port-Of: odoo/enterprise#120934 Forward-Port-Of: odoo/enterprise#115779
10 changes
Resolved issues and error corrections
This update corrects a previous issue where Odoo was incorrectly selecting unavailable couriers from Shiprocket due to a lack of filtering. The change now ensures only serviceable couriers are considered, improving shipment accuracy and preventing errors in rate calculations. Additionally, the system is now more robust in handling potential errors from Shiprocket's data.
Original PR description
Shiprocket provides an odablock flag in the courier serviceability response. Couriers with odablock=True are not serviceable for the requested route and should not be considered for rate calculation or selection. Before this change, Odoo selected the first courier returned by Shiprocket regardless of its ODA status. As a result, unavailable couriers could be proposed to users and selected for shipments. The fix filters out ODA-blocked couriers before evaluating available services, ensuring that only serviceable couriers are considered. Additionally, freight charge parsing is hardened to gracefully handle non-numeric values returned by Shiprocket, preventing errors during AWB assignment and price computation. FYI: Shiprocket uses odablock=False for serviceable routes and odablock=True for routes that are blocked for a given courier. opw-6288768,6152279 Forward-Port-Of: odoo/enterprise#120374
This update resolves an issue where header text was too dark on mobile when the header position was set to 'Over the Content'. The fix corrects a conversion error that prevented CSS styling from applying, ensuring better color contrast and readability for users. This improves the overall user experience.
Original PR description
Steps to reproduce: - Set the header position to "Over the Content" - Set the background color to the last preset (dark) - Go to mobile view => If you are at the top of the page when opening the menu, the text is too dark to be readable. When the conversion from publicWidget to interaction was done, a mistake was made when converting HeaderGeneral. `o_top_menu_collapse_shown` was not toggled on `header#top` anymore. Therefore some css was not applied, leading to issues with the color constrasts. This commit fixes this issue by fixing the selector in dynamicContent. task-6311038 Forward-Port-Of: odoo/odoo#270560
This update resolves an issue where E-Way Bill amounts were incorrectly calculated when sales prices included tax. The fix ensures that tax is handled correctly, producing accurate amounts in both the printed E-Way Bill and the JSON data. This ensures compliance with Indian tax regulations.
Original PR description
`*` = `ewaybill_Stock, sale_stock, purchase_stock` **Steps to reproduce:** * Install `l10n_in_ewabill_stock` and `l10n_in_sale_Stock`. * Set the Default Tax Price Setting to "Tax Included". * Create…
`*` = `ewaybill_Stock, sale_stock, purchase_stock` **Steps to reproduce:** * Install `l10n_in_ewabill_stock` and `l10n_in_sale_Stock`. * Set the Default Tax Price Setting to "Tax Included". * Create a Sales Order (e.g. unit price 300, qty 600, 18% GST) and confirm the Delivery Challan/Delivery Order. * Generate an E-Way Bill from the Delivery Challan. **Observed behavior:** * The Taxable Amount and Total Invoice Amount are displayed incorrectly in the generated E-Way Bill, including both the printed document and the JSON. * The `ewaybill_price_unit` shows the tax-excluded price (e.g. 254.24) instead of the original tax-included price (300), leading to a double tax exclusion when `compute_all` processes it. **Cause:** * `_l10n_in_get_product_price_unit` in both `l10n_in_sale_stock` and `l10n_in_purchase_stock` unconditionally used `price_subtotal / qty` to compute the E-Way Bill price unit. `price_subtotal` is always tax-excluded, so for tax-included prices, the tax was already stripped. * `_l10n_in_tax_details_by_stock_move` then passed this already tax-excluded price to `compute_all` with taxes that have `price_include=True`, causing `compute_all` to strip the tax a second time (e.g. 254.24 / 1.18 = 215.46 instead of the correct 254.24). **Fix:** * Check whether any of the line's taxes have `price_include` set. If so, use `price_total / qty` (which preserves the tax-included price) so that `compute_all` can correctly extract the tax. Otherwise, continue using `price_subtotal / qty` as before. opw-6273101 Forward-Port-Of: odoo/odoo#271264 Forward-Port-Of: odoo/odoo#268504
This update fixes an issue where flexible employees couldn't request single-day leaves on public holidays. The change ensures that a request for a public holiday date is now correctly processed and counted as 1 day, aligning with multi-day leave behavior. This improves the usability of the HR holiday request feature.
Original PR description
Currently, flexible employees can request a multi-day leave spanning a public holiday when the leave type includes public holidays in duration. However, requesting the public holiday date alone is…
Currently, flexible employees can request a multi-day leave spanning a public holiday when the leave type includes public holidays in duration. However, requesting the public holiday date alone is rejected. ### **Steps to reproduce:** - Create a public holiday. - Create a time off type with "Public Holiday Included" enabled. - Select/create an employee with a flexible work schedule and its time zone must be same as admin. - Request a time off on the public holiday date only. ### **Observed Behavior:** The request is rejected because its duration is computed as 0 days. ### **Expected Behavior:** The request should be allowed and count as 1 day, consistent with the multi-day request behavior. ### **Root Cause:** At [1], a dedicated duration computation path is used for single-day leaves of flexible employees. This logic always retrieves overlapping public holidays and computes the leave duration based on the remaining intervals. As a result, a leave requested entirely on a public holiday is computed as 0 days, even when `include_public_holidays_in_duration` is enabled. [1]- https://github.com/odoo/odoo/blob/242f6d3cf7288853f163ac6986a3b7aa4279efaf/addons/hr_holidays/models/hr_leave.py#L436-L444 ### **Fix:** This commit ensures that the `include_public_holidays_in_duration` setting is taken into account when computing single-day leave durations for flexible employees **opw-6284768** Forward-Port-Of: odoo/odoo#269743
This update resolves a crash that occurred when users attempted to view Instagram videos within Odoo. The fix now displays the video link instead of the image, ensuring a smooth user experience. This improves stability and prevents the previewer from failing.
Original PR description
Purpose ======= When we have a real on Instagram, we try to show the video as an image. When clicking on the broken image, the previewer crash. To fix that issue, we know show the link of the video in the message. Task-5491124 Forward-Port-Of: odoo/enterprise#121176 Forward-Port-Of: odoo/enterprise#113487
This update resolves an issue where the due date calculation for French payroll was incorrect, specifically returning a month of 0 for November transactions. It also corrects a technical error that prevented the system from properly processing empty recordsets, improving data reliability. This ensures accurate reporting and compliance for French businesses using this module.
Original PR description
- Fix due date calculation (returned month 0 if move date was in November) - Fix ensure_one error, avoid calling _deduce_country_code() on an empty recordset opw-6293701 Forward-Port-Of: odoo/odoo#270003
This update resolves an issue where commands like `/table` were accidentally executed within code blocks in the HTML editor. The fix prevents commands and markdown shorthands from appearing inside code blocks, ensuring a cleaner and more predictable editing experience for users. This improves the stability and usability of the ToDo module.
Original PR description
### Steps to reproduce: - Go to ToDo. - Create a code block using `/code`. - Place the cursor inside the code block. - Type `/table` and select the table command. - A traceback occurs. ### Purpose of this PR: - Commands and markdown shorthands should not be available inside code blocks. However, typing `/` inside a `<pre>` opened the command palette, allowing structural commands such as `/table` to be executed and causing a traceback. Similarly, markdown shorthands such as `* ` and `1.` were still active, unexpectedly transforming code content into lists. ### This PR fixes the issue by: - Disabling the command palette when the cursor is inside a `<pre>` element. - Disabling markdown shorthands inside `<pre>` elements by registering an `is_shorthand_available_predicates` predicate. task-6292231 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270858 Forward-Port-Of: odoo/odoo#269430
This update significantly speeds up the calculation of future timesheets based on public holidays. The previous process was slow and inefficient, especially when many holidays were defined. This change optimizes the calculation, resulting in faster timesheet generation and improved system performance.
Original PR description
**Problem:** When creating a new employee, the future timesheets due to public holidays are computed. If the number of public holidays is large (i.e. if the user creates them for each year, several…
**Problem:** When creating a new employee, the future timesheets due to public holidays are computed. If the number of public holidays is large (i.e. if the user creates them for each year, several years in the future), then it takes excessively long and the action may not complete. **Cause:** The pytz method `localize` and comparing times with non-static timezones is done repeatedly and unnecessarily which becomes costly with more records. **Solution:** Only localize the time when absolutely necessary (determining the date of the leave in the calendar timezone). **Performance Stats:** |Record count|Time before|Queries before|Time after|Queries after| |------------|-----------|--------------|----------|-------------| |100 |3.1s |393 |0.8s |117 | |1,000 |22.3s |2,090 |1.5s |183 | |10,000 |Timeout |N/A |6.7s |541 | opw-6087422 Forward-Port-Of: odoo/odoo#269876 Forward-Port-Of: odoo/odoo#263953
A test within the Odoo email system failed on the pg18 database version. This fix addresses a change in how database constraints are handled, specifically a 'RESTRICT_VIOLATION' error instead of a 'FOREIGN_KEY_VIOLATION' error. The test has been updated to use a more general error type for better reliability.
Original PR description
This commit is kind of a follow up of
odoo/odoo@39cd4ea856fe00f5674f8c44b2b66cbf2705426d (in 18.0).
In a nutshell, following a standard-compliance fix (postgres/postgres@086c84b) has led to `RESTRICT_VIOLATION` being emitted in cases which formerly emitted `FOREIGN_KEY_VIOLATION`. One such case is specifically being tested for by `test_alias_domain_setup`, leading to this test failing systematically when running pg18:
psycopg2.errors.RestrictViolation: update or delete on table "mail_alias_domain" violates RESTRICT setting of foreign key constraint "mail_alias_alias_domain_id_fkey" on table "mail_alias"
DETAIL: Key (id)=(191) is referenced from table "mail_alias".
This commit updates the test to use the more generic `IntegrityError` as it's probably more than sufficient for our purposes.
Forward-Port-Of: odoo/odoo#271302This update resolves an issue where Android 14 users couldn't access their camera when uploading images through the Odoo web interface. The fix ensures users can now select photos from their device, improving usability on this popular operating system. This enhancement addresses a compatibility problem identified by Google and other developers.
Original PR description
Since Android 14 we don't have option to take a photo on clicking on file input in Chrome.
This for example will allow only images but no option "Camera"
```html
<input type="file" accept="image/*/>
```
A workaround is to use a dummy mimetype (`*/*`), example `dummy/allowAndroidCamera` The fix will be applied on image widget in addition to the original `acceptedFileExtensions` to not override the existing `accept` attribute
Linked url
- https://blog.addpipe.com/html-file-input-accept-video-camera-option-is-missing-android-14-15/
- https://stackoverflow.com/questions/77876374/html-input-type-file-not-working-to-pull-up-camera-for-pixel-android-14-comb/79163998#79163998
- https://issues.chromium.org/issues/40937303
opw-6040375
backport of https://github.com/odoo/odoo/pull/265750
Forward-Port-Of: odoo/odoo#268584
Forward-Port-Of: odoo/odoo#2668503 changes
Resolved issues and error corrections
This update corrects a previous issue where Odoo was selecting unavailable couriers from Shiprocket due to a lack of filtering. The change now excludes 'blocked' couriers, ensuring only service-eligible options are considered for shipping rates and selections. Additionally, the system is more robust to handle potential errors in Shiprocket's data.
Original PR description
Shiprocket provides an odablock flag in the courier serviceability response. Couriers with odablock=True are not serviceable for the requested route and should not be considered for rate calculation or selection. Before this change, Odoo selected the first courier returned by Shiprocket regardless of its ODA status. As a result, unavailable couriers could be proposed to users and selected for shipments. The fix filters out ODA-blocked couriers before evaluating available services, ensuring that only serviceable couriers are considered. Additionally, freight charge parsing is hardened to gracefully handle non-numeric values returned by Shiprocket, preventing errors during AWB assignment and price computation. FYI: Shiprocket uses odablock=False for serviceable routes and odablock=True for routes that are blocked for a given courier. opw-6288768,6152279 Forward-Port-Of: odoo/enterprise#120374
This update fixes an issue where product prices weren't updating correctly when changing the cost price of a product variant. The fix ensures that price calculations are accurate, preventing discrepancies in on-sale prices for products linked to cost-based pricelists. This improves the reliability of pricing within the system.
Original PR description
When we create a product variant and have a pricelist which is based on the cost price, and change the cost price, the on_sale_price doesn't update correctly. It gets delayed by one update because the product._origin isn't getting updated with the new onchanged value. Steps to Reproduce: 1.Create a pricelist and add a line with "formula" price type, and based on "cost", 2.Create a product variant, and add the pricelist just created. 3.Change the "Cost". The "On Sale Price" updates based on the value before. To fix the issue, we need to update the product._origin for standard_price just like the lst_price before computing the on_sale_price opw-5947995 Forward-Port-Of: odoo/enterprise#119470
This update resolves a crash that occurred when users attempted to view Instagram videos within Odoo. The fix now displays the video link instead of attempting to render the video as an image, ensuring a stable preview experience. This improves user satisfaction and prevents disruptions.
Original PR description
Purpose ======= When we have a real on Instagram, we try to show the video as an image. When clicking on the broken image, the previewer crash. To fix that issue, we know show the link of the video in the message. Task-5491124 Forward-Port-Of: odoo/enterprise#121176 Forward-Port-Of: odoo/enterprise#113487
21 changes
Resolved issues and error corrections
A recent payroll upgrade introduced an error preventing users from accessing the Wage Types configuration in Odoo. This change required restoring the action's update functionality to ensure the system correctly reflects the latest payroll structure settings. This fix resolves a critical issue impacting Swiss payroll functionality.
Original PR description
The Wage Types action record salary rules belonging to the CHMONTHLYELM payroll structure. During the payroll refactoring, salary rules were changed to support multiple payroll structures. in the…
The Wage Types action record salary rules belonging to the CHMONTHLYELM payroll structure.
During the payroll refactoring, salary rules were changed to support multiple payroll structures. in the 19.4 version here c2f18f3
Where struct_id M20 field is changes to [M2m](https://github.com/odoo/upgrade/pull/10294/changes#diff-541246af074f8ac598b0a274ef9861f5fe974e6ded22e906c3d35adecb284e8cR51) struct_ids
Opening Payroll > Configuration > Company > Wage Types will cause the issue as the action has not updated which Failes the [ci/upgrade_enterprise](https://runbot.odoo.com/runbot/batch/2598248/build/115031148)
Steps to reproduce.
- Create a database on saas-19.3.
- Install l10n_ch_hr_payroll.
- Upgrade the database to master.
- Open Payroll > Configuration > Company > Wage Types.
- Error raise error(message % (*args, self.field_expr, self.operator, self.value)) ValueError: Invalid field hr.salary.rule.struct_id in condition
('struct_id.code', '=', 'CHMONTHLYELM')
The issue will directly reproduce in the runbot maste too installed the l10n_ch_hr_payroll module and access the wage type.
```
Adding menu ('l10n_ch_hr_payroll.menu_l10n_ch_wage_types', 1598, 'Payroll > Configuration > Company > Wage Types', 2337) to the failing menus
Traceback (most recent call last):
File "[/data/build/odoo/odoo/orm/domains.py](https://github.com/odoo/odoo/blob/2fb276668c824d6fe759a7c51f9ef10677532508/odoo/orm/domains.py#L964)", line 964, in __get_field
field = model._fields[field_name]
~~~~~~~~~~~~~^^^^^^^^^^^^
KeyError: 'struct_id'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "[/data/build/upgrade/migrations/base/tests/test_mock_crawl.py](https://github.com/odoo/upgrade/blob/07bec6a1031093cf001642f8df21e40421cce3be/migrations/base/tests/test_mock_crawl.py#L346)", line 346, in crawl_menu
self.mock_action(action_vals)
File "[/data/build/upgrade/migrations/base/tests/test_mock_crawl.py](https://github.com/odoo/upgrade/blob/07bec6a1031093cf001642f8df21e40421cce3be/migrations/base/tests/test_mock_crawl.py#L377)", line 377, in mock_action
return self.mock_act_window(action)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "[/data/build/upgrade/migrations/base/tests/test_mock_crawl.py](https://github.com/odoo/upgrade/blob/07bec6a1031093cf001642f8df21e40421cce3be/migrations/base/tests/test_mock_crawl.py#L537)", line 537, in mock_act_window
mock_method(model, view, fields_list, domain, group_by)
File "[/data/build/upgrade/migrations/base/tests/test_mock_crawl.py](https://github.com/odoo/upgrade/blob/07bec6a1031093cf001642f8df21e40421cce3be/migrations/base/tests/test_mock_crawl.py#L675)", line 675, in mock_view_list
return self.mock_view_tree(model, view, fields_list, domain, group_by)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "[/data/build/upgrade/migrations/base/tests/test_mock_crawl.py](https://github.com/odoo/upgrade/blob/07bec6a1031093cf001642f8df21e40421cce3be/migrations/base/tests/test_mock_crawl.py#L688)", line 688, in mock_view_tree
self.mock_web_search_read(model, view, [domain], fields_list)
File "[/data/build/upgrade/migrations/base/tests/test_mock_crawl.py](https://github.com/odoo/upgrade/blob/07bec6a1031093cf001642f8df21e40421cce3be/migrations/base/tests/test_mock_crawl.py#L722)", line 722, in mock_web_search_read
data = model.search_read(domain=domain, fields=fields_list, limit=80, order=filter_order(model))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "[/data/build/odoo/odoo/orm/models.py](https://github.com/odoo/odoo/blob/2fb276668c824d6fe759a7c51f9ef10677532508/odoo/orm/models.py#L5187)", line 5187, in search_read
records = self.search_fetch(domain or [], fields, offset=offset, limit=limit, order=order)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "[/data/build/odoo/odoo/orm/models.py](https://github.com/odoo/odoo/blob/2fb276668c824d6fe759a7c51f9ef10677532508/odoo/orm/models.py#L1462)", line 1462, in search_fetch
query = self._search(domain, offset=offset, limit=limit, order=order or self._order)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "[/data/build/odoo/odoo/orm/models.py](https://github.com/odoo/odoo/blob/2fb276668c824d6fe759a7c51f9ef10677532508/odoo/orm/models.py#L4773)", line 4773, in _search
domain = domain.optimize_full(self)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "[/data/build/odoo/odoo/orm/domains.py](https://github.com/odoo/odoo/blob/2fb276668c824d6fe759a7c51f9ef10677532508/odoo/orm/domains.py#L472)", line 472, in optimize_full
return self._optimize(model, OptimizationLevel.FULL)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "[/data/build/odoo/odoo/orm/domains.py](https://github.com/odoo/odoo/blob/2fb276668c824d6fe759a7c51f9ef10677532508/odoo/orm/domains.py#L486)", line 486, in _optimize
previous, domain = domain, domain._optimize_step(model, next_level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "[/data/build/odoo/odoo/orm/domains.py](https://github.com/odoo/odoo/blob/2fb276668c824d6fe759a7c51f9ef10677532508/odoo/orm/domains.py#L670)", line 670, in _optimize_step
children = self._flatten(child._optimize(model, level) for child in self.children)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "[/data/build/odoo/odoo/orm/domains.py](https://github.com/odoo/odoo/blob/2fb276668c824d6fe759a7c51f9ef10677532508/odoo/orm/domains.py#L628)", line 628, in _flatten
for child in children:
File "[/data/build/odoo/odoo/orm/domains.py](https://github.com/odoo/odoo/blob/2fb276668c824d6fe759a7c51f9ef10677532508/odoo/orm/domains.py#L670)", line 670, in <genexpr>
children = self._flatten(child._optimize(model, level) for child in self.children)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "[/data/build/odoo/odoo/orm/domains.py](https://github.com/odoo/odoo/blob/2fb276668c824d6fe759a7c51f9ef10677532508/odoo/orm/domains.py#L486)", line 486, in _optimize
previous, domain = domain, domain._optimize_step(model, next_level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "[/data/build/odoo/odoo/orm/domains.py](https://github.com/odoo/odoo/blob/2fb276668c824d6fe759a7c51f9ef10677532508/odoo/orm/domains.py#L988)", line 988, in _optimize_step
field, property_name = self.__get_field(model)
^^^^^^^^^^^^^^^^^^^^^^^
File "[/data/build/odoo/odoo/orm/domains.py](https://github.com/odoo/odoo/blob/2fb276668c824d6fe759a7c51f9ef10677532508/odoo/orm/domains.py#L966)", line 966, in __get_field
self._raise("Invalid field %s.%s", model._name, field_name)
File "[/data/build/odoo/odoo/orm/domains.py](https://github.com/odoo/odoo/blob/2fb276668c824d6fe759a7c51f9ef10677532508/odoo/orm/domains.py#L951)", line 951, in _raise
raise error(message % (*args, self.field_expr, self.operator, self.value))
ValueError: Invalid field hr.salary.rule.struct_id in condition ('struct_id.code', '=', 'CHMONTHLYELM')
2026-06-22 12:02:29 [ERROR](https://github.com/odoo/upgrade-util/blob/f3431df77099e3df9299b9d6fb1ea001796c176c/src/testing.py#L483)
FAIL: TestCrawler.test_check
Traceback (most recent call last):
File "[/data/build/upgrade-util/src/testing.py](https://github.com/odoo/upgrade-util/blob/f3431df77099e3df9299b9d6fb1ea001796c176c/src/testing.py#L483)", line 483, in test_check
self.check(value)
File "[/data/build/upgrade/migrations/base/tests/test_mock_crawl.py](https://github.com/odoo/upgrade/blob/07bec6a1031093cf001642f8df21e40421cce3be/migrations/base/tests/test_mock_crawl.py#L230)", line 230, in check
self.assertFalse(diff, msg)
AssertionError: [('l10n_ch_hr_payroll.menu_l10n_ch_wage_types', 1598, 'Payroll > Configuration > Company > Wage Types', 2337)] is not false : At least one menu or view working before upgrade is not working after upgrade.
```
Soln:- Update the action with the correct field.
ref :- https://runbot.odoo.com/runbot/batch/2598248/build/115031148This update fixes a bug where rental order PDFs didn't show the pickup and return dates. The fix adds the necessary date fields to the PDF report, ensuring consistent information between the portal and the printed sales orders. This improves clarity for customers receiving rental order details.
Original PR description
**Problem:** On a rental order, the sales order / quotation PDF no longer shows the pickup and return dates. The line description only displays the rental duration (e.g. "2 Days"), so the actual…
**Problem:** On a rental order, the sales order / quotation PDF no longer shows the pickup and return dates. The line description only displays the rental duration (e.g. "2 Days"), so the actual dates are missing from the printout. **Steps to reproduce:** 1. Create a rental order with a rentable product and pickup/return dates 2. Print the order (Print > Quotation / Order) 3. Observe the PDF shows only the duration, with no pickup/return dates **Current behavior:** Neither the rental dates (removed from the description) nor any pickup/return field appear on the PDF. **Expected behavior:** The pickup and return dates are shown on the rental order PDF. **Cause of the issue:** The rental line description was intentionally reduced to only the duration (`_get_rental_duration_description`), the actual dates being meant to appear as dedicated Pickup/Return fields. This was added to the customer portal (`sale_rental_portal_details` inherits `sale.sale_order_portal_content`) but the equivalent was never added to the `sale.report_saleorder_document` PDF report, so the dates disappeared from the printout. **Fix:** Inherit the sale order report to render the order-level pickup and return dates for rental orders, mirroring the existing portal presentation so the PDF and the portal stay consistent. opw-6268640 Forward-Port-Of: odoo/enterprise#119736
A bug preventing users from adding cover images to Knowledge articles has been resolved. The issue stemmed from a missing callback function during the upload process, causing the upload to fail. This update ensures cover images can now be successfully added, improving the article creation workflow.
Original PR description
Steps to reproduce: 1. Install Knowledge. 2. Create an article. 3. Open the more actions menu. 4. Click "Add Cover". 5. Upload a cover image. Issue: - The upload crashes with the following traceback:…
Steps to reproduce: 1. Install Knowledge. 2. Create an article. 3. Open the more actions menu. 4. Click "Add Cover". 5. Upload a cover image. Issue: - The upload crashes with the following traceback: `Uncaught Promise > this.props.setAbortUploadsCallback is not a function` Cause: - `KnowledgeCoverSelector` extends the html_editor `ImageSelector`, whose upload flow registers an abort callback through setAbortUploadsCallback. The generic MediaDialog provides this callback, but KnowledgeCoverDialog renders KnowledgeCoverSelector directly and did not pass it. As a result, the inherited upload flow called a missing prop. Solution: - Pass setAbortUploadsCallback from KnowledgeCoverDialog to KnowledgeCoverSelector and abort pending uploads when the cover dialog is discarded. Alternative approach: - Make ImageSelector tolerate callers that do not provide setAbortUploadsCallback by calling it with optional chaining. opw-6176716 Forward-Port-Of: odoo/enterprise#121162 Forward-Port-Of: odoo/enterprise#116906
This update fixes an issue preventing users from accessing payslip lists within the employee departure process. The changes include making fields read-only to prevent unintended modifications and relocating currency data to improve data handling. This ensures accurate payslip access and avoids errors.
Original PR description
Bug 1: In the departure tab of the Employee, you can't open the payslip list Fix: Added a check to get the correct departure id depending on the model we are in Bug 2: You can select payslips for other employees than the departing employee and the payslips list is not affected Fix: made fields `l10n_be_payslip_n_ids` and `l10n_be_payslip_n1_ids` readonly so they can't be modified in the UI without being saved Bug 3: You get an error because you can't read `currency_id` when opening n payslips (happens when the monetary fields are shown in the list) Fix: moved the `currency_id` to be inside the list instead of the parent form task-id: 6265648 Forward-Port-Of: odoo/enterprise#119402
This update resolves an issue preventing the 'Send to SII' option from appearing on Chilean vendor bills. The fix adjusts internal settings to correctly display this functionality, ensuring accurate electronic invoice submission for Chilean businesses. This ensures compliance with local tax regulations.
Original PR description
**Steps to reproduce:** * Install the **l10n_cl_edi** module. * Go to **Accounting → Configuration → CAFs**, create a new CAF, and upload a valid CAF…
**Steps to reproduce:** * Install the **l10n_cl_edi** module. * Go to **Accounting → Configuration → CAFs**, create a new CAF, and upload a valid CAF [XML](https://www.odoo.com/mail/message/1097235975) file. * Create a new **Purchase Journal** with **Use Documents** enabled. * Create a vendor bill using this journal. * Set the **Document Type** to **46 - Liquidación-Factura Electrónica**. * Confirm the vendor bill. **Observed behavior:** * The Send button is not visible on the confirmed vendor bill despite the DTE being generated and `l10n_cl_dte_status` being set to `not_sent`. **Cause:** * `_compute_display_send_button` in `account` only returns `True` for sale documents (`is_sale_document()`), so the "Send" button — which opens the Send & Print dialog containing the "Send to SII" option — was never shown on vendor bills. * `_get_move_constraints` in `account.move.send` unconditionally adds a `not_sale_document` constraint for non-sale documents, blocking the Send & Print dialog from processing vendor bills even if the button were visible. * The cron's `cron_run_sii_workflow` only processes moves with `l10n_cl_dte_status = 'ask_for_status'`, skipping moves still in `not_sent` state. **Fix:** * Override `_compute_display_send_button` in `l10n_cl_edi` to also show the "Send" button on posted moves with `l10n_cl_dte_status == 'not_sent'`, matching the pattern used by `l10n_br_edi`. * Override `_get_move_constraints` in `l10n_cl_edi` to remove the `not_sale_document` constraint for Chilean purchase documents with `not_sent` status, matching the pattern used by `l10n_br_edi`. **REF** During this [refactor](https://github.com/odoo/enterprise/pull/103427/changes/f5617ecf7584cf019897408df94b002622f48d9d), these two methods were inadvertently missed and were not overridden opw-6300571 Forward-Port-Of: odoo/enterprise#121233 Forward-Port-Of: odoo/enterprise#120818
This update significantly speeds up how Odoo retrieves document access permissions, particularly for the 'my counters' route. By switching to a subquery, the system now utilizes an index more efficiently, resulting in a much faster response time for users accessing documents. This improves overall performance and user experience.
Original PR description
The '/my/counters' route is hit a lot of times on big databases like odoo.com One thing it does is a `self.env['documents.document].search_count([])` With this commit, we use a subquery for the…
The '/my/counters' route is hit a lot of times on big databases like odoo.com
One thing it does is a `self.env['documents.document].search_count([])`
With this commit, we use a subquery for the folder access instead of the current LEFT JOIN.
This ok since the number of folders is typically small compared to regular documents and the query is fast since it can use the index on 'type'
Before as portal user
------
2x Seq Scan
```
Aggregate (cost=1900290.73..1900290.74 rows=1 width=8) (actual time=282.271..282.276 rows=1 loops=1)
Buffers: shared hit=66629
-> Hash Left Join (cost=41649.94..1900044.55 rows=98472 width=0) (actual time=184.202..282.267 rows=3 loops=1)
Hash Cond: (documents_document.folder_id = documents_document__folder_id.id)
Filter: ((hashed SubPlan 2) OR ((documents_document.owner_id = 6) AND ((documents_document.shortcut_document_id IS NULL) OR (documents_document.shortcut_document_owner_id = 6))) OR (((documents_document.access_via_link)::text = ANY ('{edit,view}'::text[])) AND (documents_document.folder_id IS NOT NULL) AND ((hashed SubPlan 4) OR ((documents_document__folder_id.owner_id = 6) AND ((documents_document__folder_id.shortcut_document_id IS NULL) OR (documents_document__folder_id.shortcut_document_owner_id = 6)))) AND (documents_document.is_access_via_link_hidden IS NOT TRUE)))
Rows Removed by Filter: 28085
Buffers: shared hit=66629
-> Seq Scan on documents_document (cost=0.00..1857903.54 rows=187073 width=26) (actual time=0.022..109.288 rows=28088 loops=1)
Filter: ((active IS TRUE) AND ((hashed SubPlan 2) OR ((owner_id = 6) AND ((shortcut_document_id IS NULL) OR (shortcut_document_owner_id = 6))) OR (((access_via_link)::text = ANY ('{edit,view}'::text[])) AND (folder_id IS NOT NULL) AND (is_access_via_link_hidden IS NOT TRUE))))
Rows Removed by Filter: 342576
Buffers: shared hit=33313
SubPlan 2
-> Nested Loop (cost=0.85..357.41 rows=99 width=4) (actual time=0.008..0.009 rows=0 loops=2)
Buffers: shared hit=6
-> Index Scan using documents_access__partner_id_index on documents_access (cost=0.43..105.55 rows=103 width=9) (actual time=0.008..0.008 rows=0 loops=2)
Index Cond: (partner_id = 7)
Filter: ((expiration_date IS NULL) OR (expiration_date >= '2026-06-18 10:16:38'::timestamp without time zone))
Buffers: shared hit=6
-> Index Scan using documents_document_pkey on documents_document documents_access__document_id (cost=0.42..2.44 rows=1 width=9) (never executed)
Index Cond: (id = documents_access.document_id)
Filter: (((access_via_link)::text <> 'none'::text) OR ((documents_access.role)::text = ANY ('{view,edit}'::text[])))
-> Hash (cost=37016.64..37016.64 rows=370664 width=16) (actual time=164.521..164.521 rows=370664 loops=1)
Buckets: 524288 Batches: 1 Memory Usage: 17824kB
Buffers: shared hit=33310
-> Seq Scan on documents_document documents_document__folder_id (cost=0.00..37016.64 rows=370664 width=16) (actual time=0.005..100.491 rows=370664 loops=1)
Buffers: shared hit=33310
SubPlan 4
-> Nested Loop (cost=0.85..357.41 rows=99 width=4) (actual time=0.003..0.003 rows=0 loops=1)
Buffers: shared hit=3
-> Index Scan using documents_access__partner_id_index on documents_access documents_access_1 (cost=0.43..105.55 rows=103 width=9) (actual time=0.002..0.003 rows=0 loops=1)
Index Cond: (partner_id = 7)
Filter: ((expiration_date IS NULL) OR (expiration_date >= '2026-06-18 10:16:38'::timestamp without time zone))
Buffers: shared hit=3
-> Index Scan using documents_document_pkey on documents_document documents_access__document_id_1 (cost=0.42..2.44 rows=1 width=9) (never executed)
Index Cond: (id = documents_access_1.document_id)
Filter: (((access_via_link)::text <> 'none'::text) OR ((documents_access_1.role)::text = ANY ('{view,edit}'::text[])))
Planning:
Buffers: shared hit=69
Planning Time: 1.708 ms
Execution Time: 282.344 ms
```
After as portal user
-----
Only 1x Seq Scan
```
Aggregate (cost=2004948.33..2004948.34 rows=1 width=8) (actual time=116.161..116.165 rows=1 loops=1)
Buffers: shared hit=37942
-> Seq Scan on documents_document (cost=145660.16..2004490.36 rows=183187 width=0) (actual time=24.635..116.155 rows=3 loops=1)
Filter: ((active IS TRUE) AND ((hashed SubPlan 2) OR ((owner_id = 6) AND ((shortcut_document_id IS NULL) OR (shortcut_document_owner_id = 6))) OR (((access_via_link)::text = ANY ('{edit,view}'::text[])) AND (hashed SubPlan 5) AND (is_access_via_link_hidden IS NOT TRUE))))
Rows Removed by Filter: 370661
Buffers: shared hit=37942
SubPlan 2
-> Nested Loop (cost=0.85..357.41 rows=99 width=4) (actual time=0.008..0.009 rows=0 loops=1)
Buffers: shared hit=3
-> Index Scan using documents_access__partner_id_index on documents_access (cost=0.43..105.55 rows=103 width=9) (actual time=0.008..0.008 rows=0 loops=1)
Index Cond: (partner_id = 7)
Filter: ((expiration_date IS NULL) OR (expiration_date >= '2026-06-18 10:15:10'::timestamp without time zone))
Buffers: shared hit=3
-> Index Scan using documents_document_pkey on documents_document documents_access__document_id (cost=0.42..2.44 rows=1 width=9) (never executed)
Index Cond: (id = documents_access.document_id)
Filter: (((access_via_link)::text <> 'none'::text) OR ((documents_access.role)::text = ANY ('{view,edit}'::text[])))
SubPlan 5
-> Index Scan using documents_document__type_index on documents_document documents_document_1 (cost=0.42..145625.73 rows=13772 width=4) (actual time=11.688..11.689 rows=0 loops=1)
Index Cond: ((type)::text = 'folder'::text)
Filter: ((hashed SubPlan 4) OR ((owner_id = 6) AND ((shortcut_document_id IS NULL) OR (shortcut_document_owner_id = 6))))
Rows Removed by Filter: 28198
Buffers: shared hit=4629
SubPlan 4
-> Nested Loop (cost=0.85..357.41 rows=99 width=4) (actual time=0.002..0.002 rows=0 loops=1)
Buffers: shared hit=3
-> Index Scan using documents_access__partner_id_index on documents_access documents_access_1 (cost=0.43..105.55 rows=103 width=9) (actual time=0.001..0.002 rows=0 loops=1)
Index Cond: (partner_id = 7)
Filter: ((expiration_date IS NULL) OR (expiration_date >= '2026-06-18 10:15:10'::timestamp without time zone))
Buffers: shared hit=3
-> Index Scan using documents_document_pkey on documents_document documents_access__document_id_1 (cost=0.42..2.44 rows=1 width=9) (never executed)
Index Cond: (id = documents_access_1.document_id)
Filter: (((access_via_link)::text <> 'none'::text) OR ((documents_access_1.role)::text = ANY ('{view,edit}'::text[])))
Planning:
Buffers: shared hit=56
Planning Time: 1.544 ms
Execution Time: 116.216 ms
```
Before as internal user
--------
```
Aggregate (cost=1902165.43..1902165.44 rows=1 width=8) (actual time=332.919..332.925 rows=1 loops=1)
Buffers: shared hit=69223 read=370
-> Hash Left Join (cost=41649.94..1901908.04 rows=102955 width=0) (actual time=176.179..332.325 rows=10040 loops=1)
Hash Cond: (documents_document.folder_id = documents_document__folder_id.id)
Filter: ((hashed SubPlan 2) OR ((documents_document.owner_id = 1054906) AND ((documents_document.shortcut_document_id IS NULL) OR (documents_document.shortcut_document_owner_id = 1054906))) OR (((documents_document.access_internal)::text = ANY ('{view,edit}'::text[])) AND ((documents_document.company_id = 1) OR (documents_document.company_id IS NULL))) OR (((documents_document.access_via_link)::text = ANY ('{view,edit}'::text[])) AND (documents_document.folder_id IS NOT NULL) AND ((hashed SubPlan 4) OR ((documents_document__folder_id.owner_id = 1054906) AND ((documents_document__folder_id.shortcut_document_id IS NULL) OR (documents_document__folder_id.shortcut_document_owner_id = 1054906))) OR (((documents_document__folder_id.access_internal)::text = ANY ('{view,edit}'::text[])) AND ((documents_document__folder_id.company_id = 1) OR (documents_document__folder_id.company_id IS NULL)))) AND (documents_document.is_access_via_link_hidden IS NOT TRUE)))
Rows Removed by Filter: 27228
Buffers: shared hit=69223 read=370
-> Seq Scan on documents_document (cost=0.00..1859756.86 rows=190950 width=35) (actual time=15.029..155.718 rows=37268 loops=1)
Filter: ((active IS TRUE) AND ((hashed SubPlan 2) OR ((owner_id = 1054906) AND ((shortcut_document_id IS NULL) OR (shortcut_document_owner_id = 1054906))) OR (((access_internal)::text = ANY ('{view,edit}'::text[])) AND ((company_id = 1) OR (company_id IS NULL))) OR (((access_via_link)::text = ANY ('{view,edit}'::text[])) AND (folder_id IS NOT NULL) AND (is_access_via_link_hidden IS NOT TRUE))))
Rows Removed by Filter: 333396
Buffers: shared hit=33931 read=370
SubPlan 2
-> Nested Loop (cost=0.85..357.41 rows=99 width=4) (actual time=0.155..7.920 rows=148 loops=2)
Buffers: shared hit=1612 read=370
-> Index Scan using documents_access__partner_id_index on documents_access (cost=0.43..105.55 rows=103 width=9) (actual time=0.110..3.448 rows=200 loops=2)
Index Cond: (partner_id = 1800102)
Filter: ((expiration_date IS NULL) OR (expiration_date >= '2026-06-18 12:17:29'::timestamp without time zone))
Buffers: shared hit=192 read=190
-> Index Scan using documents_document_pkey on documents_document documents_access__document_id (cost=0.42..2.44 rows=1 width=9) (actual time=0.022..0.022 rows=1 loops=400)
Index Cond: (id = documents_access.document_id)
Filter: (((access_via_link)::text <> 'none'::text) OR ((documents_access.role)::text = ANY ('{view,edit}'::text[])))
Rows Removed by Filter: 0
Buffers: shared hit=1420 read=180
-> Hash (cost=37016.64..37016.64 rows=370664 width=25) (actual time=157.822..157.823 rows=370664 loops=1)
Buckets: 524288 Batches: 1 Memory Usage: 21336kB
Buffers: shared hit=33310
-> Seq Scan on documents_document documents_document__folder_id (cost=0.00..37016.64 rows=370664 width=25) (actual time=0.005..96.730 rows=370664 loops=1)
Buffers: shared hit=33310
SubPlan 4
-> Nested Loop (cost=0.85..357.41 rows=99 width=4) (actual time=0.019..0.372 rows=148 loops=1)
Buffers: shared hit=991
-> Index Scan using documents_access__partner_id_index on documents_access documents_access_1 (cost=0.43..105.55 rows=103 width=9) (actual time=0.005..0.078 rows=200 loops=1)
Index Cond: (partner_id = 1800102)
Filter: ((expiration_date IS NULL) OR (expiration_date >= '2026-06-18 12:17:29'::timestamp without time zone))
Buffers: shared hit=191
-> Index Scan using documents_document_pkey on documents_document documents_access__document_id_1 (cost=0.42..2.44 rows=1 width=9) (actual time=0.001..0.001 rows=1 loops=200)
Index Cond: (id = documents_access_1.document_id)
Filter: (((access_via_link)::text <> 'none'::text) OR ((documents_access_1.role)::text = ANY ('{view,edit}'::text[])))
Rows Removed by Filter: 0
Buffers: shared hit=800
Planning:
Buffers: shared hit=69 read=8
Planning Time: 2.116 ms
Execution Time: 333.013 ms
```
After as internal user
--------
```
Aggregate (cost=2006950.17..2006950.18 rows=1 width=8) (actual time=157.117..157.121 rows=1 loops=1)
Buffers: shared hit=39918
-> Seq Scan on documents_document (cost=145798.74..2006482.26 rows=187165 width=0) (actual time=16.595..156.590 rows=10040 loops=1)
Filter: ((active IS TRUE) AND ((hashed SubPlan 2) OR ((owner_id = 1054906) AND ((shortcut_document_id IS NULL) OR (shortcut_document_owner_id = 1054906))) OR (((access_internal)::text = ANY ('{view,edit}'::text[])) AND ((company_id = 1) OR (company_id IS NULL))) OR (((access_via_link)::text = ANY ('{view,edit}'::text[])) AND (hashed SubPlan 5) AND (is_access_via_link_hidden IS NOT TRUE))))
Rows Removed by Filter: 360624
Buffers: shared hit=39918
SubPlan 2
-> Nested Loop (cost=0.85..357.41 rows=99 width=4) (actual time=0.019..1.016 rows=148 loops=1)
Buffers: shared hit=991
-> Index Scan using documents_access__partner_id_index on documents_access (cost=0.43..105.55 rows=103 width=9) (actual time=0.012..0.262 rows=200 loops=1)
Index Cond: (partner_id = 1800102)
Filter: ((expiration_date IS NULL) OR (expiration_date >= '2026-06-18 12:16:29'::timestamp without time zone))
Buffers: shared hit=191
-> Index Scan using documents_document_pkey on documents_document documents_access__document_id (cost=0.42..2.44 rows=1 width=9) (actual time=0.004..0.004 rows=1 loops=200)
Index Cond: (id = documents_access.document_id)
Filter: (((access_via_link)::text <> 'none'::text) OR ((documents_access.role)::text = ANY ('{view,edit}'::text[])))
Rows Removed by Filter: 0
Buffers: shared hit=800
SubPlan 5
-> Index Scan using documents_document__type_index on documents_document documents_document_1 (cost=0.42..145763.43 rows=14124 width=4) (actual time=0.429..14.916 rows=4625 loops=1)
Index Cond: ((type)::text = 'folder'::text)
Filter: ((hashed SubPlan 4) OR ((owner_id = 1054906) AND ((shortcut_document_id IS NULL) OR (shortcut_document_owner_id = 1054906))) OR (((access_internal)::text = ANY ('{view,edit}'::text[])) AND ((company_id = 1) OR (company_id IS NULL))))
Rows Removed by Filter: 23573
Buffers: shared hit=5617
SubPlan 4
-> Nested Loop (cost=0.85..357.41 rows=99 width=4) (actual time=0.007..0.390 rows=148 loops=1)
Buffers: shared hit=991
-> Index Scan using documents_access__partner_id_index on documents_access documents_access_1 (cost=0.43..105.55 rows=103 width=9) (actual time=0.003..0.074 rows=200 loops=1)
Index Cond: (partner_id = 1800102)
Filter: ((expiration_date IS NULL) OR (expiration_date >= '2026-06-18 12:16:29'::timestamp without time zone))
Buffers: shared hit=191
-> Index Scan using documents_document_pkey on documents_document documents_access__document_id_1 (cost=0.42..2.44 rows=1 width=9) (actual time=0.001..0.001 rows=1 loops=200)
Index Cond: (id = documents_access_1.document_id)
Filter: (((access_via_link)::text <> 'none'::text) OR ((documents_access_1.role)::text = ANY ('{view,edit}'::text[])))
Rows Removed by Filter: 0
Buffers: shared hit=800
Planning:
Buffers: shared hit=56
Planning Time: 1.569 ms
Execution Time: 157.171 ms
```
portal user
before https://explain.dalibo.com/plan/e1e755fg7bb26a21
after https://explain.dalibo.com/plan/hb5fa1d201ff164g
internal user with few documents access
before https://explain.dalibo.com/plan/f753bf2aa244dg63
after https://explain.dalibo.com/plan/538dg5ecb120ch84
internal user with *lots* of documents access
before https://explain.dalibo.com/plan/cf76h84537f7ge4a
after https://explain.dalibo.com/plan/45317a5e3168c5bc
Forward-Port-Of: odoo/enterprise#120991This update resolves an issue impacting how Odoo calculates sick leave payments, specifically related to the 'DPV' (days of paid vacation) calculation for employees with extended absences. The fix ensures accurate assimilation of sickness periods, particularly when transitioning between long and partial absences, improving payroll accuracy and compliance. The changes primarily affect the Be payroll module.
Original PR description
Forward-Port-Of: odoo/enterprise#121086 Forward-Port-Of: odoo/enterprise#120868
This update resolves a critical issue where VoIP registration would fail due to idle sessions, causing error dialogs and preventing users from making calls. The fix ensures that registration requests are properly handled and retried, preventing indefinite waiting and ensuring reliable VoIP 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#120487
Forward-Port-Of: odoo/enterprise#119701This update resolves an issue where changing multiple project names didn't update the associated folder names. The fix ensures that when users edit project names, the linked folder names are automatically updated, streamlining project management. This prevents inconsistencies and ensures data accuracy.
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 Forward-Port-Of: odoo/enterprise#120654 Forward-Port-Of: odoo/enterprise#119060
This update resolves an issue where manually added by-products on manufacturing orders caused errors when closing production in the shopfloor view. The fix ensures that serial numbers are correctly handled for by-products created outside of the standard BOM definition, preventing user errors and improving production workflow.
Original PR description
**Issue** Adding a serial-tracked by-product manually on a Manufacturing Order whose BOM does not define it, can lead to inconsistencies when assigning serial numbers in the shopfloor application.…
**Issue** Adding a serial-tracked by-product manually on a Manufacturing Order whose BOM does not define it, can lead to inconsistencies when assigning serial numbers in the shopfloor application. **Steps to reproduce** - Activate by-product in the settings - Create a product with an empty BOM (final product) - Create another product tracked by serial number (by-product) - Create and confirm a MO for the final product with 1 unit of the by-product - Go to Miscellaneaous -> operation Type -> shopfloor - Activate the option "Pre fill lot/serial numbers in shop floor" - Return to the MO and open the shopfloor view - Click on the '+' button next to the by-product and assign a serial number - Try to close the production -> A user error is raised stating that the by-product requires a serial number. **Cause** When the by-product is added manually on the MO, a stock move is created with an initial move line that does not contain any serial number. Later, when assigning a serial number from the shopfloor view: https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/mrp_workorder/models/stock_move.py#L121-L122 a new move line containing the serial number is created: https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/mrp_workorder/models/stock_move.py#L116-L119 However, the original empty move line is not removed (the issue): https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/mrp_workorder/models/stock_move.py#L124-L125 Because `self.picking_type_prefill_shop_floor_lots` is True, but `self.byproduct_id` is an empty recordset since: https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/addons/mrp/models/mrp_production.py#L1304-L1311 https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/addons/mrp/models/mrp_production.py#L1279 Indeed, `byproduct_id` is only populated from BOM-defined by-products. As a result, while confirming the production, there is 2 sml and among them, the original one without SN, which triggers the error: https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/addons/stock/models/stock_move_line.py#L590 https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/addons/stock/models/stock_move_line.py#L634-L635 https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/addons/stock/models/stock_move_line.py#L658-L659 https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/addons/stock/models/stock_move_line.py#L661-L669 opw-6223158 Forward-Port-Of: odoo/enterprise#120493 Forward-Port-Of: odoo/enterprise#118792
This update resolves an issue where the system wasn't properly validating partner banks when creating SEPA direct debit mandates. The change adds a constraint to ensure the correct bank is associated with each mandate, improving data accuracy and preventing potential errors in payment processing. This enhances the reliability of our SEPA direct debit functionality.
Original PR description
Forward-Port-Of: odoo/enterprise#121236 Forward-Port-Of: odoo/enterprise#120901
This update resolves a warning in the Odoo payroll system that was causing incorrect results or access errors. The fix corrected a misconfiguration that was incorrectly targeting employee data instead of the version model. This ensures accurate payroll calculations and reliable system performance.
Original PR description
The warning `hr_payroll_warning_wrong_work_code` was targetting the version model but was returning employee records which led to the wonrg result or access errors
This update cleans up the appearance of payslips by removing unnecessary trailing zeros from the line rate displayed in the salary section. This improves the clarity and professionalism of payroll reports for employees and managers. It's a small but important visual enhancement.
Original PR description
Problem: A lot of trailing zeros were displayed on the rate of each payslip line, in the salary tab of the payslip form. Solution: We simply hid trailing zeros. Task-6310227
This update resolves a bug where tests were failing due to outdated configurations after removing a field. The tests have been updated to correctly utilize the new 'is_live' field, ensuring accurate functionality for rental stock processes. This ensures the system continues to operate reliably.
Original PR description
Some tests were not adapted after removing state field, this caused the failed tests, the tests are now adatped to set up the is_live field instead. Community: https://github.com/odoo/odoo/pull/271052
This update fixes a technical issue in the Belgian payroll localization (l10n_be_hr_payroll) where a field was incorrectly configured to accept monetary values instead of the intended quantity. This change ensures accurate calculation of 'Forced # Months' compensation rules, aligning with Belgian accounting standards.
Original PR description
In Belgium localization salary rule "Forced # Months", the input unit type was monetary when it supposed to be quantity. This commit changes the input type to the correct one (quantity) Task: 6241599
This update fixes a potential issue where changes to the Point of Sale system could disrupt the display of receipt quantities. By using a more flexible method to locate the relevant data, the update ensures the receipt information remains accurate and consistent, regardless of future Point of Sale updates. This enhances the reliability of the receipt generation process.
Original PR description
In this commit - -------------- Use a more generic xpath on the receipt quantity span instead of matching the full class attribute, so the template inheritance does not break when point_of_sale updates the text size class.
This update corrects a previous issue where Odoo was incorrectly selecting unavailable couriers from Shiprocket. The fix now filters out ‘blocked’ couriers, ensuring only serviceable options are considered for rate calculations and shipment selection. Additionally, the system is now more robust in handling potential errors from Shiprocket’s data.
Original PR description
Shiprocket provides an odablock flag in the courier serviceability response. Couriers with odablock=True are not serviceable for the requested route and should not be considered for rate calculation or selection. Before this change, Odoo selected the first courier returned by Shiprocket regardless of its ODA status. As a result, unavailable couriers could be proposed to users and selected for shipments. The fix filters out ODA-blocked couriers before evaluating available services, ensuring that only serviceable couriers are considered. Additionally, freight charge parsing is hardened to gracefully handle non-numeric values returned by Shiprocket, preventing errors during AWB assignment and price computation. FYI: Shiprocket uses odablock=False for serviceable routes and odablock=True for routes that are blocked for a given courier. opw-6288768,6152279 Forward-Port-Of: odoo/enterprise#120374
This update optimizes how the system searches for documents, specifically addressing a slow and complex query when filtering by 'not SHARED'. The change aligns with the production database's approach, resulting in faster and more efficient searches. This improves overall user experience and system responsiveness.
Original PR description
Searching for "not 'SHARED'" results in a very complex query. Our own production DB prefers this implementation, also easier to read. credit: https://github.com/odoo/enterprise/pull/105915#discussion_r2745148099 Task-5893183 Forward-Port-Of: odoo/enterprise#121070 Forward-Port-Of: odoo/enterprise#120870
This update fixes a bug where changes to employee data didn't correctly update past payslips. The fix ensures that all affected payslips are accurately corrected when a user manages them, preventing discrepancies in payroll calculations. This improves data accuracy and payroll processing reliability.
Original PR description
Steps to reproduce: 1. Make sure you have an employee with a contract 2. Create 2 payslips for this employee 3. Change any field of the employee (ex: job position) 4. Go to one of the payslips…
Steps to reproduce: 1. Make sure you have an employee with a contract 2. Create 2 payslips for this employee 3. Change any field of the employee (ex: job position) 4. Go to one of the payslips created before 5. Click on the "Manage Payslips" link appearing because of the change of data Problem: When the data of an employee has been modified and past payslip are affected, the popup currently states 0 payslip has been affected. When clicking the "Correct" button, the correct amount briefly shows before we are sent to the payslip page where only one payslip gets corrected. Source of the problem: - The `employee_id` field was missing from the wizard form view. Since it was not referenced anywhere in the view, the web client did not include it in the initial payload / default_get calls. As a result, the wizard was initialized without `employee_id`, causing the payslip computation to use an empty employee and return a count of 0. - The window action did not explicitly call the intended wizard form view. Odoo therefore selected an unintended inherited view (salary increase wizard) due to view resolution rules (inheritance and priority ordering). This inherited view specifically replaces the description and the correction choice with nothing, which explains why it didn't show before. Fix: - Add an invisible `employee_id` field in the form view to ensure it is included in the initial form payload and properly initialized from context defaults. - Explicitly specify the correct view in the `views` parameter of the window action to prevent fallback to an inherited or unintended view. - Add an explicit priority on the salary increase wizard view to avoid ambiguous view selection in the future. Task-6304311
This update resolves an issue where the 281.XX report generation failed due to missing employee first and last names. The fix adds a check to ensure these fields are populated, preventing errors and ensuring accurate report creation. This improves the reliability of payroll reporting.
Original PR description
Steps to reproduce: 1. Create a Belgian company with a full address, phone and VAT 2. Create an employee of this company with a full private address, valid NISS (or "/"), and give him a contract. 3. Make sure the employee doesn't have a first name or a last name set. 4. Create some payslips for the employee (one is enough). 5. Go to Reporting > 281.XX Sheets and try creating a new report for the corresponding year. Problem: When pressing "Compute", you will see a traceback indicating us that an error occured because of the first name not being set. Fix: Adding a check to make sure that the first and last name are set, and raising an error if it is not the case. Task-6318024
This update resolves a crash that occurred when users viewed real Instagram videos within Odoo. The fix now displays the video link instead of attempting to show the video as an image, preventing the previewer from failing. This ensures a smoother user experience when viewing Instagram content.
Original PR description
Purpose ======= When we have a real on Instagram, we try to show the video as an image. When clicking on the broken image, the previewer crash. To fix that issue, we know show the link of the video in the message. Task-5491124 Forward-Port-Of: odoo/enterprise#121176 Forward-Port-Of: odoo/enterprise#113487
9 changes
Resolved issues and error corrections
This update resolves a technical issue preventing debit notes generated for Colombian DIAN tax reporting from being successfully sent. The fix removes an unnecessary 'BuyerReference' field from the debit note XML, which was causing a validation error. This ensures accurate and compliant submission of debit notes to the DIAN authority.
Original PR description
Issue: Sending Debit Notes to a tax authority can cause the following error: "ValueError: The following child node is not defined in the template: DebitNote/cbc:BuyerReference" Steps to reproduce on…
Issue: Sending Debit Notes to a tax authority can cause the following error: "ValueError: The following child node is not defined in the template: DebitNote/cbc:BuyerReference" Steps to reproduce on any database with DIAN and Colombian localization: 1. Create a new "Sales" type journal. Then, check the checkbox “Nota de Debito”. 2. Find a res.partner with a ref field, or add a ref field to any partner. 3. Make an invoice using the partner found in step 2. Ensure it uses a tax. Confirm it. 4. Send that invoice to DIAN. 5. Create a Debit Note for that invoice. Use the journal created in step 1. 6. Add a product, price, and tax to the debit note. Confirm it. 7. Send the debit note to DIAN. Explanation: The `_add_invoice_header_nodes` method on the AccountEdiXmlUbl_21 model adds a BuyerReference node unconditionally. (See account_edi_xml_ubl_21.py.) But the DebitNote XML template does not include a BuyerReference element (see ubl_21_debit_note.py). This caused a ValueError when assembling the XML for debit note documents. Solution: The fix overrides this in the Colombian localization by clearing the BuyerReference value when the document type is "debit_note". That way, the node is omitted from the output. opw-6181039
This update fixes an issue where preparation times weren't accurately calculated when order stages changed and where reports incorrectly included data from all companies. The changes ensure preparation times are correctly updated and that reports now only display data for the active company, improving reporting accuracy and efficiency.
Original PR description
Issues: - Preparation time for order lines was not computed when the preparation order stage changed. - Preparation time report aggregated orders across all companies instead of showing records for the active company only. Fixes: - Ensure preparation time is properly recomputed when the order stage changes. - Add company domain filtering to the preparation time report. Task-6250974 Forward-Port-Of: odoo/enterprise#118738
This update resolves an issue where processing invoices with multiple related documents (especially cancellations) was slow due to a database index limitation. Switching to a different index type allows the system to handle complex scenarios efficiently and maintain fast search performance for finding invoices.
Original PR description
The field `l10n_mx_edi_cfdi_origin` can contain a large number of associated UUIDs, especially in complex cancellation scenarios. The default B-tree index fails when this field exceeds 2704 bytes, which occurs after approximately 20 UUIDs. By switching to a trigram index, we avoid the entry size limit of PostgreSQL's B-tree nodes. This ensures that invoices with many related documents can be processed while maintaining efficient search performance for partial matches on this field. **Video before the fix:** https://youtu.be/24u0HbxwIH8 **Video after the fix:** https://youtu.be/sUelv1HZMvI Forward-Port-Of: odoo/enterprise#118868
This update corrects a previous issue where Odoo was selecting unavailable couriers from Shiprocket due to a lack of filtering. The change now ensures only serviceable couriers are considered, preventing incorrect rate calculations and shipment selections. Additionally, the system is more robust to handle potential errors in Shiprocket's data.
Original PR description
Shiprocket provides an odablock flag in the courier serviceability response. Couriers with odablock=True are not serviceable for the requested route and should not be considered for rate calculation or selection. Before this change, Odoo selected the first courier returned by Shiprocket regardless of its ODA status. As a result, unavailable couriers could be proposed to users and selected for shipments. The fix filters out ODA-blocked couriers before evaluating available services, ensuring that only serviceable couriers are considered. Additionally, freight charge parsing is hardened to gracefully handle non-numeric values returned by Shiprocket, preventing errors during AWB assignment and price computation. FYI: Shiprocket uses odablock=False for serviceable routes and odablock=True for routes that are blocked for a given courier. opw-6288768,6152279 Forward-Port-Of: odoo/enterprise#120374
This update resolves a bug where Odoo failed to correctly retrieve lot numbers from GS1 barcodes containing leading zeros (like '10'). The fix ensures accurate lot number identification when scanning these barcodes, preventing errors and improving inventory management. This ensures accurate tracking of products by lot.
Original PR description
When we scan a gs1 barcode that has in his lot a special character and start with 10, odoo will not be able to retrieve it from the db. **Steps to reproduce** * In settings activate: - Lots & Serial…
When we scan a gs1 barcode that has in his lot a special character and start with 10, odoo will not be able to retrieve it from the db. **Steps to reproduce** * In settings activate: - Lots & Serial Numbers - Units of Measure & Packagings - Storage Locations - Barcode Scanner : GS1 nomenclature * Create a Product tracked by lot with - barcode: 00001234567895 * Add on hand quantity: - 100 kg in lot : 10002002303-4 - 100 kg in lot : 11002002303-4 * Go to barcode>Operation>Internal Transfer>New * Scan 02000012345678951010002002303-4#3100000100 meaning: - 02 following 14 characters are the product barcode - 10 following characters are the lot number - "#" separator - 3100: means the units are kilograms, - 00100 means 100 units. -> if you check with the edit button the lot was not found (if you click on validate it will trigger an UserError for missing lot) **Observation** When scanning the GS1 barcode it will call onBarcodeSubmitted->onBarcodeScanned where we will execute processBarcode: https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/stock_barcode/static/src/components/main.js#L387 Where we will deconstruct the barcode into his component en retrieve from the db the relevant data: https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/stock_barcode/static/src/models/barcode_model.js#L709-L717 - First the barcode is parsed, identifiers are erased and each section is separated, the variable with our lot number only has the lot number in it, the identifier (10) is not included, BarcodeObject.forBarcode(bc) -> new BarcodeObject -> parser.parse_barcode: https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/stock_barcode/static/src/barcode_object.js#L14 - Check if the data is in the cache, if not, set it to retrieve after - Retrieve missing data getMissingRecords : https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/stock_barcode/static/src/lazy_barcode_cache.js#L349 From here we will get a call to get_specific_barcode_data for each element: https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/stock_barcode/controllers/stock_barcode.py#L176 In the case of the stock.lot since it has a symbol and it's not only digit it will skip the gs1 nomenclature domain converter (it will not become 'ilike' and stay with 'in'): https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/stock_barcode/controllers/stock_barcode.py#L182-L197 We will do the search: https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/stock_barcode/controllers/stock_barcode.py#L205 during which we will retrieve specific query from the stock.lot module : https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/odoo/orm/models.py#L1408 Where, since it's a GS1 nomenclature, we will preprocess the agrs: https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/stock_barcode/models/stock_lot.py#L14 -> Since our barcode start with a 10, it will erase it, which lead to a miss in the search. It will also avoid further searches since we avoid multiple search on the same elements (added in missingBarcodeKeyCache in getMissingRecords). https://github.com/odoo/enterprise/blob/c6d18a7a92092ffdf96f4569a70e95bdc276441c/stock_barcode/static/src/lazy_barcode_cache.js#L294-L298 opw-6207120
This update resolves an issue where changing a task's deadline by shrinking its right edge in the Gantt chart view caused a server error. The fix addresses a situation where tasks with no successors resulted in an empty date list, triggering a ValueError. This ensures the Gantt chart's deadline adjustment functionality is now consistently reliable.
Original PR description
## Current behavior: In the Project's app, switch to Gantt chart's view, when changing the deadline of a single task by shrinking its right edge, the server throws `ValueError: max() iterable…
## Current behavior: In the Project's app, switch to Gantt chart's view, when changing the deadline of a single task by shrinking its right edge, the server throws `ValueError: max() iterable argument`` is empty when calling end_date = max(candidates.mapped(stop_date_field_name)). ## Steps to reproduce: 1. In version 19.0 and above, install Project app 2. Create a project and only 1 single task 3. Switch to Gantt chart view 4. Try changing the deadline of a task by dragging its right edge 5. Observe that extending the task's deadline by dragging to the right works fine, but shrinking the deadline by dragging to the left will cause server to throw RPC_ERROR: Odoo Server Error and ValueError: max() iterable argument is empty. ## Cause of the issue: - A task with NO successors will cause candidates gathered via dependency_inverted_field_name to be empty. - The empty candidates recordset then get called by max(candidates.mapped(stop_date_field_name)), which is the reason causing error message ValueError: max() iterable argument is empty. opw-6283566
This update resolves a crash that occurred when users attempted to view Instagram videos within Odoo. The fix now displays the video link instead of the image, ensuring a smooth user experience. This improves stability and prevents interruptions when accessing Instagram content.
Original PR description
Purpose ======= When we have a real on Instagram, we try to show the video as an image. When clicking on the broken image, the previewer crash. To fix that issue, we know show the link of the video in the message. Task-5491124 Forward-Port-Of: odoo/enterprise#121176 Forward-Port-Of: odoo/enterprise#113487
This update resolves an issue where international UPS shipments were failing due to incorrect commercial invoice address information. The fix initially used the delivery address, but caused further problems. Now, the system defaults back to the delivery address if country codes don't match, with a warning displayed to the user to ensure accurate invoice details.
Original PR description
Issue ----- When making an international delivery to a partner with different invoice and delivery addresses, we send the delivery address as the `Sold To` address as well. Problematic case 1 ----- -…
Issue ----- When making an international delivery to a partner with different invoice and delivery addresses, we send the delivery address as the `Sold To` address as well. Problematic case 1 ----- - Create a belgian company - Setup UPS - Create a French customer - Add a different french delivery address - Create a product (with some weight) - Create a SO (with UPS delivery) to the customer & confirm - Validate the transfer > Commercial invoice `Sold To` uses the delivery address Solution for case 1 ----- Use the delivery address' `commercial_partner_id`. This leads to another issue in some edge cases... Problematic case 2 (caused by case 1 fix) ----- - Create a belgian company - Setup UPS - Create a French customer - Add a delivery address in Switzerland - Create a product (with some weight) - Create a SO (with UPS delivery) to the customer & confirm - Validate the transfer > UPS error `The Sold To party's country code must be the same as the Ship To party's country code with the exception of Canada and satellite countries.` Solution for case 2 ----- Default back to delivery address for the `Sold To` field when countries don't match, as this is a limitation of the UPS API. Warn the user, either on the SO or the transfer itself (if no SO). Warning looks like this (on SO): <img width="1914" height="716" alt="image" src="https://github.com/user-attachments/assets/f7aa73c4-f24c-42da-8f3e-6a58765ef020" /> ----- Ticket: opw-6200263 Forward-Port-Of: odoo/enterprise#120592 Forward-Port-Of: odoo/enterprise#118031
This update fixes an error in the CFDI invoice generation process when payments are made in foreign currencies (like USD). Previously, the CFDI document incorrectly displayed the payment amount and rate. The fix ensures the correct USD amount and corresponding MXN rate are used, accurately reflecting the payment details on the CFDI document.
Original PR description
The rate and payment amount shown on the CFDI document generated after updating payments was wrong when the payment was made in a foreign currency. Steps to reproduce: ------------------- * Create a journal that use USD as currency and set the rate to 20 MXN for 1 USD * Create an invoice in MXN and make sure it is set to PPD * Add any product to the invoice for 300$ and post it * Send the invoice to CFDI (a first document should be generated) * Create a payment of 15 USD in the new journal and reconcile it with the invoice * Go back to the invoice and click on "Update payments" to generate the second CFDI document > Observation: The payment document shows an amount of 300 USD with a rate of 1 instead of 15 USD with a rate of 20. Why the fix: ------------ We make sure to use the amount from the statement line when there is one. opw-5974519 Forward-Port-Of: odoo/enterprise#120934 Forward-Port-Of: odoo/enterprise#115779
6 changes
Resolved issues and error corrections
This update addresses slow response times in the Point of Sale UI caused by prolonged network requests. By adding timeouts and optimizing font loading, the system now reacts faster to network changes, preventing delays in operations like receipt printing and synchronization. This enhances the overall user experience and system stability.
Original PR description
Currently, requests from the PoS UI are sent without any timeout, which can lead to indefinite waiting when the system is connected to a network but lacks internet access. Examples: - `sync_from_ui`…
Currently, requests from the PoS UI are sent without any timeout, which can lead to indefinite waiting when the system is connected to a network but lacks internet access. Examples: - `sync_from_ui` can take more than 2 minutes to fail. - Font CDN requests during receipt printing can take over 4 minutes to fail. - In some cases, this causes receipt printing failure as well, even after several minutes (4-5 min) of delay. This commit introduces a timeout for PoS UI requests to prevent such delays and improve responsiveness. Additionally, font declarations are extracted from `web` into `point_of_sale`, and only the required fonts are included. This avoids unnecessary requests to missing CDN resources. Additionally, this PR backports the following commits required to support this fix: - https://github.com/odoo/odoo/pull/215130 - https://github.com/odoo/odoo/pull/220954 Ensures the system continuously checks network connectivity and resumes synchronization once the connection is restored. - https://github.com/odoo/odoo/pull/225743 Prevents receipt printing from being blocked by logo loading issues and ensures the logo is displayed gracefully in such scenarios. Task-6053404 | Font CDN request delay (~ 4 min) | `sync_from_ui` long request (> 2 min) | | --------------------------------- | --------------------------------------------------------------------------------------------------------- | | <img width="400" src="https://github.com/user-attachments/assets/8ea8b3e4-7ffe-44bf-a4d0-7975f43a8f68" /> | <img width="400" src="https://github.com/user-attachments/assets/5f899cab-b022-4ed2-aa82-12e54ea34ea7" /> |
A test within the Mail Alias module was failing on the pg18 database version. This fix addresses an underlying issue related to database constraints that resulted in a specific error. The test has been updated to use a more general error type for better reliability.
Original PR description
This commit is kind of a follow up of
odoo/odoo@39cd4ea856fe00f5674f8c44b2b66cbf2705426d (in 18.0).
In a nutshell, following a standard-compliance fix (postgres/postgres@086c84b) has led to `RESTRICT_VIOLATION` being emitted in cases which formerly emitted `FOREIGN_KEY_VIOLATION`. One such case is specifically being tested for by `test_alias_domain_setup`, leading to this test failing systematically when running pg18:
psycopg2.errors.RestrictViolation: update or delete on table "mail_alias_domain" violates RESTRICT setting of foreign key constraint "mail_alias_alias_domain_id_fkey" on table "mail_alias"
DETAIL: Key (id)=(191) is referenced from table "mail_alias".
This commit updates the test to use the more generic `IntegrityError` as it's probably more than sufficient for our purposes.
Forward-Port-Of: odoo/odoo#271302This update corrects a bug in how Odoo calculates the Cost of Goods Sold (COGS) for sale orders involving kits. Previously, archived components were excluded, leading to inaccurate journal entries. Now, all components, including archived ones, are correctly included in the COGS calculation, ensuring accurate inventory valuation and invoicing.
Original PR description
### Issue: When invoicing a sale order for a kit, components tracked by quantity that are archived are excluded from the Cost of Goods Sold (COGS) calculation As a result, the journal items for…
### Issue: When invoicing a sale order for a kit, components tracked by quantity that are archived are excluded from the Cost of Goods Sold (COGS) calculation As a result, the journal items for "Expenses" and "Stock Interim (Delivered)" are undervalued on the invoice, creating a mismatch with the inventory valuation which correctly includes the archived components' costs Odoo natively allows the delivery and usage of archived components when they are part of a BoM ### Cause: The Bill of Materials (BoM) explosion correctly bypasses the active check using `with_context(active_test=False)` However, during the invoice posting, `_stock_account_get_anglo_saxon_price_unit()` filters the kit's components using a standard `search()`, but without disabling the active test Consequently, archived components tracked by quantity are ignored when computing the final anglo-saxon price unit ### To reproduce the issue: - Install `account_accountant`, `sale_management` and `mrp` - Create a product category PC (Inventory Valuation: Automated) - Create 3 Products: - Kit (Tracked: Quantity, Product Category: PC) - Kit_Comp01 (Tracked: Quantity, Product Category: PC, Cost: 10$) - Kit_Comp02 (Tracked: Quantity, Product Category: PC, Cost: 20$) - Set Kit_Comp01 and Kit_Comp02 on hand's quantity to 1 - Create a Bill of Materials (Product: Kit, Type: Kit, Components: 1x Kit_Comp01, 1x Kit_Comp02) - Archive Kit_Comp02 - Create and Confirm a Sale Order for 1x Kit - Process the related delivery - Create and Post the Invoice - Check the Journal Items tab Before the fix, the lines `Expenses` and `Stock Interim (Delivered)` are 10$ instead of 30$ opw-6204621
This update corrects a previous issue where Odoo was incorrectly selecting unavailable couriers from Shiprocket. The change now filters out ‘blocked’ couriers, ensuring only service-eligible options are considered for shipping rates and selections. Additionally, the system is now more robust to handle unexpected data from Shiprocket, preventing errors in shipment pricing.
Original PR description
Shiprocket provides an odablock flag in the courier serviceability response. Couriers with odablock=True are not serviceable for the requested route and should not be considered for rate calculation or selection. Before this change, Odoo selected the first courier returned by Shiprocket regardless of its ODA status. As a result, unavailable couriers could be proposed to users and selected for shipments. The fix filters out ODA-blocked couriers before evaluating available services, ensuring that only serviceable couriers are considered. Additionally, freight charge parsing is hardened to gracefully handle non-numeric values returned by Shiprocket, preventing errors during AWB assignment and price computation. FYI: Shiprocket uses odablock=False for serviceable routes and odablock=True for routes that are blocked for a given courier. opw-6288768,6152279 Forward-Port-Of: odoo/enterprise#120374
This update ensures that custom reports attached to Mexican invoices are named correctly, avoiding duplicate filenames. The previous issue stemmed from a technical error in how report names were generated, now fixed to properly utilize the custom report's name when sending invoices.
Original PR description
**Steps to reproduce:** * Install **l10n_mx_edi**. * Go to **Accounting → Customers → Invoices**. * Open **Studio** and, from the top bar, go to **Reports**. * Duplicate the standard **Invoice PDF**…
**Steps to reproduce:** * Install **l10n_mx_edi**. * Go to **Accounting → Customers → Invoices**. * Open **Studio** and, from the top bar, go to **Reports**. * Duplicate the standard **Invoice PDF** report. * Open the duplicated report and make any modification to it. * Enable **Developer Mode**. * Go to **Settings → Technical → Actions → Reports** and update the custom report's **Printed Report Name**. * Go to **Settings → Technical → Email → Templates** and create a new invoice email template. * Add the custom report to the template's **Dynamic Reports**. * Create and confirm an invoice for a **Mexican company**. * Click **Send** and select the newly created email template. **Observed behavior:** * The custom report attachment uses the CFDI-based filename instead of its own report name, making it appear as a duplicate of the standard invoice attachment. **Cause:** * `_get_invoice_report_filename` in `l10n_mx_edi` unconditionally returned the CFDI filename whenever `l10n_mx_edi_is_cfdi_needed` was `True`, ignoring the `invoice_report` context key. * `account_move_send` sets `invoice_report` to the extra mail template when requesting the filename for dynamic report attachments, expecting the method to delegate to `super()` and evaluate the template's `print_report_name`. The MX override never reached that branch. **Fix:** * Check for the `invoice_report` context key before applying the CFDI filename logic. When it is present (i.e. a custom/extra report is requesting its filename), fall through to `super()` so the template's `print_report_name` is used correctly. opw-6228268
This update resolves an error that occurred when the 'Company Car (To order)' option was enabled in the salary configurator. The fix ensures that a car model is selected before attempting to extract data, preventing a system crash. This improves the stability and usability of the Belgian HR contract module.
Original PR description
## Steps to Reproduce: 1. Install `l10n_be_hr_contract_salary` without demo data. 2. Create a Belgian company and switch to it. 3. Create an employee. 4. Create a contract for the employee. 5. Click Generate Offer and open the Salary Configurator. 6. Enable the 'Company Car (To order)' option. ## Error: `AttributeError: 'NoneType' object has no attribute 'split'` ## Cause: When the salary configurator is used without demo data, no car model is selected. The method assumes that select_wishlist_car_total_depreciated_cost always contains a value and directly calls split() on it, resulting in an error, when the field is None. ## Fix: This commit checks that both the company car option is enabled and a car model has been selected before trying to extract the model ID. sentry-7554712017
2 changes
Resolved issues and error corrections
This update resolves an issue where foreign currency vendor bills were incorrectly flagged as 'Partially matched' during GSTR-2B reporting. The fix ensures that GSTR-2B data, always in INR, is accurately compared against the bill's amounts, regardless of the currency setting. This improves the reliability of GSTR-2B reconciliation.
Original PR description
**Steps to reproduce:** * Install the **l10n_in_reports** module. * Go to **Accounting → Configuration → Settings**, and enable **Multi-Currencies**. * Activate a foreign currency (e.g., USD) and set…
**Steps to reproduce:** * Install the **l10n_in_reports** module. * Go to **Accounting → Configuration → Settings**, and enable **Multi-Currencies**. * Activate a foreign currency (e.g., USD) and set an exchange rate. * Create a new vendor bill for an Indian vendor, setting the currency to USD. * Add lines to the bill and apply IGST/GST taxes, then confirm the bill. * Go to **Accounting → Reporting → GST Return Period** and initiate GSTR-2B matching for the period corresponding to the bill (using a valid JSON payload where the amounts are correctly reported in INR). **Observed behavior:** * The vendor bill is incorrectly marked as "Partially matched" instead of "Fully matched", accompanied by an exception stating that the total amount as per GSTR-2B does not match. **Cause:** * The GSTR-2B data fetched from the GST portal always reports values in the company's base currency (INR). * The `match_bills` method was directly comparing the GSTR-2B INR amounts ( `bill_total` and `bill_taxable_value`) against the bill's `amount_total` and `amount_untaxed` fields. * Because these fields return values in the document's foreign currency (e.g., USD), the mismatch triggers an exception and flags the bill as partially matched. **Fix:** * Modified the matching logic to compare GSTR-2B values against `abs(amount_total_signed)` and `abs(amount_untaxed_signed)`. * This ensures that the amounts evaluated during reconciliation are always correctly converted and compared in the company's base currency (INR). opw-6311097
This update ensures that sales orders with recurring products always have a valid subscription plan. Previously, adding a recurring product without a subscription plan didn't trigger a warning, leading to potential errors. This fix introduces a consistent validation process for both manual and catalog product additions, improving order accuracy.
Original PR description
Steps to reproduce: --------------------------------------- 1. Install Subscription Module 2. Create and Confirm SO with no recurring plan and a non-recurring product 3. Add a recurring product >…
Steps to reproduce: --------------------------------------- 1. Install Subscription Module 2. Create and Confirm SO with no recurring plan and a non-recurring product 3. Add a recurring product > Save SO > Observe the User Error 4. Now add the same recurring product through Catalog View Observation: --------------------------------------- No User Error raised stating 'You cannot save a sale order with recurring product and no subscription plan.' Issue: --------------------------------------- When you manually add a line and click 'Save', the constraint (`_constraint_subscription_plan`) is triggered and raised `UserError` https://github.com/odoo/enterprise/blob/434d88960abb5e424fdc1106fc93935d328bff78/sale_subscription/models/sale_order.py#L176-L177 When you add a product via the catalog view, it calls `_update_order_line_info` which directly creates/updates order lines, Which do not trigger the python constraint. https://github.com/odoo/odoo/blob/ef9772bba1515bdaf5410c3af5a3e395f562d513/addons/sale/models/sale_order.py#L1926-L1933 Solution: --------------------------------------- Two private helpers are introduced: * `_is_exempt_from_subscription_plan_check`: single source of truth for all exempt states (draft, cancelled, upsell, and legacy upgrade orders). * `_check_recurring_plan_mismatch`: raises a `UserError` when the order has or will have a recurring product but no subscription plan, reusing the exemption helper so both call sites stay in sync. `_constraint_subscription_plan` is refactored to delegate to these helpers, and `_update_order_line_info` is overridden to call `_check_recurring_plan_mismatch` before the catalog update is applied, ensuring consistent validation across both entry points. opw-6194865