Daily updates from Odoo
Thursday, July 9, 2026
113 changes
22 changes
Enhancements to existing features
Belgian payroll rules now include updated employment bonus parameters effective 1 July 2026 and 1 September 2026. This helps ensure payslip calculations stay aligned with the latest Belgian payroll requirements.
Original PR description
Update the employment bonus parameters for 1st July 2026 and 1st September 2026. task-6369633 Forward-Port-Of: odoo/enterprise#123311 Forward-Port-Of: odoo/enterprise#123262
The bank reconciliation widget now sends less unnecessary data to the browser and precomputes some information on the server. This should make opening and using bank reconciliation faster on very large databases, improving accountant productivity.
Original PR description
When opening the bank rec widget on huge DB's, it takes
a lot of time to load everything.
This commit aims to improve the loading performances by
removing some JS fields:
1 - reconciled_lines_ids: We only use the first element of
this recordset in JS, so we add a new computed field
to only send 1 record to the JS
2 - hasAttachment: replace the long JS computation of
`get hasAttachment` with a python computed field.
3 - Replace matched_credit_ids and matched_debit_ids
with exchange_diff_partial_ids.
Linked:https://github.com/odoo/odoo/pull/269119
task-6275945
Forward-Port-Of: odoo/enterprise#119557Searching for customers in Point of Sale is now more responsive when many partners exist. The system now shows only a practical number of results and waits a bit longer before re-running the search while typing, which reduces delays and improves the user experience.
Original PR description
Before this commit, when high number of partners were loaded in the POS, searching for a partner was slow. The main issue was that all of the filtered partners based on the search query were being rendered, while in reality, if a query returns lots of results, the search query is not refined enough and the user is likely to type more characters to narrow down the search. So in this commit, we limit the number of rendered partners to 200, which is a reasonable number of results to display and does not cause performance issues. Moreover, the debounce time of the search input has been increased from 100ms to 500ms to further reduce the number of times the search function is called while the user is typing. opw-6215958 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#268658 Forward-Port-Of: odoo/odoo#264300
Resolved issues and error corrections
Australian payroll payslips now refresh an employee's income stream type before calculating the sheet. This prevents payroll users from hitting an error when an employee's income category was updated after a payslip had already been created.
Original PR description
When an employee's Income Stream Type is changed after a payslip has been created, computing the sheet for payslip will raise a traceback. Steps to reproduce the error: - Install…
When an employee's Income Stream Type is changed after a payslip has been created, computing the sheet for payslip will raise a traceback. Steps to reproduce the error: - Install ``l10n_au_hr_payroll_account`` module with demo data - Switch to ``My Australian Company`` company - Create a new payslip for ``Dennis Cactus`` Employee > Save - Go to Employees > Open the ``Dennis Cactus`` employee > In Payroll tab, Income Stream Type: Other specified payments > Save - Go back to payslip > click the compute sheet button Traceback: ```py KeyError: 'OSP' ``` https://github.com/odoo/enterprise/blob/13e64e0cb7f566cbbb46109fe1c218eb7a14eead/l10n_au_hr_payroll/models/hr_payslip.py#L175-L178 The ``l10n_au_income_stream_type`` field on the payslip is a computed field that only depends on ``employee_id``. As a result, changing the employee's Income Stream Type does not trigger a recomputation of the corresponding field on existing payslip. So, when the ``payslip_ytd_totals`` field is computed, it uses the old value of ``l10n_au_income_stream_type`` field at [1], The resulting ``payslip_ytd_totals`` is then used to build the ``totals`` dictionary, and eventually, when the employee's current ``income_stream_type`` is used to access ``totals``, the mismatch key leads to the above traceback. https://github.com/odoo/enterprise/blob/13e64e0cb7f566cbbb46109fe1c218eb7a14eead/l10n_au_hr_payroll_account/models/hr_payslip.py#L75-L88 [1]: https://github.com/odoo/enterprise/blob/13e64e0cb7f566cbbb46109fe1c218eb7a14eead/l10n_au_hr_payroll/models/hr_payslip.py#L269-L272 solution: I added ``l10n_au_income_stream_type`` to ``add_to_compute()`` in ``compute_sheet()``. This ensures that stale values of ``l10n_au_income_stream_type`` on existing payslips are recomputed when the payslip sheet is computed. sentry-7536819310 Forward-Port-Of: odoo/enterprise#123288 Forward-Port-Of: odoo/enterprise#120143
This fix ensures sales orders cannot add recurring subscription products from the catalog unless a subscription plan is set. It closes a validation gap so users get the same warning whether they add products manually or through the catalog view, helping prevent incorrect subscription orders.
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 Forward-Port-Of: odoo/enterprise#123216 Forward-Port-Of: odoo/enterprise#117879
Vendor bills imported from Chilean electronic invoices now use the correct foreign-currency amounts instead of peso amounts. This prevents incorrect bill totals when companies work with currencies such as UF, improving accounting accuracy.
Original PR description
**STEP TO REPRODUCE** 1. Create a invoice to a chilian company, using another currency (for example UF, don't forget setup up a currency rate). 2. Confirm. 3. Download the xml in the chatter, and import it as a vendor bill. 4. Notice the imported bill amount are wrong (Pesos amount are used, with the currency being UF). opw-6269662 Forward-Port-Of: odoo/enterprise#123179 Forward-Port-Of: odoo/enterprise#119664
Fixes an error that could stop Sendcloud batch deliveries when one transfer was split into multiple packages. Users can now validate these deliveries reliably, avoiding failed shipping workflows and disruption during order fulfillment.
Original PR description
Issue ----- When using Sendcloud batch deliveries, users get a traceback if the transfer is split into multiple packages. Steps to reproduce ----- - Setup Sendcloud - Enable batch delivery - Create a…
Issue ----- When using Sendcloud batch deliveries, users get a traceback if the transfer is split into multiple packages. Steps to reproduce ----- - Setup Sendcloud - Enable batch delivery - Create a delivery for 2 units of a product - Delivery method set to sendcloud - Put each unit in a separate package - Validate the delivery > Traceback Cause ----- Bug introduced by #90302 (so only present in 19.3+). When using the batch deliveries option, the packages are sent in a single list. This means that, in `_prepare_parcel`, when we iterate over the packages, `pkg` can be a list https://github.com/odoo/enterprise/blob/2c89c8e5da7dcb83d5a60c9616de4d5d07f0b9ab/delivery_sendcloud/models/sendcloud_service.py#L462 This means that `pkg.name` will fail https://github.com/odoo/enterprise/blob/2c89c8e5da7dcb83d5a60c9616de4d5d07f0b9ab/delivery_sendcloud/models/sendcloud_service.py#L481 Considering that a batch delivery uses the same reference number on all labels, we can pass `None` as a fallback to `_get_unique_order_number_reference` (it is an accepted value) https://github.com/odoo/enterprise/blob/2c89c8e5da7dcb83d5a60c9616de4d5d07f0b9ab/delivery_sendcloud/models/sendcloud_service.py#L388-L393 ----- Ticket: opw-6267928 Forward-Port-Of: odoo/enterprise#120206
This fixes DHL shipping validation when deliveries are processed from a company other than the main one. Commercial invoice numbers are now generated correctly, preventing DHL from rejecting affected international deliveries.
Original PR description
Issue ----- When validating a delivery in a different company from the main one, the commercial invoice's number field is incorrect, which raises an error on DHL end.…
Issue ----- When validating a delivery in a different company from the main one, the commercial invoice's number field is incorrect, which raises an error on DHL end. `content/exportDeclaration/invoice/number: expected type: String, found: Boolean` Steps to reproduce ----- - Create a Belgian company - Setup DHL - DHL Product D - Express Worldwide - Dutiable Material enabled - Create an amrican customer - Deliver a product to the american customer > Validation Error Cause ----- The field is populated in https://github.com/odoo/enterprise/blob/cf3c2fce8a6b7b2d7547d44a0e4423f887986d52/delivery_dhl_rest/models/dhl_request.py#L204 The problem is that `next_by_code` uses the company found in the env, whereas the sequence's company is the main one, so it is not found when doing https://github.com/odoo/odoo/blob/e3b0ca11d99b2ef819cdad68b169112cd73668b6/odoo/addons/base/models/ir_sequence.py#L287 ----- Ticket: opw-6171886 Forward-Port-Of: odoo/enterprise#123170 Forward-Port-Of: odoo/enterprise#118379
This fix restores reliable access to WhatsApp message content for users who are allowed to see those WhatsApp messages. It prevents upgrade and usage failures caused by overly restrictive linked-message checks, while keeping the existing WhatsApp message visibility rules in place.
Original PR description
The `body` field on `whatsapp.message` was defined with `related_sudo=False` with the intent of restricting access to messages from restricted records. However, this was never actually providing any…
The `body` field on `whatsapp.message` was defined with `related_sudo=False` with the intent of restricting access to messages from restricted records. However, this was never actually providing any security value because [`mail.message.fetch()`] was overriding it with `self.sudo()` till `v19.1`, meaning the body was always fetched as superuser regardless:
```py
web_search_read() -> search_fetch()
-> fields.py _compute_related()
-> record[self.related_field.name] # triggers fetch of mail.message.body
-> models.py _fetch_field()
-> mail_message.py fetch()
-> self = self.sudo() # sudo hack overrides related_sudo=False silently
```
In `v19.2`, the `fetch()` sudo hack was intentionally removed (see commit odoo/odoo@4727f12d274a0b2d7c455363d189565bd8fb2e7a) as access rights are now cached and can be checked without a performance penalty. This exposed the broken `related_sudo=False` which now causes an `AccessError` when trying to read the body of a `whatsapp.message` whose linked `mail.message` points to a document the current user cannot access (e.g. `purchase.order`).
Access control on `whatsapp.message` is already correctly enforced at the `ir.rule` level:
- Regular users can only see messages they created (`create_uid = user.id`)
- WA Admins can see all messages
We have upgrade requests failing on this issue: TBG-[2765]
[`mail.message.fetch()`]: https://github.com/odoo/odoo/blob/saas-19.1/addons/mail/models/mail_message.py#L812-L819
[2765]: https://upgrade.odoo.com/odoo/tbg/2765?debug=1
Forward-Port-Of: odoo/enterprise#119867Fixed a barcode workflow issue where scanning an existing package followed by a package type could create a new package without attaching it to the delivery items. Warehouse users now get the expected destination package assignment, reducing packing mistakes and invisible backend inconsistencies.
Original PR description
When scanning a package then a package type, from the point of view of the user nothing happend, and in the backend it will created a new package but it will not link it to the products nor will it…
When scanning a package then a package type, from the point of view of the user nothing happend, and in the backend it will created a new package but it will not link it to the products nor will it show any warning. Steps to reproduce: ------------------- * Install barcode and stock * Enable packages in settings * Open Inventory * Create a product, * Create a Package Type -> barcode PACKTYPE, * Create a Package linked to this package type -> PACK, * Add at least 2 unit of product to this package, * Create a delivery for 2 unit of the product, Open Barcode * Operation > Delivery orders > your delivery * Erase the destination package from the first line * Scan PACK ( don't click on the green line) * Scan PACKTYPE **Actual behavior** create a new package but does not link it to the new products **Expected behavior** create a new package and set it as destination package. Observation: ------------- When scanning the package (PACK), we will go through ```_processPackage``` -> ```async _processPackage``` where in the end the line is unselected: https://github.com/odoo/enterprise/blob/39d8a473fe03038ca0494a6a8165e3eb75bd8492/stock_barcode/static/src/models/barcode_picking_model.js#L2090 When we scan our package type (PACKTYPE), we will go to ``` _processPackage``` -> ```_processPackage```->```_processPackageType``` where we will obtains packagesIds checking that we have a source package: https://github.com/odoo/enterprise/blob/7cd9834d1d918f12dec43844cae6f112309e5772/stock_barcode/static/src/models/barcode_picking_model.js#L2123-L2132 and will send us to ```_putPackInPack```: https://github.com/odoo/enterprise/blob/7cd9834d1d918f12dec43844cae6f112309e5772/stock_barcode/static/src/models/barcode_picking_model.js#L2133-L2136 Where we will avoid the empty packageIds since we checked on the source package and not the destination package: https://github.com/odoo/enterprise/blob/2b887d094c66be7aebd92fbf735b1852f5dde4b5/stock_barcode/static/src/models/barcode_picking_model.js#L2296-L2299 and will call ```action_put_in_pack``` from the packaging model: https://github.com/odoo/enterprise/blob/2b887d094c66be7aebd92fbf735b1852f5dde4b5/stock_barcode/static/src/models/barcode_picking_model.js#L2301-L2306 In ```action_put_in_pack``` will create a new packaging and put it as a the new destination package, but since the ```previous_dest_package``` (saved in db) was itself, he will [erase the link](https://github.com/odoo/odoo/blob/cda011dc8590773f6c3a26f4ae9d5242a3147024/addons/stock/models/stock_package.py#L354-L363) he just made. Which means that in our case, we created a package without linking it to anything. Even if we avoid the function to erase the destination package, since the destination package shown in barcode is the one from move line : https://github.com/odoo/enterprise/blob/d0d0a3cf4a02bf24cf502b533e494fe7ca155eb3/stock_barcode/static/src/components/line.js#L115-L117 It will not show the new package in barcode opw-5449729 Forward-Port-Of: odoo/enterprise#120335 Forward-Port-Of: odoo/enterprise#104876
This fix ensures point-of-sale planning checks all relevant resources when a payment method is not tied to a specific resource. It also limits planning slot selection to the same company as the POS configuration, helping businesses avoid missing slots or using slots from the wrong company.
Original PR description
When no resource is linked to a resource payment method, we should take into account all resource which was not done before. This is now done. We also change the filter in python to only look for slots that are part of the same company as the config.
The timesheet grid now marks public holidays, weekends, and approved personal time off according to the employee's assigned working schedule instead of always using the company default. This helps employees and managers see accurate unavailable days, especially when teams have different schedules or contract-based calendar changes.
Original PR description
Steps to Reproduce --- - Create two different working schedules with different public holidays - Assign employees to specific working schedules - Set company default working schedule to a different…
Steps to Reproduce --- - Create two different working schedules with different public holidays - Assign employees to specific working schedules - Set company default working schedule to a different schedule - Login as employee with specific working schedule - Navigate to Timesheets app -> My Timesheets - Observe public holidays and personal time-off displayed in the timesheet grid Issue --- - The timesheet grid displays unavailable dates (public holidays, weekends) from the company's default working schedule instead of the employee's assigned working schedule. - Personal time-off requests are not reflected as unavailable dates in the timesheet grid. Current Behaviour --- - Public holidays shown are always from the company's default working schedule, ignoring employee-specific working schedule assignments. - Employee's approved time-off requests don't appear as unavailable in the timesheet. Expected Behaviour --- - Public holidays should display based on the employee's assigned working schedule, with company schedule as fallback only when no specific schedule is assigned. - Employee's personal time-off requests should appear as unavailable dates. - This should align with Time Off app behavior. Fix --- - Included employee-specific work interval calculation with personal time-off requests. - Added support for contract-based calendar changes and calendar validity periods. - Implemented proper fallback when valid intervals are not found. task-4997080 Forward-Port-Of: odoo/enterprise#123331 Forward-Port-Of: odoo/enterprise#95458
Lazada order syncing now uses the overall order status instead of separate item-level statuses. This prevents sync failures when a previously delivered item is later marked canceled, helping keep marketplace orders importing reliably.
Original PR description
Lazada stores order statuses at the item level. When an item is canceled, we mirrored this by decreasing the ordered quantity on the sale order line. But if the item was already delivered, decreasing the quantity below the delivered amount is forbidden and raises a `UserError`, which aborts the whole order sync:
```python
File ".../sale_stock/models/sale_order_line.py", line 420, in _update_line_quantity
raise UserError(_('The ordered quantity of a sale order line cannot be decreased below the amount already delivered. [...]'))
```
In practice, item-level statuses only differ from the order status in exceptional cases. Stop syncing statuses at the item level and assume the entire order shares a single status, which avoids the quantity decrease and the resulting traceback.
opw-6267730
Forward-Port-Of: odoo/enterprise#123365
Forward-Port-Of: odoo/enterprise#122851The Point of Sale product list now uses the fuller layout on medium-sized tablet screens instead of switching too early to the compact view. This makes product browsing easier for store staff on supported tablets without affecting smaller mobile screens.
Original PR description
Previously, the product list was rendered in "small display" mode for all screen sizes below the medium breakpoint (< 992px). However, some small tablets are able to fully display the product list at the medium breakpoint (≥ 768px and ≤ 991px). After this fix, "small display" mode is only applied when the screen width is below 768px. Task.6251934 Community: https://github.com/odoo/odoo/pull/266704 Forward-Port-Of: odoo/enterprise#122613 Forward-Port-Of: odoo/enterprise#119534
This fixes cases where generated website snippets could point to the wrong filter when modules were installed in a different order. The change ensures the website uses the correct database filter values, helping generated content display reliably.
Original PR description
Our default dynamic snippets filter ids are set based on the order that we install our modules. This can cause issues if the user installs their modules in a different order. To fix this, we need to update the data-filter-id value to the correct value of the DB. To be able to do this, we also change the regex replacement to use lxml instead since it's much simpler. Lxml part from 799f83575e162eb683cfaebb4eb602ccc1fbe466. Forward-Port-Of: odoo/enterprise#123340 Forward-Port-Of: odoo/enterprise#122671
AI-related screens now fit better on smaller devices, making agent profiles, composer cards, and skill forms easier to read and use on mobile. This reduces wasted space and presents key information more clearly for users working from phones or tablets.
Original PR description
This commit improves the user experience of the AI modules on smaller screens by fixing several views for mobile devices. The changes include: - Adapt the AI agent form view to follow the Contacts mobile layout by centering the avatar in a circular container and improving the layout of the name and description. - Move the agent avatar next to the record name in the AI Composer kanban view to optimize space usage. - Remove unnecessary empty space in the AI Skill form view so the form uses the available width on mobile. task-6366399
This change prevents a crash that could happen when users try to split a stock transfer that has already been completed. Since there is nothing left to split in that situation, the system now exits safely instead of showing an error.
Original PR description
Issue before this commit: ========================= When splitting a done picking that contains at least one stock move whose done quantity is less than the demanded quantity (product_uom_qty), an…
Issue before this commit: ========================= When splitting a done picking that contains at least one stock move whose done quantity is less than the demanded quantity (product_uom_qty), an expected singleton traceback occurs. Steps to Reproduce: ========================= - Install the stock module with demo data. - Create a delivery picking for any product with a demand of 5. - Set the done quantity to 2. - Validate the picking without creating a backorder. - Try to split the validated/done picking. - An expected singleton traceback is raised. Cause of the issue: ========================= Previously, attempting to split a done picking simply returned because there was nothing left to split. After this [PR](https://github.com/odoo/odoo/pull/224952), the split action calls **message_post()** to post a note on the original picking of the generated backorder. However, no backorder is created when splitting a done picking since there is no remaining quantity to split. As a result, message_post() is called on an empty recordset, leading to an expected singleton traceback. With This Commit: ========================= Splitting a done picking has no functional purpose, as there is nothing left to split. In this case, simply return without performing any action. This preserves the previous behaviour and prevents the traceback. Forward-Port-Of: odoo/odoo#274855 Forward-Port-Of: odoo/odoo#274382
This fix prevents the website editor from crashing when users open the Documents tab after selecting an icon in the media picker. It ensures the editor correctly distinguishes document items from icons, making the replacement flow more reliable.
Original PR description
### Steps to reproduce: - Open the website editor and insert a snippet. - Inside the snippet, add an image and a document via /media. - Select the image, click Replace, pick an icon. - Click the icon, then click Replace from the sidebar. - In the dialog, click the Documents tab. - Traceback occurs. ### Root cause: - Both icon and document box elements are `<span>` tags. `DocumentSelector` inherits `selectInitialMedia()` from `FileSelector` which only checks the tag name, so it incorrectly returns true for icons. This causes `fetchAttachments` to call `querySelector(a)` on the icon span, which returns null and crashes. ### Solution: - Override `selectInitialMedia()` in `DocumentSelector` to also check for the `o_file_box` class. Add optional chaining on `querySelector(a)` as a safety net. task-6310147 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270548
When a task is moved to another project, its followers now inherit the notification preferences set at the destination project. This ensures people continue receiving the updates they expect, such as stage changes, instead of missing important task activity.
Original PR description
Steps to reproduce: - 1. Create projects A and B. 2. Add a user as a follower of project B and select specific notification subtypes (e.g., 'Stage Changed'). 3. Create a task in project A and add the same user as a follower(defaulting to 'Discussions'). 4. Move the task from project A to project B. Issue: - The follower's subscription preferences on the task do not reflect their project-level settings after the move. In the example above, the user remains subscribed only to 'Discussions' and misses 'Stage Changed' updates. Cause: - The default auto-subscription logic skips existing followers. When moving a task, this prevents the system from adding the new project's notification preferences to users who were already following the task. Fix: - Override `_message_auto_subscribe` in project.task to the `update` policy when the `project_id` is changed. task-5877507 Forward-Port-Of: odoo/odoo#248224
This change fixes a problem where e-invoices could be rejected by the Nilvera service when the company uses a foreign main currency. The system now always includes the required exchange rate to Turkish Lira in the invoice data, helping invoices go through successfully.
Original PR description
Description of the issue/feature this PR addresses: This PR resolves an integration failure with the Nilvera e-invoicing provider when a company’s primary currency is configured to a foreign currency…
Description of the issue/feature this PR addresses: This PR resolves an integration failure with the Nilvera e-invoicing provider when a company’s primary currency is configured to a foreign currency (e.g., USD) rather than the local currency (TRY). Nilvera strictly requires a valid exchange rate relative to Turkish Lira (TRY) to be included inside the XML nodes of every posted invoice utilizing a foreign currency. Functions affected: def _add_invoice_exchange_rate_nodes(self, document_node, vals): def _l10n_tr_get_currency_conversion_rate(self, invoice): Current behavior before PR: When generating an invoice where both the company's main currency and the invoice currency are foreign (e.g., USD), the system does not calculate or embed a TRY conversion/exchange rate into the invoice payload. Because this mandatory local currency reference mapping is missing, Nilvera rejects the invoice submission. Desired behavior after PR is merged: For every invoice processed via the Nilvera localization, the system will explicitly calculate and inject the exchange rate between the active invoice currency and TRY into the posted document nodes, regardless of what the underlying company's primary currency is set to. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271129 Forward-Port-Of: odoo/odoo#270531
This change prevents signed-in website visitors from being unexpectedly logged out after browsing pages when a guest chat session already exists. It improves reliability of the website experience by making sure guest tracking does not override an authenticated user’s session.
Original PR description
Before this commit, browsing any page of the website while having a guest cookie set would log out the user after a few seconds. Steps to reproduce: 1. While logged out start a live chat on "/contactus" (or get a guest cookie in any other way). 2. Log in as Marc Demo 3. Open "/contactus" (or any other website page) 4. Refresh after a few seconds -> logged out This happens since [1], which refactored the visitor page tracking. In said change, the override of `track` in `website_livechat` adds the guest to the request context (using `force_guest_env`) if the guest cookie is found. This is done to correctly connect the guest and visitor records, but will log out an authenticated user that has the guest cookie. This commit fixes the issue by only forcing the guest env if the user is not authenticated. [1] https://github.com/odoo/odoo/pull/247438 task-6369344 Forward-Port-Of: odoo/odoo#274704
This change fixes an issue where unreserving a manufacturing order could accidentally reset byproduct quantities to zero. As a result, producing the order again now correctly creates the expected byproducts, avoiding missing output and manual rework.
Original PR description
On a mo that has byproducts, if you unreserve, it will also set the quantity of byproducts to 0 Steps to reproduce: ------------------- * Create a Products main, component and byproduct * Create a…
On a mo that has byproducts, if you unreserve, it will also set the quantity of byproducts to 0 Steps to reproduce: ------------------- * Create a Products main, component and byproduct * Create a bom for main with component as component and byproduct as byproduct * Create and confirm a mo for main * Set qty_producing to quantity ot produce * click on "Unreserve" (do_unreserve) * click on "Check availability" (action_assign) * Produce All -> the byproducts will not be produced. Observation: ------------- When updating the qty_producing value it will also update the quantity of the byproducts moves: https://github.com/odoo/odoo/blob/77b180e8251fb8019e0034e1c2f485fd2c34ea4e/addons/mrp/models/mrp_production.py#L892-L893 https://github.com/odoo/odoo/blob/77b180e8251fb8019e0034e1c2f485fd2c34ea4e/addons/mrp/models/mrp_production.py#L1350 https://github.com/odoo/odoo/blob/77b180e8251fb8019e0034e1c2f485fd2c34ea4e/addons/stock/models/stock_move.py#L2382 The quantity on the byproducts move has been updated. When clicking on Unreserve it will call do_unreserve, https://github.com/odoo/odoo/blob/aca2e226143487b421f79194d677bb48d5da1358/addons/mrp/models/mrp_production.py#L2297-L2298 It will filters the moves that do not need to be unreserved and select the others: https://github.com/odoo/odoo/blob/aca2e226143487b421f79194d677bb48d5da1358/addons/stock/models/stock_move.py#L900 and it will unlink all the sml from the moves: https://github.com/odoo/odoo/blob/aca2e226143487b421f79194d677bb48d5da1358/addons/stock/models/stock_move.py#L919 Which will set the quantity on the byproduct moves to 0. When Producing all (button_mark_done) since the qty_producing has already been set, it will simply mark the byproduct move has picked. https://github.com/odoo/odoo/blob/aca2e226143487b421f79194d677bb48d5da1358/addons/mrp/models/mrp_production.py#L1323-L1324 In our case, this means that the no byproducts will be created since, the quantity was previously set to 0 opw-6296562 Forward-Port-Of: odoo/odoo#273739 Forward-Port-Of: odoo/odoo#272216
18 changes
Enhancements to existing features
Self-order kiosk orders are now only sent to the Belgian fiscal blackbox once they are fully paid. This supports flows where customers choose to pay at the counter or use other payment methods, avoiding premature fiscal registration.
Original PR description
This commits adapts the code in confirmation_page.js to not send the order to the blackbox from the kiosk if the order is not in paid state. task-id: 5960666 Forward-Port-Of: odoo/enterprise#119724 Forward-Port-Of: odoo/enterprise#117585
The bank reconciliation screen now sends less unnecessary data to the browser and moves some heavy calculations to the server. This should make opening the widget faster on very large databases, helping accounting teams work with bank statements more smoothly.
Original PR description
When opening the bank rec widget on huge DB's, it takes
a lot of time to load everything.
This commit aims to improve the loading performances by
removing some JS fields:
1 - reconciled_lines_ids: We only use the first element of
this recordset in JS, so we add a new computed field
to only send 1 record to the JS
2 - hasAttachment: replace the long JS computation of
`get hasAttachment` with a python computed field.
3 - Replace matched_credit_ids and matched_debit_ids
with exchange_diff_partial_ids.
Linked:https://github.com/odoo/odoo/pull/269119
task-6275945
Forward-Port-Of: odoo/enterprise#119557Xendit payments now cover the Singapore market with PayNow (SGQR) support, and merchants can also accept SGD and USD. The update also adds support for additional card brands, including JCB and AMEX in supported markets, helping expand payment options for customers.
Original PR description
This commit expands Xendit support to include the Singaporean market and additional card brands. The following changes were made: - Added support for the PayNow (SGQR) payment method. - Added SGD and USD to the list of supported currencies. - Added JCB and AMEX to the supported card brands (available for some markets). - Updated the base payment provider data for Xendit to include PayNow. Task-5964309 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274769 Forward-Port-Of: odoo/odoo#253542
Customers can now choose to pay at the counter even when a payment method has already been set up in self-order. This gives businesses more flexibility at checkout and avoids blocking mixed payment flows.
Original PR description
pos*: point_of_sale, pos_self_order This commit allows the user to allow his customer to pay at the counter even if they already have payment method set in the self order. task-id: 5960666 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#268893 Forward-Port-Of: odoo/odoo#250364
Resolved issues and error corrections
This fix prevents Australian payroll users from seeing an error when recalculating a payslip after an employee's Income Stream Type has changed. Existing payslips now refresh that value before calculation, helping payroll processing continue smoothly and reducing manual disruption.
Original PR description
When an employee's Income Stream Type is changed after a payslip has been created, computing the sheet for payslip will raise a traceback. Steps to reproduce the error: - Install…
When an employee's Income Stream Type is changed after a payslip has been created, computing the sheet for payslip will raise a traceback. Steps to reproduce the error: - Install ``l10n_au_hr_payroll_account`` module with demo data - Switch to ``My Australian Company`` company - Create a new payslip for ``Dennis Cactus`` Employee > Save - Go to Employees > Open the ``Dennis Cactus`` employee > In Payroll tab, Income Stream Type: Other specified payments > Save - Go back to payslip > click the compute sheet button Traceback: ```py KeyError: 'OSP' ``` https://github.com/odoo/enterprise/blob/13e64e0cb7f566cbbb46109fe1c218eb7a14eead/l10n_au_hr_payroll/models/hr_payslip.py#L175-L178 The ``l10n_au_income_stream_type`` field on the payslip is a computed field that only depends on ``employee_id``. As a result, changing the employee's Income Stream Type does not trigger a recomputation of the corresponding field on existing payslip. So, when the ``payslip_ytd_totals`` field is computed, it uses the old value of ``l10n_au_income_stream_type`` field at [1], The resulting ``payslip_ytd_totals`` is then used to build the ``totals`` dictionary, and eventually, when the employee's current ``income_stream_type`` is used to access ``totals``, the mismatch key leads to the above traceback. https://github.com/odoo/enterprise/blob/13e64e0cb7f566cbbb46109fe1c218eb7a14eead/l10n_au_hr_payroll_account/models/hr_payslip.py#L75-L88 [1]: https://github.com/odoo/enterprise/blob/13e64e0cb7f566cbbb46109fe1c218eb7a14eead/l10n_au_hr_payroll/models/hr_payslip.py#L269-L272 solution: I added ``l10n_au_income_stream_type`` to ``add_to_compute()`` in ``compute_sheet()``. This ensures that stale values of ``l10n_au_income_stream_type`` on existing payslips are recomputed when the payslip sheet is computed. sentry-7536819310 Forward-Port-Of: odoo/enterprise#123288 Forward-Port-Of: odoo/enterprise#120143
Vendor bills imported from Chilean electronic invoice XML files now use the correct foreign-currency amounts instead of incorrectly taking peso values. This prevents overstated or understated bills when companies transact in currencies such as UF, improving accounting accuracy.
Original PR description
**STEP TO REPRODUCE** 1. Create a invoice to a chilian company, using another currency (for example UF, don't forget setup up a currency rate). 2. Confirm. 3. Download the xml in the chatter, and import it as a vendor bill. 4. Notice the imported bill amount are wrong (Pesos amount are used, with the currency being UF). opw-6269662 Forward-Port-Of: odoo/enterprise#123179 Forward-Port-Of: odoo/enterprise#119664
Belgian payroll no longer applies a special public holiday eligibility rule for time credit contracts because it lacked a legal basis. This helps ensure payroll calculations follow the correct legal interpretation and avoids unsupported holiday entitlement handling.
Original PR description
The specific code related to the eligibility to public holiday for time credit contracts has no legal base. This commit removes it. task-6370653 Forward-Port-Of: odoo/enterprise#123303
Deliveries using DHL from a company different than the main company now send a valid commercial invoice number. This prevents DHL validation errors and allows affected international shipments to be processed correctly.
Original PR description
Issue ----- When validating a delivery in a different company from the main one, the commercial invoice's number field is incorrect, which raises an error on DHL end.…
Issue ----- When validating a delivery in a different company from the main one, the commercial invoice's number field is incorrect, which raises an error on DHL end. `content/exportDeclaration/invoice/number: expected type: String, found: Boolean` Steps to reproduce ----- - Create a Belgian company - Setup DHL - DHL Product D - Express Worldwide - Dutiable Material enabled - Create an amrican customer - Deliver a product to the american customer > Validation Error Cause ----- The field is populated in https://github.com/odoo/enterprise/blob/cf3c2fce8a6b7b2d7547d44a0e4423f887986d52/delivery_dhl_rest/models/dhl_request.py#L204 The problem is that `next_by_code` uses the company found in the env, whereas the sequence's company is the main one, so it is not found when doing https://github.com/odoo/odoo/blob/e3b0ca11d99b2ef819cdad68b169112cd73668b6/odoo/addons/base/models/ir_sequence.py#L287 ----- Ticket: opw-6171886 Forward-Port-Of: odoo/enterprise#123170 Forward-Port-Of: odoo/enterprise#118379
This change prevents WhatsApp message lists from failing when a message is linked to a business document the user cannot access directly. Existing WhatsApp message visibility rules still determine who can see messages, so regular users only see their own messages while WhatsApp administrators can see all.
Original PR description
The `body` field on `whatsapp.message` was defined with `related_sudo=False` with the intent of restricting access to messages from restricted records. However, this was never actually providing any…
The `body` field on `whatsapp.message` was defined with `related_sudo=False` with the intent of restricting access to messages from restricted records. However, this was never actually providing any security value because [`mail.message.fetch()`] was overriding it with `self.sudo()` till `v19.1`, meaning the body was always fetched as superuser regardless:
```py
web_search_read() -> search_fetch()
-> fields.py _compute_related()
-> record[self.related_field.name] # triggers fetch of mail.message.body
-> models.py _fetch_field()
-> mail_message.py fetch()
-> self = self.sudo() # sudo hack overrides related_sudo=False silently
```
In `v19.2`, the `fetch()` sudo hack was intentionally removed (see commit odoo/odoo@4727f12d274a0b2d7c455363d189565bd8fb2e7a) as access rights are now cached and can be checked without a performance penalty. This exposed the broken `related_sudo=False` which now causes an `AccessError` when trying to read the body of a `whatsapp.message` whose linked `mail.message` points to a document the current user cannot access (e.g. `purchase.order`).
Access control on `whatsapp.message` is already correctly enforced at the `ir.rule` level:
- Regular users can only see messages they created (`create_uid = user.id`)
- WA Admins can see all messages
We have upgrade requests failing on this issue: TBG-[2765]
[`mail.message.fetch()`]: https://github.com/odoo/odoo/blob/saas-19.1/addons/mail/models/mail_message.py#L812-L819
[2765]: https://upgrade.odoo.com/odoo/tbg/2765?debug=1
Forward-Port-Of: odoo/enterprise#119867Point of Sale now fetches Urban Piper and platform orders together instead of making extra separate requests. This reduces waiting time and unnecessary server calls when retrieving orders, improving reliability and responsiveness for restaurant and delivery workflows.
Original PR description
Issue: pos_urban_piper overrode getServerOrders() to add a separate loadServerOrders() call for it's own orders before delegating to super, resulting in up to an additional sequential RPCs on every order fetch. Fix: Extract the base query domain into a new overridable getServerOrdersDomain() method. Each module overrides it to OR in its own domain via Domain.or([super.getServerOrdersDomain(), extraDomain]), so all orders are fetched in a single RPC call instead of three. Task-6284860 Forward-Port-Of: odoo/enterprise#123160 Forward-Port-Of: odoo/enterprise#120001
The timesheet grid now uses each employee's own working schedule to show public holidays, weekends, and approved time off as unavailable. This prevents employees from seeing incorrect availability based on the company default schedule and keeps Timesheets aligned with Time Off.
Original PR description
Steps to Reproduce --- - Create two different working schedules with different public holidays - Assign employees to specific working schedules - Set company default working schedule to a different…
Steps to Reproduce --- - Create two different working schedules with different public holidays - Assign employees to specific working schedules - Set company default working schedule to a different schedule - Login as employee with specific working schedule - Navigate to Timesheets app -> My Timesheets - Observe public holidays and personal time-off displayed in the timesheet grid Issue --- - The timesheet grid displays unavailable dates (public holidays, weekends) from the company's default working schedule instead of the employee's assigned working schedule. - Personal time-off requests are not reflected as unavailable dates in the timesheet grid. Current Behaviour --- - Public holidays shown are always from the company's default working schedule, ignoring employee-specific working schedule assignments. - Employee's approved time-off requests don't appear as unavailable in the timesheet. Expected Behaviour --- - Public holidays should display based on the employee's assigned working schedule, with company schedule as fallback only when no specific schedule is assigned. - Employee's personal time-off requests should appear as unavailable dates. - This should align with Time Off app behavior. Fix --- - Included employee-specific work interval calculation with personal time-off requests. - Added support for contract-based calendar changes and calendar validity periods. - Implemented proper fallback when valid intervals are not found. task-4997080 Forward-Port-Of: odoo/enterprise#123331 Forward-Port-Of: odoo/enterprise#95458
This change prevents an access error that could appear during subcontracting operations when handling serial numbers. It helps users complete the process smoothly without running into permission issues.
Original PR description
opw-6316136 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#274830 Forward-Port-Of: odoo/odoo#271739
This change prevents the website editor from crashing when a user opens the Documents tab after selecting an icon. It improves the media picker so it correctly distinguishes icons from document attachments, making the replace flow more reliable.
Original PR description
### Steps to reproduce: - Open the website editor and insert a snippet. - Inside the snippet, add an image and a document via /media. - Select the image, click Replace, pick an icon. - Click the icon, then click Replace from the sidebar. - In the dialog, click the Documents tab. - Traceback occurs. ### Root cause: - Both icon and document box elements are `<span>` tags. `DocumentSelector` inherits `selectInitialMedia()` from `FileSelector` which only checks the tag name, so it incorrectly returns true for icons. This causes `fetchAttachments` to call `querySelector(a)` on the icon span, which returns null and crashes. ### Solution: - Override `selectInitialMedia()` in `DocumentSelector` to also check for the `o_file_box` class. Add optional chaining on `querySelector(a)` as a safety net. task-6310147 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270548
This update improves the Point of Sale experience by making product cards larger so long names display correctly. It also automatically selects single-option product variants and ensures saved interface settings are restored correctly, so product details appear properly in the cart and receipt.
Original PR description
This commit fixes multiple issues: 1. Product visibility: Product card are too small, we increase their size so that big product name can be displayed properly. 2. Variant selection: When a product has attributes with only one choice the choice is not selected automatically. We select it in this commit such that the information is displayed properly in the cart and receipt. 3. uiState not updated: When we restore the uiState of a record, we do not take into account that the uiState architecture might have changed. We now init the uiState before restoring it so new fields are properly initialized even when not present in the saved uiState. task-id: 6344288 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272843
When a task is moved to another project, followers now inherit the notification settings of the new project. This ensures people continue receiving the right updates, such as stage changes, instead of missing important task activity.
Original PR description
Steps to reproduce: - 1. Create projects A and B. 2. Add a user as a follower of project B and select specific notification subtypes (e.g., 'Stage Changed'). 3. Create a task in project A and add the same user as a follower(defaulting to 'Discussions'). 4. Move the task from project A to project B. Issue: - The follower's subscription preferences on the task do not reflect their project-level settings after the move. In the example above, the user remains subscribed only to 'Discussions' and misses 'Stage Changed' updates. Cause: - The default auto-subscription logic skips existing followers. When moving a task, this prevents the system from adding the new project's notification preferences to users who were already following the task. Fix: - Override `_message_auto_subscribe` in project.task to the `update` policy when the `project_id` is changed. task-5877507 Forward-Port-Of: odoo/odoo#248224
This change ensures e-invoices sent through the Turkish Nilvera integration always include the exchange rate to TRY, even when the company’s main currency is not TRY. It prevents invoice rejections by making the XML meet Nilvera’s required currency rules.
Original PR description
Description of the issue/feature this PR addresses: This PR resolves an integration failure with the Nilvera e-invoicing provider when a company’s primary currency is configured to a foreign currency…
Description of the issue/feature this PR addresses: This PR resolves an integration failure with the Nilvera e-invoicing provider when a company’s primary currency is configured to a foreign currency (e.g., USD) rather than the local currency (TRY). Nilvera strictly requires a valid exchange rate relative to Turkish Lira (TRY) to be included inside the XML nodes of every posted invoice utilizing a foreign currency. Functions affected: def _add_invoice_exchange_rate_nodes(self, document_node, vals): def _l10n_tr_get_currency_conversion_rate(self, invoice): Current behavior before PR: When generating an invoice where both the company's main currency and the invoice currency are foreign (e.g., USD), the system does not calculate or embed a TRY conversion/exchange rate into the invoice payload. Because this mandatory local currency reference mapping is missing, Nilvera rejects the invoice submission. Desired behavior after PR is merged: For every invoice processed via the Nilvera localization, the system will explicitly calculate and inject the exchange rate between the active invoice currency and TRY into the posted document nodes, regardless of what the underlying company's primary currency is set to. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271129 Forward-Port-Of: odoo/odoo#270531
This change prevents paid point-of-sale orders from creating duplicate payment lines when they are synced again. It also avoids a crash that could happen if the system tried to process a payment that had already been removed, making payment updates more reliable.
Original PR description
A paid order can reach `sync_from_ui` more than once. In that case the order falls into the else branch of `sync_from_ui` and its payments are re-processed through `process_saved_payments`, which was…
A paid order can reach `sync_from_ui` more than once. In that case the order falls into the else branch of `sync_from_ui` and its payments are re-processed through `process_saved_payments`, which was not idempotent and led to two issues: - The change/return cash payment is generated server-side in `_process_payment_lines` and has no uuid, so `_update_lines` cannot deduplicate it. Each extra sync therefore created an additional return payment. It is now removed before being recomputed, which also keeps it correct when the payments are edited after payment (new return amount, or no change at all). - `_update_lines` replays the client commands as-is. On a second sync, a delete command (`[2, id]`) targets a payment that the first sync already removed, and `_create_pm_change_log` crashed with a MissingError while reading the deleted record. Update/delete/unlink commands referencing records that no longer exist are now skipped. Note that delete/unlink commands only carry 2 elements, so the check runs before the `len(line) < 3` guard. Steps to reproduce: - Pay an order, then re-sync it (or edit its payments and sync again). => the return payment was duplicated, or a MissingError was raised. opw-6327912 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272539
This update prevents manufacturing byproducts from being reset to zero when a manufacturing order is unreserved and then re-checked. As a result, businesses can safely unreserve and replan production without losing expected byproduct output.
Original PR description
On a mo that has byproducts, if you unreserve, it will also set the quantity of byproducts to 0 Steps to reproduce: ------------------- * Create a Products main, component and byproduct * Create a…
On a mo that has byproducts, if you unreserve, it will also set the quantity of byproducts to 0 Steps to reproduce: ------------------- * Create a Products main, component and byproduct * Create a bom for main with component as component and byproduct as byproduct * Create and confirm a mo for main * Set qty_producing to quantity ot produce * click on "Unreserve" (do_unreserve) * click on "Check availability" (action_assign) * Produce All -> the byproducts will not be produced. Observation: ------------- When updating the qty_producing value it will also update the quantity of the byproducts moves: https://github.com/odoo/odoo/blob/77b180e8251fb8019e0034e1c2f485fd2c34ea4e/addons/mrp/models/mrp_production.py#L892-L893 https://github.com/odoo/odoo/blob/77b180e8251fb8019e0034e1c2f485fd2c34ea4e/addons/mrp/models/mrp_production.py#L1350 https://github.com/odoo/odoo/blob/77b180e8251fb8019e0034e1c2f485fd2c34ea4e/addons/stock/models/stock_move.py#L2382 The quantity on the byproducts move has been updated. When clicking on Unreserve it will call do_unreserve, https://github.com/odoo/odoo/blob/aca2e226143487b421f79194d677bb48d5da1358/addons/mrp/models/mrp_production.py#L2297-L2298 It will filters the moves that do not need to be unreserved and select the others: https://github.com/odoo/odoo/blob/aca2e226143487b421f79194d677bb48d5da1358/addons/stock/models/stock_move.py#L900 and it will unlink all the sml from the moves: https://github.com/odoo/odoo/blob/aca2e226143487b421f79194d677bb48d5da1358/addons/stock/models/stock_move.py#L919 Which will set the quantity on the byproduct moves to 0. When Producing all (button_mark_done) since the qty_producing has already been set, it will simply mark the byproduct move has picked. https://github.com/odoo/odoo/blob/aca2e226143487b421f79194d677bb48d5da1358/addons/mrp/models/mrp_production.py#L1323-L1324 In our case, this means that the no byproducts will be created since, the quantity was previously set to 0 opw-6296562 Forward-Port-Of: odoo/odoo#273739 Forward-Port-Of: odoo/odoo#272216
10 changes
Enhancements to existing features
Event teams can now print attendee badges in A4 PDF format directly from the registration desk. This also extends badge printing support to Point of Sale, helping on-site teams manage event check-ins and badge distribution more flexibly.
Original PR description
This PR adds the support for A4 pdf badge printing through the registration desk. Requested for OXP in Kenya See https://github.com/odoo/odoo/pull/275021
The bank reconciliation widget now loads less unnecessary data when opened, especially on very large databases. This should make reconciliation screens appear faster and feel more responsive for accounting users.
Original PR description
When opening the bank rec widget on huge DB's, it takes
a lot of time to load everything.
This commit aims to improve the loading performances by
removing some JS fields:
1 - reconciled_lines_ids: We only use the first element of
this recordset in JS, so we add a new computed field
to only send 1 record to the JS
2 - hasAttachment: replace the long JS computation of
`get hasAttachment` with a python computed field.
3 - Replace matched_credit_ids and matched_debit_ids
with exchange_diff_partial_ids.
Linked:https://github.com/odoo/odoo/pull/269119
task-6275945
Forward-Port-Of: odoo/enterprise#119557Resolved issues and error corrections
Fixes an error that could occur when changing quantities on confirmed Field Service sales orders while an automated incoming-message rule is active. The change keeps unnecessary chatter messages suppressed without breaking automation, improving reliability for sales and field service workflows.
Original PR description
Steps to reproduce: ---------------------------------------- 1. Install `industry_fsm_sale` and `base_automation` modules 2. Create a product with: * Type: Service * Create on order: Task * Project:…
Steps to reproduce:
----------------------------------------
1. Install `industry_fsm_sale` and `base_automation` modules
2. Create a product with:
* Type: Service
* Create on order: Task
* Project: Field Service
3. Create an automation rule with:
* Model: Sales order
* Trigger: Incoming message
4. Create and confirm a sale order with this product
5. Add another product to the SO via the catalog view:
* Change the quantity to 2 or more
Observation:
----------------------------------------
Traceback occurs:
```
File '/home/odoo/src/odoo/addons/base_automation/models/base_automation.py', line 871, in _message_post
message_sudo = message.sudo().with_context(active_test=False)
AttributeError: 'bool' object has no attribute 'sudo'
```
Root Cause:
----------------------------------------
* Catalog qty change calls `set_fsm_quantity()` method
* Setting `fsm_quantity` triggers its inverse `_inverse_fsm_quantity()`, which writes the new qty to the SOL, but passes `fsm_no_message_post=True` in context to suppress chatter noise
https://github.com/odoo/enterprise/blob/ac5d670832a5e0db714c0bd056e1406b50bb4c17/industry_fsm_sale/models/product_product.py#L72-L83
* `sale.order.line.write()` detects a qty change on a confirmed order and calls `_update_line_quantity()`, which posts a message on the parent sale order
* FSM's `message_post` override sees the context flag and returns `False`
* When `base_automation` has an `on_message_received` rule on `sale.order`, it wraps `message_post` at registry load time. That wrapper calls `sudo()` on whatever `message_post` returns, Which was `False`
Solution:
----------------------------------------
Return `self.env['mail.message']` (empty recordset) instead of False, it's still falsy, but it's a proper ORM object that `sudo()` can be called on
opw-6276916
Forward-Port-Of: odoo/enterprise#123010
Forward-Port-Of: odoo/enterprise#119542This fix prevents Australian payroll payslip calculations from failing when an employee's Income Stream Type is changed after a payslip has already been created. The payslip now refreshes that information before calculation, helping payroll teams complete processing without unexpected errors.
Original PR description
When an employee's Income Stream Type is changed after a payslip has been created, computing the sheet for payslip will raise a traceback. Steps to reproduce the error: - Install…
When an employee's Income Stream Type is changed after a payslip has been created, computing the sheet for payslip will raise a traceback. Steps to reproduce the error: - Install ``l10n_au_hr_payroll_account`` module with demo data - Switch to ``My Australian Company`` company - Create a new payslip for ``Dennis Cactus`` Employee > Save - Go to Employees > Open the ``Dennis Cactus`` employee > In Payroll tab, Income Stream Type: Other specified payments > Save - Go back to payslip > click the compute sheet button Traceback: ```py KeyError: 'OSP' ``` https://github.com/odoo/enterprise/blob/13e64e0cb7f566cbbb46109fe1c218eb7a14eead/l10n_au_hr_payroll/models/hr_payslip.py#L175-L178 The ``l10n_au_income_stream_type`` field on the payslip is a computed field that only depends on ``employee_id``. As a result, changing the employee's Income Stream Type does not trigger a recomputation of the corresponding field on existing payslip. So, when the ``payslip_ytd_totals`` field is computed, it uses the old value of ``l10n_au_income_stream_type`` field at [1], The resulting ``payslip_ytd_totals`` is then used to build the ``totals`` dictionary, and eventually, when the employee's current ``income_stream_type`` is used to access ``totals``, the mismatch key leads to the above traceback. https://github.com/odoo/enterprise/blob/13e64e0cb7f566cbbb46109fe1c218eb7a14eead/l10n_au_hr_payroll_account/models/hr_payslip.py#L75-L88 [1]: https://github.com/odoo/enterprise/blob/13e64e0cb7f566cbbb46109fe1c218eb7a14eead/l10n_au_hr_payroll/models/hr_payslip.py#L269-L272 solution: I added ``l10n_au_income_stream_type`` to ``add_to_compute()`` in ``compute_sheet()``. This ensures that stale values of ``l10n_au_income_stream_type`` on existing payslips are recomputed when the payslip sheet is computed. sentry-7536819310 Forward-Port-Of: odoo/enterprise#123288 Forward-Port-Of: odoo/enterprise#120143
Blank US checks now print the same payment stub lines that already appeared on pre-printed checks. The check layout was also adjusted so the bottom section fits on a single page, reducing printing errors and wasted paper.
Original PR description
See individual commits. task-6359599 Forward-Port-Of: odoo/enterprise#123144
Vendor bills imported from Chilean electronic invoices now use the correct amount when the original invoice is in a non-peso currency such as UF. This prevents overstated or understated bills caused by mixing peso totals with the foreign currency on import.
Original PR description
**STEP TO REPRODUCE** 1. Create a invoice to a chilian company, using another currency (for example UF, don't forget setup up a currency rate). 2. Confirm. 3. Download the xml in the chatter, and import it as a vendor bill. 4. Notice the imported bill amount are wrong (Pesos amount are used, with the currency being UF). opw-6269662 Forward-Port-Of: odoo/enterprise#123179 Forward-Port-Of: odoo/enterprise#119664
Restaurant platform orders are now included in the normal order fetch instead of requiring extra back-to-back calls. This reduces waiting time and server load when point of sale retrieves orders, especially for UrbanPiper integrations.
Original PR description
Issue: pos_urban_piper overrode getServerOrders() to add a separate loadServerOrders() call for it's own orders before delegating to super, resulting in up to an additional sequential RPCs on every order fetch. Fix: Extract the base query domain into a new overridable getServerOrdersDomain() method. Each module overrides it to OR in its own domain via Domain.or([super.getServerOrdersDomain(), extraDomain]), so all orders are fetched in a single RPC call instead of three. Task-6284860 Forward-Port-Of: odoo/enterprise#123160 Forward-Port-Of: odoo/enterprise#120001
Fixed DHL delivery validation for shipments created under a company different from the main company. Commercial invoices now receive a valid invoice number, preventing DHL rejection errors for international dutiable deliveries.
Original PR description
Issue ----- When validating a delivery in a different company from the main one, the commercial invoice's number field is incorrect, which raises an error on DHL end.…
Issue ----- When validating a delivery in a different company from the main one, the commercial invoice's number field is incorrect, which raises an error on DHL end. `content/exportDeclaration/invoice/number: expected type: String, found: Boolean` Steps to reproduce ----- - Create a Belgian company - Setup DHL - DHL Product D - Express Worldwide - Dutiable Material enabled - Create an amrican customer - Deliver a product to the american customer > Validation Error Cause ----- The field is populated in https://github.com/odoo/enterprise/blob/cf3c2fce8a6b7b2d7547d44a0e4423f887986d52/delivery_dhl_rest/models/dhl_request.py#L204 The problem is that `next_by_code` uses the company found in the env, whereas the sequence's company is the main one, so it is not found when doing https://github.com/odoo/odoo/blob/e3b0ca11d99b2ef819cdad68b169112cd73668b6/odoo/addons/base/models/ir_sequence.py#L287 ----- Ticket: opw-6171886 Forward-Port-Of: odoo/enterprise#123170 Forward-Port-Of: odoo/enterprise#118379
Employees and managers can now request an appraisal even when the scheduled next appraisal date has already passed. This removes an unnecessary blocking error and helps teams process overdue appraisals without needing special permissions to change employee settings.
Original PR description
# How to reproduce You need to simulate the fact that you are creating an appraisal late so either : A) Directly edit the `next_appraisal_date` in SQL B) Go to Employee App > any Employee > Settings,…
# How to reproduce You need to simulate the fact that you are creating an appraisal late so either : A) Directly edit the `next_appraisal_date` in SQL B) Go to Employee App > any Employee > Settings, set Next Appraisal Date to tomorrow and wait for 2 days Then : - Click on Request Appraisal - Save # The problem An error is shown saying "You cannot set 'Next Appraisal Date' in the past.". You can workaround this by changing the Next Appraisal Date to a date in the future, but the problem is not every user has the right to do this. # Cause `next_appraisal_date` is also defined in hr.appraisal as a relate field of hr.employee : https://github.com/odoo/enterprise/blob/0226ad15abc8db70f8e379fddec3d83d15749c85/hr_appraisal/models/hr_appraisal.py#L56-L57 When creating an hr.appraisal, `next_appraisal_date` is present in `vals_list` because it is defined in the view since : https://github.com/odoo/enterprise/commit/58fba3098f33db82dfbccca2db229550402ed3ab https://github.com/odoo/enterprise/blob/0226ad15abc8db70f8e379fddec3d83d15749c85/hr_appraisal/views/hr_appraisal_views.xml#L92 This triggers a write on `next_appraisal_date` of hr.employee which triggers a constraint : https://github.com/odoo/enterprise/blob/0226ad15abc8db70f8e379fddec3d83d15749c85/hr_appraisal/models/hr_employee.py#L81-L85 opw-6147865 Forward-Port-Of: odoo/enterprise#114876
Bank reconciliation entries that apply tax models now correctly show the taxable base amount immediately. This prevents tax lines from appearing with a misleading zero base amount until a manual reset is performed, improving accounting accuracy and reporting clarity.
Original PR description
### Steps to reproduce the issue: 1. Download Accounting 2. Go to Journal entries and create a new one 3. Click Toggle Studio button and go to the view to add the tax_base_amount field to the list of…
### Steps to reproduce the issue: 1. Download Accounting 2. Go to Journal entries and create a new one 3. Click Toggle Studio button and go to the view to add the tax_base_amount field to the list of existing fields 4. Add 2 lines (example): 1. account Product Sales with 1000 dollars credit and 15% tax under Tax column 2. account Bank with 1000 dollars debit 5. Go to Dashboard > Bank > Click the 3 dots of one random bank matching line and click on Manage Models 6. Go to bank fees and add the 15% tax 7. Go back to bank reconciliation and create a new one of 2000 dollars with label bank fees (it will associate the tax automatically) 8. Go back to Journal Entries, group by Journal and search for the transaction of 2000 sollars for account Bank 9. Problem: see that the Base Amount for the 15% bank fees lines (251000 Tax Received account) is 0. Clicking on Reset to draft button the base amount column is automatically updated but this should happen automatically ### Cause of the issue: This occurs because the _lines_prepare_tax_line method in account.bank.statement.line fails to map this field in its return dictionary. ### Reason to introduce the fix: Currently, when applying a reconciliation model with taxes the generated tax lines incorrectly record a tax_base_amount of $0.00. Instead, it should be displayed and calculated. opw-6220948 Forward-Port-Of: odoo/enterprise#122139
11 changes
Enhancements to existing features
The Finland localization now includes the new 13.5% tax rate for affected goods and services, replacing situations where 14% previously applied. This helps Finnish businesses keep tax reporting and exports aligned with the latest VAT requirements.
Original PR description
backport of 5324615 As in Finland the tax rate will change from 14 to 13.5 on certain goods and services those taxes and the corresponding tax group were added to the l10n task-6332565 Forward-Port-Of: odoo/enterprise#123098
The bank reconciliation screen now loads less unnecessary data, making it faster to open on very large databases. This improves day-to-day accounting workflows by reducing waiting time without changing the reconciliation process.
Original PR description
When opening the bank rec widget on huge DB's, it takes
a lot of time to load everything.
This commit aims to improve the loading performances by
removing some JS fields:
1 - reconciled_lines_ids: We only use the first element of
this recordset in JS, so we add a new computed field
to only send 1 record to the JS
2 - hasAttachment: replace the long JS computation of
`get hasAttachment` with a python computed field.
3 - Replace matched_credit_ids and matched_debit_ids
with exchange_diff_partial_ids.
Linked:https://github.com/odoo/odoo/pull/269119
task-6275945
Forward-Port-Of: odoo/enterprise#119557Resolved issues and error corrections
Bank reconciliation entries that include taxes now show the correct tax base amount immediately. This prevents tax-related journal lines from displaying zero values and gives accounting users accurate figures without needing to reset entries to draft.
Original PR description
### Steps to reproduce the issue: 1. Download Accounting 2. Go to Journal entries and create a new one 3. Click Toggle Studio button and go to the view to add the tax_base_amount field to the list of…
### Steps to reproduce the issue: 1. Download Accounting 2. Go to Journal entries and create a new one 3. Click Toggle Studio button and go to the view to add the tax_base_amount field to the list of existing fields 4. Add 2 lines (example): 1. account Product Sales with 1000 dollars credit and 15% tax under Tax column 2. account Bank with 1000 dollars debit 5. Go to Dashboard > Bank > Click the 3 dots of one random bank matching line and click on Manage Models 6. Go to bank fees and add the 15% tax 7. Go back to bank reconciliation and create a new one of 2000 dollars with label bank fees (it will associate the tax automatically) 8. Go back to Journal Entries, group by Journal and search for the transaction of 2000 sollars for account Bank 9. Problem: see that the Base Amount for the 15% bank fees lines (251000 Tax Received account) is 0. Clicking on Reset to draft button the base amount column is automatically updated but this should happen automatically ### Cause of the issue: This occurs because the _lines_prepare_tax_line method in account.bank.statement.line fails to map this field in its return dictionary. ### Reason to introduce the fix: Currently, when applying a reconciliation model with taxes the generated tax lines incorrectly record a tax_base_amount of $0.00. Instead, it should be displayed and calculated. opw-6220948 Forward-Port-Of: odoo/enterprise#122139
This fix prevents Australian payroll users from seeing an error when recalculating a payslip after an employee's Income Stream Type has been updated. Payslips now refresh the relevant income stream information before calculation, helping payroll teams complete processing reliably.
Original PR description
When an employee's Income Stream Type is changed after a payslip has been created, computing the sheet for payslip will raise a traceback. Steps to reproduce the error: - Install…
When an employee's Income Stream Type is changed after a payslip has been created, computing the sheet for payslip will raise a traceback. Steps to reproduce the error: - Install ``l10n_au_hr_payroll_account`` module with demo data - Switch to ``My Australian Company`` company - Create a new payslip for ``Dennis Cactus`` Employee > Save - Go to Employees > Open the ``Dennis Cactus`` employee > In Payroll tab, Income Stream Type: Other specified payments > Save - Go back to payslip > click the compute sheet button Traceback: ```py KeyError: 'OSP' ``` https://github.com/odoo/enterprise/blob/13e64e0cb7f566cbbb46109fe1c218eb7a14eead/l10n_au_hr_payroll/models/hr_payslip.py#L175-L178 The ``l10n_au_income_stream_type`` field on the payslip is a computed field that only depends on ``employee_id``. As a result, changing the employee's Income Stream Type does not trigger a recomputation of the corresponding field on existing payslip. So, when the ``payslip_ytd_totals`` field is computed, it uses the old value of ``l10n_au_income_stream_type`` field at [1], The resulting ``payslip_ytd_totals`` is then used to build the ``totals`` dictionary, and eventually, when the employee's current ``income_stream_type`` is used to access ``totals``, the mismatch key leads to the above traceback. https://github.com/odoo/enterprise/blob/13e64e0cb7f566cbbb46109fe1c218eb7a14eead/l10n_au_hr_payroll_account/models/hr_payslip.py#L75-L88 [1]: https://github.com/odoo/enterprise/blob/13e64e0cb7f566cbbb46109fe1c218eb7a14eead/l10n_au_hr_payroll/models/hr_payslip.py#L269-L272 solution: I added ``l10n_au_income_stream_type`` to ``add_to_compute()`` in ``compute_sheet()``. This ensures that stale values of ``l10n_au_income_stream_type`` on existing payslips are recomputed when the payslip sheet is computed. sentry-7536819310 Forward-Port-Of: odoo/enterprise#123288 Forward-Port-Of: odoo/enterprise#120143
Imported Chilean electronic invoices now use the amount in the invoice currency instead of incorrectly using Chilean peso amounts. This prevents vendor bills in foreign or indexed currencies such as UF from showing wrong totals, improving accounting accuracy.
Original PR description
**STEP TO REPRODUCE** 1. Create a invoice to a chilian company, using another currency (for example UF, don't forget setup up a currency rate). 2. Confirm. 3. Download the xml in the chatter, and import it as a vendor bill. 4. Notice the imported bill amount are wrong (Pesos amount are used, with the currency being UF). opw-6269662 Forward-Port-Of: odoo/enterprise#123179 Forward-Port-Of: odoo/enterprise#119664
DHL deliveries made from a company other than the main company now send a valid commercial invoice number. This prevents DHL validation errors and allows international shipments with dutiable goods to be processed correctly.
Original PR description
Issue ----- When validating a delivery in a different company from the main one, the commercial invoice's number field is incorrect, which raises an error on DHL end.…
Issue ----- When validating a delivery in a different company from the main one, the commercial invoice's number field is incorrect, which raises an error on DHL end. `content/exportDeclaration/invoice/number: expected type: String, found: Boolean` Steps to reproduce ----- - Create a Belgian company - Setup DHL - DHL Product D - Express Worldwide - Dutiable Material enabled - Create an amrican customer - Deliver a product to the american customer > Validation Error Cause ----- The field is populated in https://github.com/odoo/enterprise/blob/cf3c2fce8a6b7b2d7547d44a0e4423f887986d52/delivery_dhl_rest/models/dhl_request.py#L204 The problem is that `next_by_code` uses the company found in the env, whereas the sequence's company is the main one, so it is not found when doing https://github.com/odoo/odoo/blob/e3b0ca11d99b2ef819cdad68b169112cd73668b6/odoo/addons/base/models/ir_sequence.py#L287 ----- Ticket: opw-6171886 Forward-Port-Of: odoo/enterprise#123170 Forward-Port-Of: odoo/enterprise#118379
Restaurant delivery orders are now retrieved in one combined request instead of multiple back-to-back requests. This reduces waiting time and server load when point of sale orders are refreshed, improving day-to-day reliability for restaurants using UrbanPiper integrations.
Original PR description
Issue: pos_urban_piper overrode getServerOrders() to add a separate loadServerOrders() call for it's own orders before delegating to super, resulting in up to an additional sequential RPCs on every order fetch. Fix: Extract the base query domain into a new overridable getServerOrdersDomain() method. Each module overrides it to OR in its own domain via Domain.or([super.getServerOrdersDomain(), extraDomain]), so all orders are fetched in a single RPC call instead of three. Task-6284860 Forward-Port-Of: odoo/enterprise#123160 Forward-Port-Of: odoo/enterprise#120001
In multi-company setups, project Gantt charts now correctly shade unavailable time slots for users linked to employees in different companies. This keeps the visual schedule aligned with time-off warnings, helping planners avoid assigning work during approved absences.
Original PR description
Steps to reproduce: - Create one user linked to two companies. - Create one employee per company for that user. - Select one company and approve a time off for the employee. - Open Tasks > Gantt and…
Steps to reproduce: - Create one user linked to two companies. - Create one employee per company for that user. - Select one company and approve a time off for the employee. - Open Tasks > Gantt and create a task during the approved time-off period the warning is shown and the Gantt cell is grayed out. - Select both companies and create a task during the same time-off period in Tasks > Gantt. Issue: When multiple companies are selected, the time-off warning is still displayed but the corresponding Gantt cells are no longer grayed out, leading to an inconsistency between the warning logic and the Gantt rendering. Cause: In multi-company setups, a user can be linked to multiple resources. The Gantt unavailability logic assumed a one-to-one relationship between user and resource causing unavailability intervals from some resources to be overwritten. Solution: Aggregate unavailability intervals from all resources linked to the same user, limited to the selected companies, and merge them with the company calendar unavailability to ensure consistent Gantt gray rendering. Related PR: https://github.com/odoo/enterprise/pull/57028 task-5089385 Forward-Port-Of: odoo/enterprise#105288
This change stops Odoo from reprocessing work entries when no eligible employees remain after exclusions. It prevents a fallback that could unexpectedly scan many employees and slow down large databases, while keeping existing validated work entries intact.
Original PR description
**Steps to Reproduce:** - Create an employee with at least one validated work entry. - Modify the employee's resource_calendar_id. - The schedule change triggers work entry recomputation. - During…
**Steps to Reproduce:** - Create an employee with at least one validated work entry. - Modify the employee's resource_calendar_id. - The schedule change triggers work entry recomputation. - During regeneration, the employee is excluded because of the validated work entry. - No valid employees remain for regeneration. **Issue:** - Employees with validated work entries are excluded from: `valid_employees = self.employee_ids - self.validated_work_entry_employee_ids` - When all employees are excluded, `valid_employees` becomes empty. - The flow still calls: `valid_employees.generate_work_entries(date_from, date_to, True)` - An empty employee recordset causes `generate_work_entries()` to follow the global generation path and fetch all employee versions in the requested period. `_get_all_versions_with_contract_overlap_with_period(date_start, date_stop)` - This can trigger unintended global work entry regeneration and cause severe performance issues on large databases. **Root Cause:** - The regeneration flow does not stop when no valid employees remain after excluding employees having validated work entries. - As a result, generate_work_entries() is called with an empty employee recordset, which falls back to the global generation path. **Solution:** - Stop the regeneration flow when the valid employee recordset is empty Because the employee already has a valid work entry, there is no need to regenerate. **Result:** - Prevents unintended generation on all employee versions. - Avoids unnecessary performance degradation on large databases. **OPW-6290122** 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#270728
This update fixes a crash that could happen in the website editor when a user selected an icon and then opened the Documents tab while replacing media. It improves the editor’s stability so users can switch between media options without losing work or hitting an error.
Original PR description
### Steps to reproduce: - Open the website editor and insert a snippet. - Inside the snippet, add an image and a document via /media. - Select the image, click Replace, pick an icon. - Click the icon, then click Replace from the sidebar. - In the dialog, click the Documents tab. - Traceback occurs. ### Root cause: - Both icon and document box elements are `<span>` tags. `DocumentSelector` inherits `selectInitialMedia()` from `FileSelector` which only checks the tag name, so it incorrectly returns true for icons. This causes `fetchAttachments` to call `querySelector(a)` on the icon span, which returns null and crashes. ### Solution: - Override `selectInitialMedia()` in `DocumentSelector` to also check for the `o_file_box` class. Add optional chaining on `querySelector(a)` as a safety net. task-6310147 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270548
When a task is moved from one project to another, its followers now inherit the notification preferences of the destination project. This prevents people from missing important updates, such as stage changes, after a task is reassigned.
Original PR description
Steps to reproduce: - 1. Create projects A and B. 2. Add a user as a follower of project B and select specific notification subtypes (e.g., 'Stage Changed'). 3. Create a task in project A and add the same user as a follower(defaulting to 'Discussions'). 4. Move the task from project A to project B. Issue: - The follower's subscription preferences on the task do not reflect their project-level settings after the move. In the example above, the user remains subscribed only to 'Discussions' and misses 'Stage Changed' updates. Cause: - The default auto-subscription logic skips existing followers. When moving a task, this prevents the system from adding the new project's notification preferences to users who were already following the task. Fix: - Override `_message_auto_subscribe` in project.task to the `update` policy when the `project_id` is changed. task-5877507 Forward-Port-Of: odoo/odoo#248224
2 changes
Resolved issues and error corrections
Fixed an issue where time off was warned about but not visually grayed out in the project Gantt view when multiple companies were selected. This keeps scheduling guidance consistent for users working across companies and helps avoid assigning tasks during approved absences.
Original PR description
Steps to reproduce: - Create one user linked to two companies. - Create one employee per company for that user. - Select one company and approve a time off for the employee. - Open Tasks > Gantt and…
Steps to reproduce: - Create one user linked to two companies. - Create one employee per company for that user. - Select one company and approve a time off for the employee. - Open Tasks > Gantt and create a task during the approved time-off period the warning is shown and the Gantt cell is grayed out. - Select both companies and create a task during the same time-off period in Tasks > Gantt. Issue: When multiple companies are selected, the time-off warning is still displayed but the corresponding Gantt cells are no longer grayed out, leading to an inconsistency between the warning logic and the Gantt rendering. Cause: In multi-company setups, a user can be linked to multiple resources. The Gantt unavailability logic assumed a one-to-one relationship between user and resource causing unavailability intervals from some resources to be overwritten. Solution: Aggregate unavailability intervals from all resources linked to the same user, limited to the selected companies, and merge them with the company calendar unavailability to ensure consistent Gantt gray rendering. Related PR: https://github.com/odoo/enterprise/pull/57028 task-5089385 Forward-Port-Of: odoo/enterprise#105288
This fix prevents an error when users propose adding a step from the Shop Floor for manufacturing orders whose bill of materials contains very similar operations. It ensures improvement suggestions can be submitted reliably in Product Lifecycle Management workflows.
Original PR description
[FIX] mrp_workorder_plm: avoid singleton traceback when matching BOM operations **Issue** Adding a step in a manufacturing order with two operations that are too similar could lead to a traceback…
[FIX] mrp_workorder_plm: avoid singleton traceback when matching BOM operations **Issue** Adding a step in a manufacturing order with two operations that are too similar could lead to a traceback when proposing an improvement from the Shop Floor. **Steps to reproduce** - Install the Product Lifecycle Management app. - Create a BOM for any product with two operations that: - Have the same name and work center - Have no variant - Create and confirm a Manufacturing Order for that product. - Open the Shop Floor view. - Click the gear icon -> Update Instructions -> Improvement Suggestion -> Add a Step -> Propose a Change. -> A traceback occurs **Cause** When adding a step: https://github.com/odoo/enterprise/blob/1c02615b73a2b4fb9f1ab91167a3c8d7c9ac824c/mrp_workorder_plm/models/mrp_workorder.py#L10 It tries to find the corresponding operation in the ECO's new BoM. This relies on `_get_sync_values()`: https://github.com/odoo/enterprise/blob/1c02615b73a2b4fb9f1ab91167a3c8d7c9ac824c/mrp_plm/models/mrp_routing.py#L9-L13 Because two operations share the same name, work center, and no variant, both match the filter: https://github.com/odoo/enterprise/blob/1c02615b73a2b4fb9f1ab91167a3c8d7c9ac824c/mrp_workorder_plm/models/mrp_workorder.py#L39 This results in a singleton error when accessing `operation.id`: https://github.com/odoo/enterprise/blob/1c02615b73a2b4fb9f1ab91167a3c8d7c9ac824c/mrp_workorder_plm/models/mrp_workorder.py#L42 opw-6241880 Forward-Port-Of: odoo/enterprise#119404
1 change
Resolved issues and error corrections
UrbanPiper POS order fetching now combines related order searches into one request instead of making extra sequential calls. This reduces delays when loading orders and improves the point-of-sale experience without changing user workflows.
Original PR description
Issue: pos_urban_piper overrode getServerOrders() to add a separate loadServerOrders() call for it's own orders before delegating to super, resulting in up to an additional sequential RPCs on every order fetch. Fix: Extract the base query domain into a new overridable getServerOrdersDomain() method. Each module overrides it to OR in its own domain via Domain.or([super.getServerOrdersDomain(), extraDomain]), so all orders are fetched in a single RPC call instead of three. Task-6284860 Forward-Port-Of: odoo/enterprise#120001
24 changes
Enhancements to existing features
The timesheet leaderboard header has been redesigned to show the billable time target and the current month period. This gives users clearer context for their performance metrics and helps them compare progress against monthly expectations.
Original PR description
In this commit, we redesign the timesheet-leaderboard KPI header. Specifically, we add the billable time target and the current month period. task-6103977
Businesses can now assign specific deferred revenue or expense accounts to individual income and expense accounts, while still keeping company-wide defaults as a fallback. Deferred revenue and expense reports also show upcoming recognition split between amounts due within 12 months and after 12 months, improving financial visibility.
Original PR description
*accountant, reports Purpose: Supporting multiple deferred accounts allow businesses to use different deferred revenue/expense accounts based on the related income or expense account, while maintaining the existing company-wide deferred account settings as default. Changes: A "Deferred Account" field is added to the income or expense type accounts form to allow the user to override the defaults. On deferred revenues/expenses reports, the column "Later", representing amount to be recognized, is split into two columns, "Within 12 months" to represent amounts to be recognized within the year and "After 12 months" to represent amounts to be recognized after a year. task-6293902
Invoice extraction now uses the account name and tax to label grouped tax lines instead of relying on partner names and dates read by OCR. This reduces confusing or incorrect labels caused by OCR misreads and makes invoice review more reliable.
Original PR description
Previously, when a user enabled 'Single Invoice Line Per Tax', the tax group contained the partner name and date. However, the OCR would sometimes misclassify the partner name, resulting in random text appearing in the label. To fix this, we decided to use the account name and tax as the label instead. task-6159843
UK VAT return filing now warns users when their company belongs to a tax unit and guides them to file through that tax unit. When a tax unit return is filed, the HMRC connection and submission use the tax unit VAT number, reducing filing errors and compliance risk.
Original PR description
BEFORE: - Before this commit, when the current company is a member of the tax unit, there is no blocking level error for the user to select the tax unit. - And the vat used while creating a connection to the HMRC or while sending a tax report to the HMRC is of the current company. AFTER: - After this commit, there is one blocking level error, which tells the user that the current company is part of a tax unit, and on confirmation, the tax unit will automatically be selected for the current report. - And if the return contains the data of a tax unit, then the vat set on the tax unit will be considered while establishing the connection and sending the tax report to HMRC. Task-5865605 Forward-Port-Of: odoo/enterprise#123166 Forward-Port-Of: odoo/enterprise#107253
Hong Kong payroll can now use the scheduled payroll data update process. This helps keep standard, non-customized salary rules current automatically, reducing manual maintenance for users.
Original PR description
Currently, the "Payroll: Update data" cron doesn't work for HK payroll as we never set up the _get_data_files_to_update. We can set up the list of data files to keep up to date to better support our users by automatically keeping non-edited salary rules up to date. task-6360339 Forward-Port-Of: odoo/enterprise#123204 Forward-Port-Of: odoo/enterprise#122777
Point of Sale appointment dialogs now have better sizing and spacing, making them easier to read and use. Dialogs also get a consistent backdrop so users can close them more easily, improving the overall experience.
Original PR description
This PR adapts the size and spacing of POS dialogs to improve the design and usability of the interface. It also adds backdrop to POS dialogs to allow the user to easily close a dialog when needed. This allows for greater consistency, as previously only a few dialogs had this backdrop. task-5187182 commu-PR: https://github.com/odoo/odoo/pull/258131
Project document folder access is now updated when people are added to or removed from a project. This helps ensure collaborators get editing access when invited and lose access when no longer following restricted projects.
Original PR description
Before this change: - Subscribing or unsubscribing a partner from a project did not impact access rights on the related documents folder; users always retained access to the folder. After this change: - Subscribing a partner grants `edit` access to the project folder. - Unsubscribing removes access when `privacy_visibility` is `invited_users` or `followers` task-5993203
Sales teams can now manually choose which website is linked to an order when it was not created through eCommerce. This helps customer email links and preview actions open the correct website, also covering related subscription and rental flows.
Original PR description
The goal of this change is to allow manually selecting the website linked to an order (if the order does not come from eCommerce). This ensures that email links and the Preview button open the correct website. This change also applies to the Rental module. PR: https://github.com/odoo/odoo/pull/255763 Upgrade: https://github.com/odoo/upgrade/pull/9804 task-6059112
Resolved issues and error corrections
Cancelled UrbanPiper delivery orders are now excluded from active delivery counts. This prevents affected POS sessions from failing to reopen after a delivery provider cancels an order.
Original PR description
### Steps to reproduce 1. Configure UrbanPiper and start a POS session. 2. Receive an order from the delivery provider. 3. Accept the order and mark it as **Ready**. 4. Cancel the order from the…
### Steps to reproduce 1. Configure UrbanPiper and start a POS session. 2. Receive an order from the delivery provider. 3. Accept the order and mark it as **Ready**. 4. Cancel the order from the delivery provider. 5. Reopen the running POS session. ### Current behavior When a delivery provider cancels an order, the `delivery_status` is updated to `cancelled`, while the POS order state remains (`draft`, `paid`, or `done`). As a result: * Cancelled deliveries are still included in the active delivery order count. * `_get_urbanpiper_order_count()` attempts to map the `cancelled` status, which is not present in `status_map`, raising a `KeyError`. * The POS UI fails to load, preventing users from reopening the running session. ### Expected behavior Cancelled delivery orders should not be considered active delivery orders and should not be included in the delivery status count, allowing the POS session to open normally. ### Solution Exclude orders with `delivery_status = 'cancelled'` from the active delivery order count computation. This prevents the `KeyError` and ensures cancelled delivery orders are ignored when computing active delivery statistics. [Video reproducing the issue](https://drive.google.com/file/d/1XdiylekWV-q6LTbvhCgbyd_KDKlG2imz/view?usp=sharing) --- **opw-6353861** Forward-Port-Of: odoo/enterprise#122798
This fix prevents users without Payroll permissions from seeing an error when opening Working Schedules in the Employees app. It adds an access check so Belgian payroll-specific reorganisation data is only read when the user has the right permissions.
Original PR description
**Steps to Reproduce:** 1)Create a database in v19.2. 2)Install the l10n_be_hr_payroll module. 3)Open the login user's profile and set the Payroll access rights to No (null). 4)Navigate to Employees…
**Steps to Reproduce:** 1)Create a database in v19.2. 2)Install the l10n_be_hr_payroll module. 3)Open the login user's profile and set the Payroll access rights to No (null). 4)Navigate to Employees → Configuration → Working Schedules. **Actual Result:** A traceback is triggered after opening the record. ```python Failed to read field resource.calendar.l10n_be_reorganisation_measure_ids You are not allowed to access 'BE: Reorganisation Measure.' (l10n.be.reorganisation.measure) records. This operation is allowed for the following groups: - Payroll/Assistant Contact your administrator to request access if necessary. ``` **Issue:-** The traceback is caused by the following commit introduced in v19.2 [here](https://github.com/odoo/enterprise/commit/e1092393ff99e9dad84ea8b9d6066e0bc61d6312) In this commit, a new computed field `l10n_be_reorganisation_measure_ids` was added on `resource.calendar`. The field is computed and store=true when the read function is called, and reads the data from the database at that time; The payroll doesn't have any access rights due to the error **Solution:** To fix this issue, a group access check is added inside the field Ticket:- 6245936 Forward-Port-Of: odoo/enterprise#119518
Fixes issues in subscription loyalty flows so recurring invoices grant the right reward points and respect the selected point calculation mode. It also prevents incorrect negative reward invoice lines when points run out and restores missing recurring options in loyalty rules and rewards.
Original PR description
This commit fixes the following problems in the new module: - New invoices sometimes could not grant points according to the specified rules. - The reward point mode was not being taken into account and was giving a flat amount of points. - Reward lines were being invoiced with a negative amount when there was no more points in the loyalty card. - The 'Recurring' option in conditional rules and reward were not showing sometimes for an unknown reason. task-6153127 Forward-Port-Of: odoo/enterprise#116713
Timesheet Assistant suggestions are now cleaner and more accurate, with leave time excluded from suggested totals and to-do tasks hidden until they are linked to a project. Users also get keyboard shortcuts and default names for unnamed suggestions, making timesheet entry faster and less confusing.
Original PR description
## Expected Behavior After Commit - Remove the green highlight when selecting a suggestion. - Add shortcuts for timesheet creation buttons. - Allow calendar events to be considered side activities - Exclude leave time from total hours, as leave time is already counted in the timesheet. - Do not show to‑do tasks (tasks without a project) in suggestions. - Restore previous suggestions for to‑do tasks when they later become linked to a project. - Add a default name for suggestions that do not have one. - Add hotkeys to Timesheet Assistant task-[6191451](https://www.odoo.com/odoo/project/4105/tasks/6191451) Forward-Port-Of: odoo/enterprise#121085 Forward-Port-Of: odoo/enterprise#120057
The scheduled check for Mexican electronic invoice status now correctly continues when more documents remain than the configured batch size. This prevents invoices from being left unprocessed after the first batch, improving reliability for companies using Mexican e-invoicing.
Original PR description
Steps to reproduce ----------------- - Install l10n_mx_edi; - Switch to the mexican company; - Create 3 invoices for the mexican company (you will need to set an UNSPSC code on the products); - Send them to CFDI; - Go to the scheduled action "Automatic update of state on the SAT" and add "batch_size=2" to the method's parameters; - Manually run the cron; - Only two invoices will be updated, the cron is not retriggered to process the remianing one. Why is it hapening ------------------ We set a limit of batch_size + 1 in the search method, and the cron is retriggered if and only if the number of documents fetched is equal to the batch size, meaning there is no more documents to fetch. This should be triggered if we fetched more documents than the batch size. opw-6328118 Forward-Port-Of: odoo/enterprise#122659
Hong Kong payroll now calculates payment in lieu of notice based on the employee's actual contract start date instead of assuming a full prior 12 months. This improves accuracy for employees who have worked less than a year or have other partial-period situations, reducing payroll errors.
Original PR description
Currently, the calculation of the payment in lieu of notice is assuming the employee worked a whole 12 months prior to it being paid. This is of course not always going the be case, and when it happens our calculation is often incorrect. We update the salary rule to calculate a more accurate total days (which is no longer based on a fixed 12-month period but takes into account the contract's start date). We also now calculate the number of months more accurately by taking, once again, the contract's start date into account. Also adding a few test cases to test a bit more some special case we didn't yet test correctly. task-6348903 Forward-Port-Of: odoo/enterprise#122580
Task progress shading in the Gantt view now shows the correct proportion of completed work. This makes planning views easier to read and prevents users from misinterpreting partially completed tasks as barely started.
Original PR description
Steps to reproduce: ------------------------------------------- 1. Install the Timesheet module with demo data 2. Go to any FSM task > set allocated hours to 20h 3. Fill the timesheet for the same…
Steps to reproduce: ------------------------------------------- 1. Install the Timesheet module with demo data 2. Go to any FSM task > set allocated hours to 20h 3. Fill the timesheet for the same task for 10h 4. Navigate to FSM > My Tasks > Gantt view Observation: ------------------------------------------- Look at the task on the Gantt chart. The shading is barely visible because it covers only 0.5% of the bar, not 50% Issue: ------------------------------------------- In the commit https://github.com/odoo/odoo/pull/137570/changes/4a93d9aee957dd3feb3db0cb69eb3b8f0f4a4683 The progress field computation was changed from storing percentage values (0-100) to storing decimal values (0-1). Specifically, the `_compute_progress_hours` method was modified. This change was made to standardize the progress field storage format, with the understanding that the UI layer would multiply by 100 when displaying the value. While most views (form, list, kanban, etc.) were updated to multiply the progress by 100 for display purposes, the Gantt view's pill progress bar was missed. Solution: ------------------------------------------- Overrides the `enrichPill` method to multiply the `_progress` value by 100 before it's passed to the template. This ensures the Gantt pill progress bars display correctly without modifying the core web_gantt module. Before --------------------------- <img width="268" height="368" alt="image" src="https://github.com/user-attachments/assets/6d35927f-bd3f-47fc-9101-e2e188d419b8" /> After: -------------------------- <img width="250" height="371" alt="image" src="https://github.com/user-attachments/assets/fe7133e0-26d1-4c5f-b903-48826fda9488" /> opw-6038983 Forward-Port-Of: odoo/enterprise#122899 Forward-Port-Of: odoo/enterprise#111270
Users creating purchase approval requests will no longer be blocked when a product has vendor pricing records linked to vendors they are not allowed to access. This keeps RFQ approval creation working correctly in multi-company setups while respecting access permissions.
Original PR description
**Issue** Having supplier pricelists with at least one vendor inaccessible to the current user can trigger an access error when creating an RFQ approval request. **Steps to reproduce** - Have two…
**Issue** Having supplier pricelists with at least one vendor inaccessible to the current user can trigger an access error when creating an RFQ approval request. **Steps to reproduce** - Have two companies A and B and two users u1 and u2 - user u2 only have access to company A - With user u1: - Create two vendors v1 and v2 without any company assigned - Create vendor pricelists for a product for each vendor and assign the company A to the pricelist - Add the company B for the vendor v2 - With user u2: - Open approval application - Try to create an approval for an RFQ for that product (the vendor v1 will be automatically selected) - Save it -> An access error is thrown **Cause** Saving the approval request computes `has_no_seller`, which calls `_select_seller`: https://github.com/odoo/enterprise/blob/03c737685ff6dfc95a8bc72491646774fc426b1f/approvals_purchase/views/approval_product_line_views.xml#L9 https://github.com/odoo/enterprise/blob/03c737685ff6dfc95a8bc72491646774fc426b1f/approvals_purchase/models/approval_product_line.py#L32 https://github.com/odoo/enterprise/blob/03c737685ff6dfc95a8bc72491646774fc426b1f/approvals_purchase/models/approval_product_line.py#L62-L70 Which filtered the right seller https://github.com/odoo/odoo/blob/c37e76850d3ff790b76493bd1003d80e170bd4bf/addons/product/models/product_product.py#L759 By preparing the sellers: https://github.com/odoo/odoo/blob/c37e76850d3ff790b76493bd1003d80e170bd4bf/addons/product/models/product_product.py#L721 https://github.com/odoo/odoo/blob/c37e76850d3ff790b76493bd1003d80e170bd4bf/addons/product/models/product_product.py#L712 Please note that `self.seller_ids` contains both sellers (even v2) By filtering the suppliers: https://github.com/odoo/odoo/blob/c37e76850d3ff790b76493bd1003d80e170bd4bf/addons/product/models/product_supplierinfo.py#L104-L105 But at that point, one of the supplier in `self`, can be accessed, thus an access error is thrown while trying to access its associated `partner_id`. opw-6203910 Forward-Port-Of: odoo/enterprise#121008 Forward-Port-Of: odoo/enterprise#120251
Fixes an issue that prevented the Planning Analysis report from opening when Field Service Planning was installed. The Priority filter is now placed correctly, avoiding a crash and restoring access to the report.
Original PR description
Steps to reproduce: - 1. Install `planning_field_service`. 2. Open Planning > Reporting > Planning Analysis. Issue: - The view crashes with `UncaughtPromiseError > Error: Attribute "domain"` is missing, and the Planning Analysis report cannot be opened. Cause: - The xpath adding the "Priority" filter anchors on `//filter[@name='unpublished_shifts']`, which is a child of the "Status" filter. As a result, "Priority" is inserted inside "Status", and it requires a `domain` on any filter nested inside another filter. "Priority" has none. Fix: - Anchor the xpath on `//filter[@name='status']` instead. task-6358804 Forward-Port-Of: odoo/enterprise#122751
Fixed an error that could stop Belgian CODA bank statement files from importing when they contained type 4 blocks. This helps Belgian accounting users complete bank imports reliably without manual workarounds or support intervention.
Original PR description
### Issue: After the fix in commit (https://github.com/odoo/enterprise/commit/3ef8ae7a6b8eb362e18c74dfab9aadce792b5dc2), importing a CODA file containing a type 4 block raises a traceback ### Cause: That commit introduced `communication_struct_by_ref_move`, which iterates over all lines and accesses `line['communication_struct']` Type 4 lines are not assigned a `communication_struct` value by the parser in `_get_coda_file_statements` Accessing the key directly raises a `KeyError` in `_get_coda_final_statements` in `communication_struct_by_ref_move` ### Steps to reproduce: - Install `l10n_be_coda` - Switch to the BE company - Create a Bank Journal with account `BE33737018595246` - Go to the Accounting Dashboard and import a CODA file containing a type 4 block (Like the one on the ticket) Before the fix, a traceback is raised on import opw-6363148 Forward-Port-Of: odoo/enterprise#123222
This fix ensures the snippet selection dialog appears in front of the email editing window when the AI chatbox is active. Users can now add snippets normally without the editor becoming blocked or save and discard actions freezing.
Original PR description
When an AI chatbox is active, all non-error dialog modals are set to be behind the chatbox through their z-index. This causes an issue where the dialog modal to add new snippets to a mailing is set behind the fullscreen edit window, preventing its use and freezing the use of some commands (save & discard). This commit restores the snippet dialog's z-index to its original value. task-6321624
This fixes an error that could prevent users from opening the task Gantt view when grouping tasks by Sale Order Item. The progress calculation now uses the current task hours field, so project and sales teams can view grouped planning information without interruption.
Original PR description
### Steps to reproduce - Install `sale_timesheet_enterprise`. - Go to **Tasks → All Tasks**. - Switch to the **Gantt** view. - Group by **Sale Order Item** (`sale_line_id`). ### Issue A traceback is…
### Steps to reproduce - Install `sale_timesheet_enterprise`. - Go to **Tasks → All Tasks**. - Switch to the **Gantt** view. - Group by **Sale Order Item** (`sale_line_id`). ### Issue A traceback is raised when loading the Gantt view with group by `sale_line_id`: ```text ValueError: Invalid field 'planned_hours' on model 'project.task' for 'planned_hours:sum' ``` ### Root cause The Gantt progress bar computation for the `sale_line_id` grouping performs a `_read_group()` aggregation on the `planned_hours` field of `project.task`. However, `planned_hours` was renamed to `allocated_hours` during the saas-16.5 migration, so the former field no longer exists on `project.task`. As a result, the aggregation raises a `ValueError`. Migration reference: https://github.com/odoo/upgrade/blob/e638c6ce00d9d8936d034ad7130fef51565b9195/migrations/project/saas~16.5.1.2/pre-migrate.py#L10 Issued PR: https://github.com/odoo/enterprise/pull/49685 ### Fix Use `allocated_hours`, the renamed equivalent of `planned_hours`, when computing the Gantt progress bar. This restores the Gantt view when grouping tasks by **Sale Order Item** and prevents the traceback. Forward-Port-Of: odoo/enterprise#122994 Forward-Port-Of: odoo/enterprise#122297
This fixes an issue where website content generated through the AI Assistant could disrupt later editing. AI-created snippets now render without extra editor metadata, so users can continue dragging snippets and editing the page normally after saving.
Original PR description
Steps to see the issue: - Open website and start editing - Click on "AI Assistant" button - Ask it to drop a popup - Save the page and start editing again => Snippets aren't droppable and the `#wrap` of the page isn't editable. This happens because snippets inherit branding when they are rendered, so they have `data-oe-id` and others on them, which breaks the usual website flow. This occurs since [1], which added website_id to the context, and in website inherit_branding is set to true automatically, which doesn't happen without the website id. [1]: https://github.com/odoo/enterprise/commit/f9a1c8deeb74749fd176bfc8825c621f214b1985 task-6376299
The Belgian payroll 274 report now calculates deducted amounts correctly by avoiding double counting of SME exemptions. This helps businesses produce more accurate payroll tax declarations and uses the proper capped amount for the 274.34 report.
Original PR description
Prior to this commit, there was a bug where the deducted amount double counted the SME exempted amount in the 274 report. This commit fixes this.
This fixes Colombian electronic invoice PDF layouts so the company address is no longer pushed out of view when using Folder or Wave designs with long taglines. It also keeps the invoice title from overlapping the QR code, improving the readability and compliance presentation of exported invoices.
Original PR description
Issue: On Wave and Folder layout, the address of the company doesn't appear on invoices. Steps to reproduce: - In a Colombian company, - Set company layout to Folder - Add a long tag line, - Create an invoice, - Send it to DIAN - Export to PDF Current behavior: - Company address is missing in the header Cause: Tag line + logo and address take 100% of the display width. However, loca add a QR code on the left, so it takes QR Code + 100% width. Therefore, address was out of the PDF. Moreover, for Folder layout, some resizing was done and as soon as there was a tag_line, the `rem` was downsized, allowing the invoice title: "Factura Electrónica de Venta SETP/*\*\*/\*\*\*\*" to be displayed entirely. The fix of the previous issue stopped the resizing, then the invoice title got overridden by the QR Code (same as without tag_line before this fix). opw-6239030 Forward-Port-Of: odoo/enterprise#122205 Forward-Port-Of: odoo/enterprise#119678
Field service interventions now require both start and end dates before they can be completed. Send and Publish actions are also hidden when no date is set, helping teams avoid incomplete or incorrectly scheduled work.
Original PR description
After this PR: - Both dates are required to use the 'Complete' action button on an intervention - If the start date is set on an intervention, the end date should be required (and vice versa) - We hide the 'Send' and 'Publish' buttons if there is no date set task-6234939 Forward-Port-Of: odoo/enterprise#123148 Forward-Port-Of: odoo/enterprise#118411
7 changes
Enhancements to existing features
Odoo can now use official daily exchange rates from the Central Bank of Azerbaijan for automatic currency updates. This helps businesses using AZN translate multi-currency accounting and tax transactions more accurately, including rates quoted for larger nominal amounts.
Original PR description
This commit adds the Central Bank of Azerbaijan (CBA) as a supported service provider for automatic currency rate updates. Purpose: To ensure multi-currency accounting entries and taxable transactions are accurately translated into the national currency (AZN) using the official exchange rate defined by the CBA for the transaction day. Functionality: -Enables fetching official daily exchange rates directly from CBA via XML. -Automatically handles rates defined for different nominal quantities (e.g., rates quoted per 100 units instead of 1 unit). Backport of: https://github.com/odoo/enterprise/pull/122626 task-6112867
Resolved issues and error corrections
The project Gantt view now correctly shades unavailable periods when a user has employees in multiple companies. This keeps visual scheduling cues aligned with time-off warnings, helping planners avoid assigning work during approved absences.
Original PR description
Steps to reproduce: - Create one user linked to two companies. - Create one employee per company for that user. - Select one company and approve a time off for the employee. - Open Tasks > Gantt and…
Steps to reproduce: - Create one user linked to two companies. - Create one employee per company for that user. - Select one company and approve a time off for the employee. - Open Tasks > Gantt and create a task during the approved time-off period the warning is shown and the Gantt cell is grayed out. - Select both companies and create a task during the same time-off period in Tasks > Gantt. Issue: When multiple companies are selected, the time-off warning is still displayed but the corresponding Gantt cells are no longer grayed out, leading to an inconsistency between the warning logic and the Gantt rendering. Cause: In multi-company setups, a user can be linked to multiple resources. The Gantt unavailability logic assumed a one-to-one relationship between user and resource causing unavailability intervals from some resources to be overwritten. Solution: Aggregate unavailability intervals from all resources linked to the same user, limited to the selected companies, and merge them with the company calendar unavailability to ensure consistent Gantt gray rendering. Related PR: https://github.com/odoo/enterprise/pull/57028 task-5089385 Forward-Port-Of: odoo/enterprise#105288
This fix prevents an error when users propose adding a step from the Shop Floor for manufacturing orders whose bill of materials contains very similar operations. It makes the improvement suggestion flow more reliable for teams using PLM to update manufacturing instructions.
Original PR description
[FIX] mrp_workorder_plm: avoid singleton traceback when matching BOM operations **Issue** Adding a step in a manufacturing order with two operations that are too similar could lead to a traceback…
[FIX] mrp_workorder_plm: avoid singleton traceback when matching BOM operations **Issue** Adding a step in a manufacturing order with two operations that are too similar could lead to a traceback when proposing an improvement from the Shop Floor. **Steps to reproduce** - Install the Product Lifecycle Management app. - Create a BOM for any product with two operations that: - Have the same name and work center - Have no variant - Create and confirm a Manufacturing Order for that product. - Open the Shop Floor view. - Click the gear icon -> Update Instructions -> Improvement Suggestion -> Add a Step -> Propose a Change. -> A traceback occurs **Cause** When adding a step: https://github.com/odoo/enterprise/blob/1c02615b73a2b4fb9f1ab91167a3c8d7c9ac824c/mrp_workorder_plm/models/mrp_workorder.py#L10 It tries to find the corresponding operation in the ECO's new BoM. This relies on `_get_sync_values()`: https://github.com/odoo/enterprise/blob/1c02615b73a2b4fb9f1ab91167a3c8d7c9ac824c/mrp_plm/models/mrp_routing.py#L9-L13 Because two operations share the same name, work center, and no variant, both match the filter: https://github.com/odoo/enterprise/blob/1c02615b73a2b4fb9f1ab91167a3c8d7c9ac824c/mrp_workorder_plm/models/mrp_workorder.py#L39 This results in a singleton error when accessing `operation.id`: https://github.com/odoo/enterprise/blob/1c02615b73a2b4fb9f1ab91167a3c8d7c9ac824c/mrp_workorder_plm/models/mrp_workorder.py#L42 opw-6241880 Forward-Port-Of: odoo/enterprise#119404
Imported Chilean electronic invoices now use the amount in the invoice currency instead of incorrectly applying Chilean peso amounts. This prevents vendor bills in currencies such as UF from being created with wrong totals, reducing accounting corrections and reconciliation issues.
Original PR description
**STEP TO REPRODUCE** 1. Create a invoice to a chilian company, using another currency (for example UF, don't forget setup up a currency rate). 2. Confirm. 3. Download the xml in the chatter, and import it as a vendor bill. 4. Notice the imported bill amount are wrong (Pesos amount are used, with the currency being UF). opw-6269662 Forward-Port-Of: odoo/enterprise#123179 Forward-Port-Of: odoo/enterprise#119664
Duplicating certain Sign templates could fail when the same signer roles appeared across multiple documents and fields. The fix prevents already-processed signer roles from being copied again, allowing affected templates to duplicate successfully.
Original PR description
Issue: This [loop](https://github.com/odoo-dev/enterprise/blob/55bb2cc570451361701d53583f019ed832a5e5d3/sign/models/sign_item.py#L59-L63) runs multiple times with the same approvers(sign.item.role), but doesn't take into account the already 'seen map' inside the base copy function for batching. If they are already seen they will return a non-iterable [None]. To replicate: 1) Sign -> Template -> upload PDF 2) Go into the template 3) Add 2 Documents, with 2 signers and multiple fields on both documents 4) Save -> gear Icon -> make into template 5) Go back to the list view of templates 6) Select the template -> Gear Icon -> Duplicate Fix: add an already seen check to skip if already seen. opw-6352408
Kenyan POS refunds can now be validated without triggering an error during eTIMS processing. The fix also improves handling when multiple offline orders are synchronized together, helping keep sales and refund workflows running smoothly.
Original PR description
Steps to reproduce: 1. Install `l10n_ke_edi_oscu_pos`, set company to Kenya. 2. Sell and validate an order. 3. Refund it from the POS and validate the refund order. Issue: - A traceback is raised…
Steps to reproduce: 1. Install `l10n_ke_edi_oscu_pos`, set company to Kenya. 2. Sell and validate an order. 3. Refund it from the POS and validate the refund order. Issue: - A traceback is raised when validating the refund: `ValueError: Expected singleton: pos.order(<refund>, <original>)` raised in `get_l10n_ke_edi_oscu_pos_data`. Cause: - When syncing a refund, `sync_from_ui` returns both the new refund order and the original refunded order. `waitForPushOrder` forces post-processing for every Kenyan order in that list, so `beforePostPushOrderResolve` receives both ids in `order_server_ids` and forwards them as-is to `action_post_order` and `get_l10n_ke_edi_oscu_pos_data`, both of which expect a single record. `action_post_order` fails the same way, but its error was silently swallowed by the surrounding try/catch, letting the traceback surface only on the second call. - The same multi-id list is also produced whenever several orders created offline get synced together once back online. Solution: - `get_l10n_ke_edi_oscu_pos_data` is only needed for the receipt of the order being validated, so call it with `order.id` instead of the full `order_server_ids` list. - Replace the `action_post_order` call with `action_post_selected_orders`, which posts each order individually and skips ones already sent to eTIMS, correctly handling both the refund case (original order is already `sent`) and the offline multi-order sync case. opw-6364221
Invoice tax recalculations using Avatax now refresh the pre-tax base amount instead of keeping an outdated value. This helps prevent invoices from remaining stuck with incorrect tax totals after recomputing taxes or reconfirming a draft invoice.
Original PR description
Issue: Invoice lines have a json field, `extra_tax_data`. The `extra_tax_data` can include a `manual_total_excluded_currency` value, which is the pre-tax base amount that taxes get added on top of.…
Issue: Invoice lines have a json field, `extra_tax_data`. The `extra_tax_data` can include a `manual_total_excluded_currency` value, which is the pre-tax base amount that taxes get added on top of. In some cases, the `manual_total_excluded_currency` value can end up incorrect (cause unknown). When this occurs, clicking "Compute Taxes" or resetting the invoice to draft and reconfirming does not correct the problem. This leaves the invoice in a persistently incorrect state with no straightforward way to fix it. Explanation: The bug is in `_process_external_taxes` in the `account_external_tax_mixin.py` in the `account_external_tax` module. During tax re-computation, if `extra_tax_data` is considered still valid, it is used to populate an in-memory base line dict. In this dict, `manual_tax_amounts` (which comes from a sub-dict in `extra_tax_data`) is explicitly cleared and fully repopulated from the fresh Avatax response every time. However, `manual_total_excluded_currency` in the base line dict is only updated if it is `None`. So, if it has an positive incorrect value, it will not be updated using the fresh Avatax response. Then, it will be written back to `extra_tax_data` unchanged, perpetuating the problem. Solution: Reset `manual_total_excluded_currency` to `None` at the start of each re-computation loop, mirroring what is already done for `manual_tax_amounts`. This ensures the pre-tax base amount is always taken from the current Avatax response rather than a previous value. This makes the behavior of `manual_tax_amounts` and `manual_total_excluded_currency` consistent with each other. opw-6235597
4 changes
Resolved issues and error corrections
Canadian EFT payment export files now use each payment's identifier as the Item Trace Number instead of filling it with zeros. This helps ensure exported payment files meet CPA-005 requirements and avoids bank rejections for invalid trace numbers.
Original PR description
Issue: The Item Trace Number according to CPA-005 standard should be a nonzero sequence that serves as unique reference ID for payments. Currently, Odoo sets the Item Trace Number of all payments as…
Issue: The Item Trace Number according to CPA-005 standard should be a nonzero sequence that serves as unique reference ID for payments. Currently, Odoo sets the Item Trace Number of all payments as a zero-filled sequence According to CPA-005 standards on the Item Trace Number: "The data elements (b), (c) and (d) each must be greater than zero or the TRANSACTION WILL BE REJECTED" (page 36). https://www.payments.ca/sites/default/files/standard005eng.pdf Steps to reproduce: 1. Install the module l10n_ca_payment_cpa005 2. Go into "CA Company" 3. In the configuration for "CA Company", add something to the fields "Short Name used in Canadian EFT" and "Company ID" i.e. "CCC" 4. Set all the fields in the "Canadian EFT/CPA Configuration" section of the bank journal 5. Set the bank record on the bank journal. Set the field "Financial Institution ID Number" field of the "Account Number" record of the bank journal to any numerical sequence 6. Create a bank account on "Azure Interior" and make sure to check the field to trust the bank account that you created (otherwise there will be an error) 7. Create two payments with the vendor of "Azure Interior" using the payment method of "Canadian EFT" 8. Create a batch payment for both payments created 9. Validate the batch payment and the export file should show up in the chatter 10. Note that in the export file, the Item Trace Number for each payment is set to be all zeros, whereas it should be a nonzero identification sequence Solution: Set the Item Trace Number to be the payment's id opw-6323432
Luxembourg payroll now uses the correct official salary index values for contracts starting from May 2025 and June 2026. This prevents incorrect contract signature index values and helps ensure related payroll calculations remain aligned with legal indexation updates.
Original PR description
## Issue When creating or browsing an existing contract in a Luxembourgish company, the current index shown is the one from September 2023 (which was up-to-date until Mai 2025). If the contract is…
## Issue
When creating or browsing an existing contract in a Luxembourgish company, the current index shown is the one from September 2023 (which was up-to-date until Mai 2025). If the contract is created after Mai 2025, the "Index on Contract Signature" field is also wrong.
## Steps to reproduce
1. Install *Luxembourg - Payroll* (`l10n_lu_hr_payroll`)
2. Using a Luxembourgish company, create a new contract for an employee
- *Contract Start Date*: Any date after 05/01/2025 (Mai 1st 2025)
3. __The *Index on Contract Signature* shows `944.43`, which is the index from September 2023. It does not match with the most recent indices.__
## Cause
The two most recent indices are missing from the [`rule_parameter_lu_index`](https://github.com/odoo/enterprise/blob/885edbc270a86ab76e0a6eff4acb5767c0fe29d1/l10n_lu_hr_payroll/data/rule_parameters/general_rules_data.xml#L4-L58). These indices are:
- `968.04` from 2025-05-01 (Mai 1st 2025)
- `992.24` from 2026-06-01 (June 1st 2026)
These values were taken from [here](https://salary.lu/en/tools/social-parameters/indexation-of-salaries) and double-checked [here](https://lustat.statec.lu/?lc=en&tm=DF_C1201&pg=0&snb=1).
## Tests modification
Updating the latest index had an impact on the tests from the `l10n_lu_hr_payroll_account` (testing the salary rules). In fact, the current index (`l10n_lu_current_index`) is [used to compute the indexed wage](https://github.com/odoo/enterprise/blob/7892d035ddb968d67a3e8da0daf91292bd8fb499/l10n_lu_hr_payroll/models/hr_contract.py#L24-L33) (`l10n_lu_indexed_wage`), which is then used to compute most lines in the payslip (e.g., the `WAGE_SUPPLEMENT_70`).
https://github.com/odoo/enterprise/blob/7892d035ddb968d67a3e8da0daf91292bd8fb499/l10n_lu_hr_payroll/data/salary_rules/hr_salary_rule_data.xml#L70-L74
Since the latest index is not the same as when those tests were written, the values are not correct anymore. To prevent this, time was frozen to 01/01/2024 to use the expected index (944.43, from September 2023).
opw-6330790When a task is moved to another project, follower notification preferences are now updated to match the new project’s settings. This prevents people from missing important task updates after a task is reassigned between projects.
Original PR description
Steps to reproduce: - 1. Create projects A and B. 2. Add a user as a follower of project B and select specific notification subtypes (e.g., 'Stage Changed'). 3. Create a task in project A and add the same user as a follower(defaulting to 'Discussions'). 4. Move the task from project A to project B. Issue: - The follower's subscription preferences on the task do not reflect their project-level settings after the move. In the example above, the user remains subscribed only to 'Discussions' and misses 'Stage Changed' updates. Cause: - The default auto-subscription logic skips existing followers. When moving a task, this prevents the system from adding the new project's notification preferences to users who were already following the task. Fix: - Override `_message_auto_subscribe` in project.task to the `update` policy when the `project_id` is changed. task-5877507 Forward-Port-Of: odoo/odoo#248224
This change ensures each project dashboard only shows the sales order lines that belong to that specific project. It prevents sales and profitability figures from being inflated by lines from other projects, so the dashboard data is more accurate.
Original PR description
Steps to reproduce: ------------------------- 1. Install sale_project and accounting 2. Create two billable projects with specific analytic accounts 3. Create two service products with "prepaid/fixed…
Steps to reproduce: ------------------------- 1. Install sale_project and accounting 2. Create two billable projects with specific analytic accounts 3. Create two service products with "prepaid/fixed price", set "create on order" to "Task" and assign each product to its respective project in the project column 4. Create a SO with these products and confirm it 5. Click on the projects stat button (it shows two projects) Observation: ------------------ Both project dashboards display both SOLs even though each SOL belongs to a different project's analytic account, leading to incorrect SOL count and profitability calculation. Cause: --------- https://github.com/odoo/odoo/blob/281658e86971687656f3235ac1ff8afcb52f2908/addons/sale_project/models/project_project.py#L420-L427 The domain matched SOLs via `order_id,` which pulled all SOLs from a matched order regardless of which project they belonged to. Solution: ----------- Add an additional filter on analytic_distribution to ensure SOLs with no `project_id` are only included when their analytic account matches the project's analytic account, preventing cross-project SOL leakage. opw-6205750 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
1 change
Resolved issues and error corrections
Fixes an issue where General Ledger Excel exports with a single journal showed tax declaration lines multiple times, breaking the report layout. The export now includes those tax lines only once and better respects the selected journal, making the spreadsheet clearer and reliable for accounting review.
Original PR description
## Issue When exporting the General Ledger in xlsx format with only one journal selected, the tax declaration lines appear multiple times and are disrupt the overall format of the report. ## Steps to…
## Issue When exporting the General Ledger in xlsx format with only one journal selected, the tax declaration lines appear multiple times and are disrupt the overall format of the report. ## Steps to reproduce 1. Install *Accounting* (`account_accountant`) with demo data 2. In Accounting > Reporting > General Ledger, select a single journal (e.g. Customer Invoices) and click the *XLSX* export button. 3. **The resulting XLSX file is incorreclty formated. The tax declaration lines appear multiple times and disrupt the structure of the report.** <img width="1012" height="603" alt="image" src="https://github.com/user-attachments/assets/1d22e9a1-3fc2-4538-b1bd-4ca1d1bbe092" /> ## Cause Since https://github.com/odoo/enterprise/commit/6a3804c5fe6b4f1d48a4ab311a0f1fbb24d75187, the xlsx report is generated by iterating over the relevant accounts and injecting the lines into the report account by account. https://github.com/odoo/enterprise/blob/b6d27f428e2b966e38b65e820e1454b711483996/account_reports/models/account_general_ledger.py#L773-L775 The [`_get_accounts_with_move_lines` method](https://github.com/odoo/enterprise/blob/17.0/account_reports/models/account_general_ledger.py#L814) does not take into account the journals that are requested when exporting .xlxs, which leads to too many accounts being iterated over. Before that commit, the `_get_lines` method was only called once when generating the xlsx report. This explains the behaviors below, that were not properly adapted to call the method multiple times to generate a single report. The first issue is that the `_get_lines` method calls the `_dynamic_lines_generator` method, which adds the tax declaration lines after each account when only one journal is selected: https://github.com/odoo/enterprise/blob/b6d27f428e2b966e38b65e820e1454b711483996/account_reports/models/account_general_ledger.py#L88-L91 To avoid that, we can add a context key to prevent the injection of the tax declaration lines for all iterations, then add the lines afterwards. Another issue is that the accounts chosen to iterate over do not take the selected journal into account. Without doing so, we iterate over too many accounts, which is inefficient, but which also adds the tax declaration lines (and only those lines) for those irrelevant accounts. That is why the tax declaration lines appear multiple times in the incorrect reports: they were added for accounts that were not supposed to belong in the report. Lastly, because the total line is added individually, it would not be bold because of the following condition from `inject_lines_into_xlsx_sheeŧ`: https://github.com/odoo/enterprise/blob/b6d27f428e2b966e38b65e820e1454b711483996/account_reports/models/account_report.py#L5262-L5266 ## Performance Impact Because the commit introducing the issue (https://github.com/odoo/enterprise/commit/6a3804c5fe6b4f1d48a4ab311a0f1fbb24d75187) is a [PERF] commit, the performance impact of this fix was evaluated. The table below shows the time taken to export the XLSX report of the General Ledger for a various amounts of `account.move.line`. Each value represents the average execution time over 10 runs (in milliseconds), with the standard deviation shown in parentheses. | | Before (ms) | After (ms) | |--------|------------------|------------------| | 100 | 321.25 (± 49.56) | 363.43 (± 59.93) | | 5,000 | 1759 (± 71.87) | 1773 (± 60.19) | | 10,000 | 2723 (± 70.72) | 2765 (± 106.8) | | 50,000 | 11501 (± 170.32) | 11567 (± 165.87) | opw-5783588