Daily updates from Odoo
Tuesday, September 30, 2025
86 changes
18 changes
Resolved issues and error corrections
Fixed an issue where Peruvian electronic invoices for foreign-currency down payments could show the company currency instead of the invoice currency. This helps ensure invoice XML data matches the actual transaction currency and avoids compliance or validation problems.
Original PR description
#### Issue: - After invoicing a downpayment in a foreign currency, in the XMl of the total invoice, the currency_id on the prepaid tag is set to PEN instead of the right currency. #### Step to…
#### Issue: - After invoicing a downpayment in a foreign currency, in the XMl of the total invoice, the currency_id on the prepaid tag is set to PEN instead of the right currency. #### Step to reproduce: 1. Install l10n_pe_edi 2. Sell a product to "Comercial Constructora los Patitos" through the sales app and make sure you use USD (or a different currency than PEN). 3. Create a downpayment invoice, could be any percentage. 4. To make sure it works correctly, add a random document number on the invoice with the format ABC-01234567. 5. Confirm this invoice. 6. Now go back to the sale order and deliver your product. 7. Create the final invoice, where the downpayment will be deducted. Make sure it is also in USD (or whatever currency you chose). 8. Confirm the invoice. #### Current behavior: - Display "PEN" in the attribute currencyID of tag PaidAmount in a PrepaidPayment: <cbc:PaidAmount currencyID=PEN> #### Expected behavior: - The currency displayed should match the invoice currency #### Cause of the issue: - the currency of the company emitting the invoice was used instead of the currency of the invoice. opw-5061019
Field service sale order lines now use the customer’s assigned pricelist instead of the product’s default price. This ensures customers are billed according to agreed pricing when tasks with timesheets are validated.
Original PR description
Before this commit, the service line on the sale order ignored the customer’s pricelist and used the product’s default price. Steps to reproduce: - Assign a fixed-price pricelist to a customer. - Create an FSM task for them and add a timesheet. - Validate the task and check the service line price. After this commit, the service line correctly reflects the price from the assigned pricelist. task-4830183 Forward-Port-Of: odoo/enterprise#95650 Forward-Port-Of: odoo/enterprise#88039
Coupon and global discount lines are now identified more reliably on sales orders, so discounted amounts are passed correctly to delivery services such as Shiprocket. This prevents cash-on-delivery shipments from being created with missing discount totals and keeps discount line values stable when quantities change.
Original PR description
Issue ----- When using Shiprocket with the "Cash On Delivery", the request sent to the Shiprocket API doesn't contain the amounts discounted by coupons. Steps to reproduce ----- - Set an Indian…
Issue ----- When using Shiprocket with the "Cash On Delivery", the request sent to the Shiprocket API doesn't contain the amounts discounted by coupons. Steps to reproduce ----- - Set an Indian company up (with valid address and some dummy mail & phone) - Create a customer "IN Cust" (with valid address and some dummy mail & phone) - Create a product "IN Prod" - Sale price: 1000 INR - Weight: 100g - Set some reference, eg "INPROD" - Create a Shiprocket delivery method - Payment Method: COD - Set some "Shiprocket Channel" - Enable Debug requests - In settings, enable "Promotions, Loyalty & Gift Card" - Go to Sales > Products > Discount & Loyalty - Create a new program - Name: 50% off - Program Type: Coupons - Change the existing reward to 50% discount on order - Generate some coupon - Copy the code to the generated coupon - Create a SO our product and customer - Use the coupon code & apply the 50% discount - Add shipping - Shiprocket COD - Get rate - Confirm the SO - Go to the picking & validate it - Open logs (Settings/Technical/Database Structure/Logging) - Open the "shiprocket_request_external/shipments/create/forward-shipment" log --> total_discount is 0 Cause ----- The problem comes from https://github.com/odoo/enterprise/blob/a971f55e736f9645eda137fd6dcb574483886483/delivery_shiprocket/models/shiprocket_request.py#L301 There are 2 issues here. The first and most important one is how we find the discount lines. https://github.com/odoo/enterprise/blob/a971f55e736f9645eda137fd6dcb574483886483/delivery_shiprocket/models/shiprocket_request.py#L320 Discounts from coupons don't use the `sale_discount_product_id`, we'll have to define a new function to override in `sale_loyalty` for this. The second issue is that we use the untaxed discount amount. https://github.com/odoo/enterprise/blob/a971f55e736f9645eda137fd6dcb574483886483/delivery_shiprocket/models/shiprocket_request.py#L321 This leads to an incoherent total amount, since the tax is computed on the products' full prices. We should instead be forwarding the total discount value (with tax included to offset the taxes applied on the full product price). ----- Enterprise PR: https://github.com/odoo/enterprise/pull/92310 Ticket: opw-4755357 Forward-Port-Of: odoo/odoo#228375 Forward-Port-Of: odoo/odoo#223517
Shiprocket Cash on Delivery orders now send coupon discounts correctly, including the tax-inclusive discount amount. This helps ensure the amount collected from customers matches the discounted order total and avoids overcharging or reconciliation issues.
Original PR description
Issue ----- When using Shiprocket with the "Cash On Delivery", the request sent to the Shiprocket API doesn't contain the amounts discounted by coupons. Steps to reproduce ----- - Set an Indian…
Issue
-----
When using Shiprocket with the "Cash On Delivery", the request sent to the Shiprocket API doesn't contain the amounts discounted by coupons.
Steps to reproduce
-----
- Set an Indian company up (with valid address and some dummy mail & phone)
- Create a customer "IN Cust" (with valid address and some dummy mail & phone)
- Create a product "IN Prod"
- Sale price: 1000 INR
- Weight: 100g
- Set some reference, eg "INPROD"
- Create a Shiprocket delivery method
- Payment Method: COD
- Set some "Shiprocket Channel"
- Enable Debug requests
- In settings, enable "Promotions, Loyalty & Gift Card"
- Go to Sales > Products > Discount & Loyalty
- Create a new program
- Name: 50% off
- Program Type: Coupons
- Change the existing reward to 50% discount on order
- Generate some coupon
- Copy the code of the generated coupon
- Create a SO our product and customer
- Use the coupon code & apply the 50% discount
- Add shipping
- Shiprocket COD
- Get rate
- Confirm the SO
- Go to the picking & validate it
- Open logs (Settings/Technical/Database Structure/Logging)
- Open the "shiprocket_request_external/shipments/create/forward-shipment" log
--> total_discount is 0
Cause
-----
The problem comes from
https://github.com/odoo/enterprise/blob/a971f55e736f9645eda137fd6dcb574483886483/delivery_shiprocket/models/shiprocket_request.py#L301
There are 2 issues here.
The first and most important one is how we find the discount lines.
https://github.com/odoo/enterprise/blob/a971f55e736f9645eda137fd6dcb574483886483/delivery_shiprocket/models/shiprocket_request.py#L320
Discounts from coupons don't use the `sale_discount_product_id`. We can use the `_can_be_invoiced_alone` function to find both regular and loyalty discounts
https://github.com/odoo/odoo/blob/ee63fe7863dfa0083674dc927c1aa67c9e36c481/addons/sale/models/sale_order_line.py#L1033-L1041
def _can_be_invoiced_alone(self):
""" Whether a given line is meaningful to invoice alone.
It is generally meaningless/confusing or even wrong to invoice some specific SOlines
(delivery, discounts, rewards, ...) without others, unless they are the only left to invoice
in the SO.
"""
self.ensure_one()
return self.product_id.id != self.company_id.sale_discount_product_id.id
https://github.com/odoo/odoo/blob/ee63fe7863dfa0083674dc927c1aa67c9e36c481/addons/sale_loyalty/models/sale_order_line.py#L50-L51
def _can_be_invoiced_alone(self):
return super()._can_be_invoiced_alone() and not self.is_reward_line
We just have to be careful not to accidentally include delivery fees because of
https://github.com/odoo/odoo/blob/ee63fe7863dfa0083674dc927c1aa67c9e36c481/addons/delivery/models/sale_order_line.py#L18-L19
def _can_be_invoiced_alone(self):
return super()._can_be_invoiced_alone() and not self.is_delivery
The second issue is that we use the untaxed discount amount.
https://github.com/odoo/enterprise/blob/a971f55e736f9645eda137fd6dcb574483886483/delivery_shiprocket/models/shiprocket_request.py#L321
This leads to an incoherent total amount, since the tax is computed on the products' full prices. We should instead be forwarding the total discount value (with tax included to offset the taxes applied on the full product price).
-----
Community PR:
https://github.com/odoo/odoo/pull/223517
Ticket:
opw-4755357
Forward-Port-Of: odoo/enterprise#95435
Forward-Port-Of: odoo/enterprise#92310Fixes the employee onboarding helper so teams can load sample data and add a new employee from the onboarding view. The helper now appears only in the right empty-company situations, reducing confusion for users managing employee records.
Original PR description
## Issue
The load sample data button of the employee onboarding helper doesn't work.
## PR Purpose
1) Add a "New employee" button to the onboarding view
2) Display the onboarding employee view only when :
- 'My Company' is being displayed
- There is 0 or 1 (Administrator) employee in 'My Company'
- The demo data have not been loaded
3) When you jump on an empty screen due to a search, display only the onboarding "helper blocks" (design)
Task: #4879557
Signed-off by thhaESG now limits account creation and assignment to eligible expense or fixed asset accounts, reducing confusion and protecting reporting data quality. If an existing account is changed to an ineligible type, users are warned and related ESG assignment or emission data is cleaned up if they proceed.
Original PR description
Before this PR, it was possible to create on the fly an account from the assignation lines list view of another type than "Expense" or "Fixed Assets". This is not desired, as this type of account is not part of the domain of the `account_id` field of the `esg.emission.factor.line` model. We prevent creation of such accounts from ESG in general, to avoid confusion and ensure data integrity. Moreover, when changing the account type of an existing account, if this one is changed to a type other than "Expense" or "Fixed Assets", we verify if there are some assignation lines linked to this account and/or journal items linked to that account. If so, we raise a warning to the user and if he wants to proceed, we remove the assignation lines linked to this account and remove the emission factors of journal entries linked to that account. task-4859806 Forward-Port-Of: odoo/enterprise#87295
Scanning a package in the Barcode app now correctly converts quantities when the package and delivery line use different units of measure, such as kilograms and grams. This prevents under-counting delivered quantities and helps warehouse teams validate package scans accurately.
Original PR description
Manual forward port of https://github.com/odoo/enterprise/pull/90878 **Problem:** When scanning a package with a different UoM than the barcode line, the conversion is not made. **Steps to…
Manual forward port of https://github.com/odoo/enterprise/pull/90878 **Problem:** When scanning a package with a different UoM than the barcode line, the conversion is not made. **Steps to reproduce:** - Enable the "Packages" setting; - Create a new storable product and set kg as its UoM; - In the inventory tab, add "g" in the packagings - Click on the on hand smart button and select update quantity - Add a new line; - In the package column create a new package; - Set a quantity of 10 kg; - Create a delivery and select your product; - Set a demand on 10000 and select g as the UoM; - Mark as todo; - Open the delivery in the Barcode app; - Scan the package. **Current behavior:** The quantity on the line is now 10 / 10000 g **Expected behavior:** It should be 10000 / 10000 g **Cause of the issue:** https://github.com/odoo/enterprise/blob/4c9fa9dc010958710d848fbcb3241b17ea7205ca/stock_barcode/static/src/models/barcode_picking_model.js#L1500-L1505 remaining_qty is expressed in the uom of the quant so it will be 10 but qty_needed is expressed in the uom of the line is it will be 10000. qty_used beeing the minimum of those two it will be 10. **Fix:** To define how much quantity to take from the package, we convert the line's quantity by using the package's UoM. Then, when we add this quantity to the line's quantity, we re-convert it by using the line's UoM. opw-4860064 Forward-Port-Of: odoo/enterprise#93693
This fix ensures that when a user chooses one delivery move line and puts it in a package, only that selected item is assigned to the package. It prevents unrelated products in the same delivery from being packed together by mistake, improving accuracy in shipping operations.
Original PR description
Steps to reproduce the bug:
- Create two storable products, e.g., “P1” and “P2”.
- Create a delivery:
- Add one unit of each product.
- Add any carrier (e.g., DHL).
- Mark the picking as "To Do".
- Set the quantity to 1.
- The move lines are created.
- Click on the Moves smart button.
- Select any move line (ML).
- Click Put in Pack.
- A wizard is triggered.
- Select any pack.
Problem:
The pack is applied to both move lines instead of only the selected one.
opw-5104034
Forward-Port-Of: odoo/odoo#228470
Forward-Port-Of: odoo/odoo#228350Fixes an issue where enabling VAT number verification on a non-empty EC Sales List could create duplicate checks and cause an error. Businesses can now run the report with VAT verification enabled without encountering a blocking traceback.
Original PR description
Create tax return checks for a non-empty EC Sales List report when the option "Verify VAT Numbers" (vat_check_vies) is enabled implies to create 2 checks with the same code (check_partner_vies). This is forbidden and raises a traceback. opw-5079474 opw-5090602 opw-5094853 opw-5103611 Forward-Port-Of: odoo/enterprise#95551
This fix makes website page settings behave correctly when a page URL and menu visibility are changed at the same time. It also ensures newly marked page templates appear immediately when creating a new page, reducing confusion for website editors.
Original PR description
Since [1], the page dependencies algorithm was updated, requiring adjustments to the tour logic. Additionally, following [2], the "Add new content" button was changed from an `<a>` tag to a…
Since [1], the page dependencies algorithm was updated, requiring adjustments to the tour logic. Additionally, following [2], the "Add new content" button was changed from an `<a>` tag to a `<button>`, which also needed to be reflected in the tour. Furthermore (see [3]), removing a page from the menu could silently fail when the page URL was changed in the same save because the wizard only looked up menus by the current URL. Resolve menus by page_id (fallback to URL) in both compute and inverse, and unlink accordingly, ensuring "In Menu" toggles work reliably across URL changes. Also, since [4], the "New Page" dialog cached the templates list, so pages newly marked as "Is a Template" didn't appear until a reload. Fetch templates without client-side caching so the Custom tab reflects changes immediately. This fixes the tour steps for "Verify is not in menu" and "Verify template Cool Page exists." Steps to reproduce: A. "In Menu" toggle fails when URL also changes (unlink by URL only) - Website > Go to any page (e.g., /cool-page). - Click Edit > Page (properties). - Change URL from /cool-page to /cool-page-2. - In the same dialog, disable "In Menu" (It should be automatic). - Click Save & Close. - Bug (before): The corresponding menu item is not removed because the unlink resolves only by the old/current URL. Now: Menus are resolved and unlinked by page_id (fallback to URL), so the menu entry is correctly removed. B. "New Page" > Custom templates list becomes stale (client cache) - Create a normal website page (not a template). - Open Page (properties) and enable "Is a Template". Save. - Without reloading the site, click New (Add new content) > New Page. - Open the Custom tab. - Bug (before): The page you just turned into a template doesn't appear because the dialog used a cached list. Now: The dialog fetches templates without client caching, so the new template appears immediately. [1]: https://github.com/odoo/odoo/commit/cd4b0c91c1cf60ff72e91cf0544cb255ee5aff3f [2]: https://github.com/odoo/odoo/commit/9fe45e2b7ddbbfd0445ffe25a859e67a316d02b2 [3]: https://github.com/odoo/odoo/commit/d6c8177824be3 [4]: https://github.com/odoo/odoo/commit/b7fe6e6704fad runbot-224020
Users who work across multiple companies can now assign themselves to planning slots in a company where they have an employee profile, even if another company is set as their current company. This prevents silent failures and makes multi-company planning assignments behave as expected.
Original PR description
_______________________________________ ## Short functional explanation of the error Let's say we have the scenario where a user has access to company_1 and company_2, but only has a corresponding…
_______________________________________ ## Short functional explanation of the error Let's say we have the scenario where a user has access to company_1 and company_2, but only has a corresponding employee in company_2. If the user selects company_1 and company_2 but keeps company_1 as his current company, and tries to assign himself a task that has been created for company_2, nothing happens. ## Reproduction Steps 1. As an admin, create a user with which you'll be able to log. Make sure that you have at least 2 companies created, and that the user has access to both. Create an employee for that user in company_2. 2. Select both companies. In planning, create a slot for company_2 and publish it. 3. Log in as the user you created. Make sure that the current company is company_1. Select company_2. 4. Go to planning and try to assign yourself to the slot you've just created as an admin ### Expected behavior Either an error message shows, or the employee is assigned to the slot for company_2 (as company_2 is selected). ### Unexpected behavior Nothing happens ## Origin of the issue When the current company isn't the one corresponding to the one the employee is in, even if another company is selected and contains the employee, self.env.user.employee_id is set at False _________________________________________ opw-4963674 --- Forward-Port-Of: odoo/enterprise#91616
Point of Sale now only shows the option to delete cash in/out entries to users who have the right permissions, and displays a clear error if deletion is refused. This avoids confusing failed actions and fixes receipt printing errors related to cash movement receipts.
Original PR description
Before this commit, a user with "account.group_account_invoice" group could try to delete a cash in/out in the pos but had no feedback. Actually, his request was refused but we never tell the user why. We now display the error but also do not give the possibility to the user to delete a cash in/out if he does not have the right group. There was also errors appearing when printing the CashMoveReceipt. We call the ReceiptHeader in the CashMoveReceipt but without giving it a real order which could cause problems cause in the ReceiptHeader we consider the order that is given as a real one and we can call methods and stuff from the model. We now create a dummy order to give to the ReceiptHeader. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#228789
This fix prevents sale orders linked to projects from becoming stuck when a related analytic account has been deleted. Users can update the project on affected sale orders without encountering a missing-record error, improving reliability in sales and project workflows.
Original PR description
# Issue: In a sale order, if any of the so lines contains the ID of a deleted analytic account in its analytic_distribution field, then updating the project_id field is impossible as it raises an…
# Issue: In a sale order, if any of the so lines contains the ID of a deleted analytic account in its analytic_distribution field, then updating the project_id field is impossible as it raises an error. # Cause This is caused because _compute_analytic_distribution() tries to retrieve 'root_plan_id' from all ids without checking if records exists. # Fix This commit add an exists() check on analytic.accounts retrieved from analytic_distribution field and clear the non-existing records ids from the field. # Steps to reproduce - Install sale_project and accountant modules - Check "Analytic Accounting" in the Accounting settings - Create a new project "Test P", set it up "Billable", with a new Analytic account "Test AC" (field "Project" tab "Analytic") - Create a new sale order "Test SO", add a few products and set up the Project field to "Test P". Save the sale order. - Delete the analytic.account "Test AC" - Go back on "Test SO", try to change the field "Project" - a Missing error is thrown --- Current behavior before PR: When creating a sale order and binding it to a project with an analytic account, then deleting the analytic account, the field "Project" on the sale order can't be updated anymore. Desired behavior after PR is merged: When creating a sale order and binding it to a project with an analytic account, then deleting the analytic account, the field "Project" on the sale order can be updated. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#224895
Spanish POS orders using TicketBAI now automatically retry the previously failed submission when a new order is paid. This helps prevent one failed tax report from creating a growing backlog of unreported sales, reducing manual follow-up for users.
Original PR description
Currently, the post failure of a single pos order can easily cause a backlog of more unposted orders since new orders will not be posted until the chain head is posted. Steps to reproduce ----- 1. Validate a pos order and have the TicketBAI post fail 2. Validate another pos order 3. The post for the second order is never attempted Cause ----- `_check_can_post()` ensures that new orders are not posted if the chain head was not posted successfully. During normal operation, it is common for many new orders to be paid before the user has a chance to manually retry the chain head post in the backend, causing a backlog of unposted orders. Solution ----- During `action_pos_order_paid()` retry the chain head post if is not sent. opw-4669823 Forward-Port-Of: odoo/odoo#228477
Deleting a countdown snippet in the website editor no longer leaves background activity running after the block is removed. This prevents repeated errors and keeps the editing experience stable when users delete embedded website content.
Original PR description
Before this commit, interactions where not always destroyed when their target was removed from the DOM. An example of this problem is given by the `s_countdown` snippet. When the snippet is removed…
Before this commit, interactions where not always destroyed when their target was removed from the DOM. An example of this problem is given by the `s_countdown` snippet. When the snippet is removed by `DeletePlugin`, the interaction is not destroyed, and a recurrent interval keeps expiring every second triggering multiple errors. This commit introduces the following changes: 1. `EditInteractionPlugin.refreshInteractions`, which is called on normalization, now checks for every interaction and destroyes the ones linked to a disconnected DOM element. 2. `websiteEditService.refresh` now checks if the target element is disconnected, and in this case stops the interaction. 3. `Countdown` now uses the `waitForTimeout` function, which does not execute any callback if the interation has been destroyed. How to reproduce the problem with `s_countdown`: 1. Insert the snippet `s_text_block` 2. Insert the snippet `s_countdown` in the middle of the text 3. Place the cursor after the countdown 4. Press "backspace" until the countdown is deleted 5. The error appears (Alternatively, place the cursor before the countdown and press delete, or select a portion of text including the countdown and press backspace). task-4367641
Point of Sale now only shows paid orders from the current register setup or its trusted related setups. This prevents staff from seeing unrelated orders from other locations or configurations, reducing confusion and improving order accuracy.
Original PR description
Before this commit, when searching paid orders in the PoS UI, orders from other configs could appear even if they were not part of the trusted configs or the same PoS config. This commit ensures that only orders related to the current PoS configuration (or its trusted configs) are loaded and displayed. opw-5083747 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#228289 Forward-Port-Of: odoo/odoo#227709
The rental schedule now correctly lists every rental order when the same serial-numbered item is rented more than once. This helps teams see accurate rental demand and availability instead of undercounting repeated rentals.
Original PR description
**Current Behavior:** With rental transfers enabled, renting a product with a serial number multiple times will result in the rental schedule only showing one of multiple rental orders for that SN.…
**Current Behavior:** With rental transfers enabled, renting a product with a serial number multiple times will result in the rental schedule only showing one of multiple rental orders for that SN. **Expected Behavior:** All rentals for the same SN should appear in the rental schedule. **Steps to Reproduce:** - Go to Rental > Configuration > Settings and enable Rental Transfers - Create a new product that is storable, can be rented, and is tracked by unique serial number - Receive 25 of the product with assigned serial numbers - Create and confirm a rental order for 25 units of product - Validate both OUT and IN transfers - Duplicate the rental order and confirm it - Check Rental > Schedule -> Odoo says 25 total units across the original and duplicate orders, but they each have 25 **Cause of the Issue:** Previously, commit ed5fd2693fc fixed a bug where all serial numbers would display regardless of whether they were involved in a rental. This introduced this bug, where only the first stock move line with a distinct serial number would be shown in the rental schedule. **Fix:** Change the "SELECT DISTINCT ON" to "sml". We can get all distinct stock move lines as we can expect SNs to appear multiple times. opw-5003247 Forward-Port-Of: odoo/enterprise#95315
This fixes an issue where shoppers could select a free reward product from a coupon offer but it was not added to their cart. The checkout now correctly recognizes the selected reward product, helping promotional campaigns work as expected.
Original PR description
Versions -------- - 18.0+ Steps ----- 1. Have a coupon program with a free product reward using a product tag; 2. generate coupons & copy a coupon code; 3. have 2 or more products with the tag; 4. go to /shop & add any product to your cart; 5. go to checkout; 6. apply coupon code; 7. select a free product; 8. click "Use". Issue ----- Product isn't added to the cart. Cause ----- On forward porting a fix for a similar issue in bb92ba5fbba94, it accidentally checks for the `product_id` in `request.env` instead of `request.env.context`. As no `product_id` is found, no product is added. Solution -------- Check `request.env.context` instead of `request.env`. opw-4979939 Forward-Port-Of: odoo/odoo#229157 Forward-Port-Of: odoo/odoo#224166
3 changes
Resolved issues and error corrections
This update improves how Odoo communicates with Belgian POS blackbox devices, reducing delays caused by repeated failed reads from the serial port. It also improves device detection and retry handling so a newly connected blackbox is recognized more reliably and communication buffers are kept clean.
Original PR description
This commit is a backport of some parts of odoo/enterprise#93614. The goal is to ensure that we don't read too many different times from the serial port, as each read has a timeout of 3 seconds: if 2 read fail, we exceed the longpolling's timeout. We then backport the `read_until(char)` instead of `read(n)` allowing us to read not more than once (except for the lrc, which is read only if first read is successful). We also backport the supported retry, which ensures we detect a blackbox when we plug one (prevent detecting it as an Adam Scale), and correctly flush buffers after writing/reading. Task: 5116854 Forward-Port-Of: odoo/enterprise#95755 Forward-Port-Of: odoo/enterprise#95635
OSS tax reports can now open correctly when a fiscal position uses a country group, such as Mainland Spain, instead of a single country. This helps businesses report EU OSS taxes for regions like Spain and the Canary Islands without report access errors.
Original PR description
To be able to deal with Spain with Canary Islands and mainland, we have a country group that is Mainland Spain VAT, with Spain minus several states (Canary basically). People want to be able to use it for OSS. But currently, if you have an entry with a tax with a fp with this country group (and no country), you can't open your OSS Report. So take the countries of the country group if there is none in the fiscal position.
This update prevents errors when multiple employees are clocked in on the same Belgian POS. Sales and session closing can now continue normally in this scenario, reducing disruption for store staff.
Original PR description
- Fix traceback when trying to sell a product with multiple employees clocked in on the same POS. - Fix traceback when trying to close a session with multiple employees clocked in. task-id: 4902090 Forward-Port-Of: odoo/enterprise#93273
3 changes
Resolved issues and error corrections
Engineering change orders now correctly track very small bill of materials quantity changes when products use more precise units of measure. This prevents quantity adjustments from being rounded away, helping manufacturing teams review and apply precise component changes reliably.
Original PR description
Steps to reproduce the bug:
- Go to Decimal Accuracy → Product Unit of Measure → set digits to 4
- Go to Units of Measure Categories → select a unit → set rounding to 0.0001
- Create a storable product “P1” with a BoM:
- Component C1: 1.0000 unit
- Create an ECO for the BoM with type BoM update
- Start the revision
- Go to V2
Problem:
You cannot update the quantity of C1 to 1.0003 (for example) because the system uses the default 2 digits instead of the UoM digits.
opw-5082488
Forward-Port-Of: odoo/enterprise#95180Fixed an error that could stop users from opening the General Ledger from the Trial Balance when multiple companies were selected. This improves reliability for accounting teams using multi-company reporting, especially when certain account codes are hidden.
Original PR description
**Issue** When multiple companies are selected and Developer Mode is enabled, clicking "View General Ledger" for an account in the Trial Balance leads to a traceback. This affects accounts whose code is hidden. **Steps to Reproduce** 1. Go to Accounting > Reporting > Trial Balance. 2. Select multiple companies. 3. Click on an account where the account code is not visible. 4. From the three-dot menu, select "View General Ledger". 5. Observe the traceback error. **Root Cause** The error occurs because the `AccountReportSearchBar` component expects a string `initialQuery` prop, but in the multi-company scenario with developer mode enabled, the value passed can be `undefined` or non-string. Owl's strict prop validation then throws an `OwlError`, leading to the traceback. **Fix** Ensure that `initialQuery` is always a string when passed to `AccountReportSearchBar`. Opw-5050843 Forward-Port-Of: odoo/enterprise#94104
Fixed an issue where the rental schedule could hide later rental orders for the same serial-numbered product when rental transfers were enabled. Businesses can now see all bookings for the same serialized item, improving schedule accuracy and reducing missed rental visibility.
Original PR description
**Current Behavior:** With rental transfers enabled, renting a product with a serial number multiple times will result in the rental schedule only showing one of multiple rental orders for that SN.…
**Current Behavior:** With rental transfers enabled, renting a product with a serial number multiple times will result in the rental schedule only showing one of multiple rental orders for that SN. **Expected Behavior:** All rentals for the same SN should appear in the rental schedule. **Steps to Reproduce:** - Go to Rental > Configuration > Settings and enable Rental Transfers - Create a new product that is storable, can be rented, and is tracked by unique serial number - Receive 25 of the product with assigned serial numbers - Create and confirm a rental order for 25 units of product - Validate both OUT and IN transfers - Duplicate the rental order and confirm it - Check Rental > Schedule -> Odoo says 25 total units across the original and duplicate orders, but they each have 25 **Cause of the Issue:** Previously, commit ed5fd2693fc fixed a bug where all serial numbers would display regardless of whether they were involved in a rental. This introduced this bug, where only the first stock move line with a distinct serial number would be shown in the rental schedule. **Fix:** Change the "SELECT DISTINCT ON" to "sml". We can get all distinct stock move lines as we can expect SNs to appear multiple times. opw-5003247 Forward-Port-Of: odoo/enterprise#95315
14 changes
Resolved issues and error corrections
Mexican electronic invoicing now handles cases where the US dollar currency has been deactivated. This prevents invoice confirmation and sending from failing for companies using Mexico localization and external trade documents.
Original PR description
**Steps to Reproduce:** 1. Install `l10n_mx_edi_extended` module without demo data. 2. Set company's country to "Mexico" and switch Fiscal Localization. 3. Deactivate USD currency. 4. Configure CFDI…
**Steps to Reproduce:** 1. Install `l10n_mx_edi_extended` module without demo data. 2. Set company's country to "Mexico" and switch Fiscal Localization. 3. Deactivate USD currency. 4. Configure CFDI Certificate and activate Testing mode in PAC. 5. Create a new product with "UNSPSC Category". 6. Create an invoice with CFDI to the public and "Definitive" in External Trade. 7. Confirm and send the invoice. **Sample certificate:** Certificate file: https://drive.google.com/file/d/1kklNGeRtR08erxWRPfIdeiwheDibcB8M/view?usp=drive_link Private key file: https://drive.google.com/file/d/1VJnKVo1doA4cCYPeZBHXKT4JGkbHhOhk/view?usp=drive_link Private key password: 12345678a **Error:** `ValueError - Expected singleton: res.currency()` **Cause:** When sending the invoice, the system attempts to retrieve the USD currency to compute exchange rates. Since the search only considers active currencies, this results in no record being returned, which raises an error in further computation. **Fix:** This commit handles the case when USD currency is deactivated. sentry-6860601127 Forward-Port-Of: odoo/enterprise#94179
Orders from self-service or kiosk online payments now appear on the preparation display only after payment is confirmed. This prevents staff from preparing unpaid orders while still ensuring confirmed orders reach the kitchen display, including when customers leave through the payment portal exit flow.
Original PR description
pos_*= pos_online_payment_self_order_preparation_display, pos_self_order_iot Before this commit, if an online payment method was assigned to a self or a kiosk, the order was displayed on the preparation display before the payment was confirmed. After this commit, the order is no longer displayed on the preparation display until the payment confirmation. Community PR: https://github.com/odoo/enterprise/pull/87173 Backport of https://github.com/odoo/odoo/pull/87173, with additional logic to ensure the order is correctly sent to the preparation display even if an exit route is used in the payment portal Forward-Port-Of: odoo/enterprise#95583 Forward-Port-Of: odoo/enterprise#95312
The Australian Taxable Payments Annual Report now excludes unrelated customer payments from the Gross Paid amount. This makes TPAR figures more accurate by counting only relevant supplier payment lines for report calculations.
Original PR description
Customer payment shoudn't be included in the TPAR report Steps: - Unarchive 10% TPAR tax - Make a bill for a partner X, set 10% TPAR tax on the invoice line and confirm - Create and confirm a customer payment for partner X - Go to 'Taxable Payments Annual Reports (TPAR)' -> The column 'Gross Paid' includes the customer payment Before this commit, we took all line from bank or cash journal to calculate the gross paid value. With this commit, we also restrict the lines to include only the one with 'asset_current' or 'liablility_current' account type. Ticket [link](https://www.odoo.com/odoo/project/967/tasks/5045457) opw-5045457 Forward-Port-Of: odoo/enterprise#95592 Forward-Port-Of: odoo/enterprise#95029
This change corrects how Mexican electronic invoices are calculated so totals match the official XML validation rules. It helps prevent valid invoices from being rejected because of tiny rounding differences in decimal amounts.
Original PR description
The validation in the XML are made based on values rounded to 6 digits. However in Odoo, we do the computation without any rounding. 352.2413793103448 + 876.7435344827586 + 162.92327586206898 + 198.73706896551727 + 526.0383620689655 + 17.241379310344826 = 2133.925 ~= 2133.93 352.241379 + 876.743534 + 162.923276 + 198.737069 + 526.038362 + 17.241379 = 2133.924999 ~= 2133.92 != 2133.93 opw-5096249 Forward-Port-Of: odoo/enterprise#95555 Forward-Port-Of: odoo/enterprise#95413
Rental orders are no longer blocked by unavailable planning resources when shift synchronization is disabled. This prevents unnecessary confirmation failures in the portal and rental app, making rentals proceed as expected when planning shifts are not being synced.
Original PR description
Step to reproduce: - Set up a role with a resource not available this week - Not activate the option to sync Rental order - Shift - Set up a rental-service product, with an auto-plan for this role Issue: - Rental orders could not be confirmed from the portal or the rental app if the required resource was unavailable, even when the `sync_shift_rental` option was not disabled. Cause: - The logic in `_planning_slot_vals_list_per_sol` treated all unavailable resources as problematic, without checking whether the shift synchronization was enabled (`sync_shift_rental`), resulting in unnecessary blocking of the order confirmation. Solution: - Added a condition to check if `sync_shift_rental` is enabled before marking a service as problematic. This allows rental orders to be confirmed when shift sync is disabled. task-5072920 Forward-Port-Of: odoo/enterprise#95745 Forward-Port-Of: odoo/enterprise#94176
Fixed an issue where the download menu for a signature request could appear empty when the request was opened from a record's chatter. Users can now reliably access the related documents from the download dropdown, reducing confusion and extra navigation.
Original PR description
Version: - saas-18.4 Steps to reproduce: - Create sign request from 'request signature' activity. - From the chatter of the related record, open the sign request. - It will redirect to form view of that sign request. - click on download dropdown button. Before: - The download dropdown was empty. - This happened because the 'sign_request_documents_dropdown' widget tried to use 'active_id' from the context, but 'active_id' was missing when the sign request was opened from chatter. After: - The download dropdown correctly shows the related documents. - When active_id is not in the context, the widget now uses the sign request id from evalcontext, so it can fetch the right documents. Impact: - Users will always see the correct documents in the download dropdown, even when opening a sign request from chatter. task-5089829 Forward-Port-Of: odoo/enterprise#94885
The AI service now handles invalid tool requests and usage limits more clearly, preventing conversations from stalling or failing silently. This makes AI-powered features more dependable and helps the system recover gracefully when the model makes an unsupported request.
Original PR description
This commit introduces several related fixes to the LLM API service to make tool call processing more robust and prevent silent failures. - **Unknown Tool Calls**: When an LLM requests a tool with an…
This commit introduces several related fixes to the LLM API service to make tool call processing more robust and prevent silent failures. - **Unknown Tool Calls**: When an LLM requests a tool with an invalid or unknown name, it previously resulted in an empty response, causing the conversation to stall. This change ensures that a proper error message is now returned to the LLM for the invalid tool call. This allows the LLM to process the failure and continue the conversation. - **Failing on Limits**: The query processing loop in `_request_llm` has limits for both successive API calls and the number of tool calls per request. Previously, these limits would be reached silently. - **API Call Limit**: If the `AI_MAX_SUCCESSIVE_CALLS` limit is reached without the LLM providing a final answer, a `ValueError` is now raised. This prevents silent failures and makes it clear to the calling code that the request could not be completed. - **Tool Call Limit**: If the number of tool calls in a single response exceeds `AI_MAX_TOOL_CALLS_PER_CALL`, any calls beyond the limit are now provided with a result stating that the limit was reached. This gives the LLM the opportunity to try the unprocessed tool calls again in a subsequent turn. - **Ignore Explanatory Text**: The text that LLMs often include alongside a tool call request (the "thinking" text) is now ignored to provide a cleaner and more concise final response to the user. Forward-Port-Of: odoo/enterprise#94413
Creating a related monetary field in Studio now also creates the matching related currency field, so the amount can be used correctly. This prevents unusable monetary fields and helps ensure values display and calculate with the right currency.
Original PR description
Before this commit, when creating a related field to a monetary, the created currency field was not stored and not related either, so the monetary was unusable. This was because of 5cf5a35a0a8f78655989009d0eddcf39f8430965 , b177b058be1531c3d2af2b591c22591c19240d33 and in general the changes in read_group that largely improve the situation. After this commit, we create a currency field related to the currency field of the related monetary to ensure that the monetary's value is coherent. This is made possible by the above mentionned improvements in read_group opw-5094619 Forward-Port-Of: odoo/enterprise#95407
Carbon emissions calculations now convert quantities using the unit of measure expected by the emission factor, rather than the invoice line. This fixes incorrect emissions values and improves the reliability of ESG reporting.
Original PR description
Prior to this commit, the UoM conversion in the carbon emissions calculation was done by targeting the UoM of the account move line instead of the UoM of the emission factor. Which led to incorrect emissions values calculations. task-5107685 Forward-Port-Of: odoo/enterprise#95468
Invoices from Point of Sale can once again be sent directly to configured IoT printers instead of only being downloaded as PDFs. This fixes a regression and reuses the printer selection flow so printing behavior stays consistent across reports and invoices.
Original PR description
This PR contains two commits, the first is a refactoring, and the second is the invoice printing itself. - **[REF] iot: extract printer select into separate function** Before this commit, the printer…
This PR contains two commits, the first is a refactoring, and the second is the invoice printing itself.
- **[REF] iot: extract printer select into separate function**
Before this commit, the printer selection wizard was tightly coupled to
the IoT report handler, and the call to send to the printer was
duplicated in the wizard and the handler.
After this commit, the printer selection wizard is contained in a
function that will always return the selected printers directly to the
caller, whether the dialog needs to be opened or not. The wizard is
simplified as a result and the print call always occurs in the handler.
This refactoring will allow other places to use the printer selection
wizard, namely for invoice printing.
- **[FIX] pos_iot: print invoices via IoT**
In the commit https://github.com/odoo/enterprise/commit/07418d7544ceecfef38257db8f59bf845a0b0769, the invoice PDF downloading was refactored to
bypass the `ir.actions.report` model, instead working directly via an
action on the invoice model. A side effect of this is that it broke
printing invoices via the IoT, as it relies on the report printing
action to function.
To fix this, this commit introduces an override in `pos_iot` for the
`account_move_service`, which will print the invoice PDF via the IoT
instead of downloading it directly (if a printer is associated with the
report).
task-5109814
Forward-Port-Of: odoo/enterprise#95689
Forward-Port-Of: odoo/enterprise#95586Fixed an issue that could cause an error when users viewed the General Ledger from the Trial Balance while working with multiple selected companies. This prevents interruptions for accounting users, especially when account codes are hidden and Developer Mode is enabled.
Original PR description
**Issue** When multiple companies are selected and Developer Mode is enabled, clicking "View General Ledger" for an account in the Trial Balance leads to a traceback. This affects accounts whose code is hidden. **Steps to Reproduce** 1. Go to Accounting > Reporting > Trial Balance. 2. Select multiple companies. 3. Click on an account where the account code is not visible. 4. From the three-dot menu, select "View General Ledger". 5. Observe the traceback error. **Root Cause** The error occurs because the `AccountReportSearchBar` component expects a string `initialQuery` prop, but in the multi-company scenario with developer mode enabled, the value passed can be `undefined` or non-string. Owl's strict prop validation then throws an `OwlError`, leading to the traceback. **Fix** Ensure that `initialQuery` is always a string when passed to `AccountReportSearchBar`. Opw-5050843 Forward-Port-Of: odoo/enterprise#94104
Peruvian electronic invoices now show the invoice currency for deducted down payments instead of defaulting to the company's currency. This prevents foreign-currency invoices from displaying PEN incorrectly, reducing compliance and customer-facing document errors.
Original PR description
#### Issue: - After invoicing a downpayment in a foreign currency, in the XMl of the total invoice, the currency_id on the prepaid tag is set to PEN instead of the right currency. #### Step to…
#### Issue: - After invoicing a downpayment in a foreign currency, in the XMl of the total invoice, the currency_id on the prepaid tag is set to PEN instead of the right currency. #### Step to reproduce: 1. Install l10n_pe_edi 2. Sell a product to "Comercial Constructora los Patitos" through the sales app and make sure you use USD (or a different currency than PEN). 3. Create a downpayment invoice, could be any percentage. 4. To make sure it works correctly, add a random document number on the invoice with the format ABC-01234567. 5. Confirm this invoice. 6. Now go back to the sale order and deliver your product. 7. Create the final invoice, where the downpayment will be deducted. Make sure it is also in USD (or whatever currency you chose). 8. Confirm the invoice. #### Current behavior: - Display "PEN" in the attribute currencyID of tag PaidAmount in a PrepaidPayment: <cbc:PaidAmount currencyID=PEN> #### Expected behavior: - The currency displayed should match the invoice currency #### Cause of the issue: - the currency of the company emitting the invoice was used instead of the currency of the invoice. opw-5061019 Forward-Port-Of: odoo/enterprise#93885
This fixes an error that could occur when generating tax return checks for a non-empty EC Sales List with VAT number verification enabled. Businesses can now use the VAT verification option without the process failing because of duplicate check entries.
Original PR description
Create tax return checks for a non-empty EC Sales List report when the option "Verify VAT Numbers" (vat_check_vies) is enabled implies to create 2 checks with the same code (check_partner_vies). This is forbidden and raises a traceback. opw-5079474 opw-5090602 opw-5094853 opw-5103611 Forward-Port-Of: odoo/enterprise#95551
ESG account assignment now only allows accounts that are appropriate for emissions tracking, reducing confusion and incorrect data entry. If an account is changed to an unsupported type, users are warned and related ESG assignment or emission data is cleaned up to keep reports accurate.
Original PR description
Before this PR, it was possible to create on the fly an account from the assignation lines list view of another type than "Expense" or "Fixed Assets". This is not desired, as this type of account is not part of the domain of the `account_id` field of the `esg.emission.factor.line` model. We prevent creation of such accounts from ESG in general, to avoid confusion and ensure data integrity. Moreover, when changing the account type of an existing account, if this one is changed to a type other than "Expense" or "Fixed Assets", we verify if there are some assignation lines linked to this account and/or journal items linked to that account. If so, we raise a warning to the user and if he wants to proceed, we remove the assignation lines linked to this account and remove the emission factors of journal entries linked to that account. task-4859806 Forward-Port-Of: odoo/enterprise#95833 Forward-Port-Of: odoo/enterprise#87295
27 changes
Resolved issues and error corrections
Store pickup checkout now checks the total quantity of the same product across all cart lines, even when different units of measure are used. This prevents customers from completing checkout without a warning when a store does not have enough stock overall.
Original PR description
Steps to reproduce: 1. Enable Pickup in Store in eCommerce. 2. Create a product with multiple UoMs (e.g., Unit, Pack of Six). 3. Add the product to the cart using different UoMs in separate lines. 4. Select a store with insufficient total stock but enough for individual lines. 5. Proceed to checkout → No warning is shown. After this commit, all order lines will be taken into account when checking available stock. opw-5108294
Self-order and kiosk orders paid online now appear on the preparation display only after payment is confirmed. This prevents staff from preparing unpaid orders while still ensuring paid orders reach the display even if customers leave the payment flow through an exit route.
Original PR description
pos_*= pos_online_payment_self_order_preparation_display, pos_self_order_iot Before this commit, if an online payment method was assigned to a self or a kiosk, the order was displayed on the preparation display before the payment was confirmed. After this commit, the order is no longer displayed on the preparation display until the payment confirmation. Community PR: https://github.com/odoo/enterprise/pull/87173 Backport of https://github.com/odoo/odoo/pull/87173, with additional logic to ensure the order is correctly sent to the preparation display even if an exit route is used in the payment portal Forward-Port-Of: odoo/enterprise#95583 Forward-Port-Of: odoo/enterprise#95312
Self-order and kiosk orders paid online now appear on the preparation display only after payment is confirmed. This prevents staff from preparing unpaid orders while still ensuring confirmed orders are sent correctly, including when customers leave through the payment portal exit flow.
Original PR description
pos_*= pos_online_payment, pos_online_payment_self_order, pos_self_order Before this commit, if an online payment method was assigned to a self or a kiosk, the order was displayed on the preparation display before the payment was confirmed. After this commit, the order is no longer displayed on the preparation display until the payment confirmation. Enterprise PR: https://github.com/odoo/enterprise/pull/95312 Backport of https://github.com/odoo/odoo/pull/213493, with additional logic to ensure the order is correctly sent to the preparation display even if an exit route is used in the payment portal --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#228687 Forward-Port-Of: odoo/odoo#228189
This fix corrects how units of measure are converted when calculating carbon emissions in ESG reporting. It helps ensure emissions figures are based on the emission factor's unit, improving the accuracy of sustainability reporting.
Original PR description
Prior to this commit, the UoM conversion in the carbon emissions calculation was done by targeting the UoM of the account move line instead of the UoM of the emission factor. Which led to incorrect emissions values calculations. task-5107685 Forward-Port-Of: odoo/enterprise#95468
Payroll users with Administrator access can now cancel completed payslips as intended. This removes an incorrect restriction that only allowed the general system admin user to perform the action, reducing payroll processing blockers.
Original PR description
steps to reproduce: ------------------- 1. Install payroll 2. Create a user and grant "Administrator" access to Payroll. 3. Log in as the new user and try to cancel a 'Done' payslip. issue: ------ A UserError is raised: "Cannot cancel a payslip that is done." observation: ------------ A user with Payroll "Administrator" access is unable to cancel a payroll payslip cause of the issue: ------------------- During cancellation, the system checks whether the user is "Admin" instead of verifying if the user has Payroll "Administrator" access. https://github.com/odoo/enterprise/blob/13832d80570956e504e1c09f41acbeb0bc4baedc/hr_payroll/models/hr_payslip.py#L509-L513 solution: ---------- Check that the user has Payroll "Administrator" access. opw-5040029 Forward-Port-Of: odoo/enterprise#95101 Forward-Port-Of: odoo/enterprise#93831
Bank transactions from one company branch can now be matched with payments from the main company or related branches when they share the same parent company. This prevents valid payments from being left unreconciled in branch accounting workflows.
Original PR description
…o end uuid The aim of this commit is handling branches cases with reconciliation via the end to end uuid. Before this commit, a bank transaction from a company branch couldn't be reconciled with a payment from the main company. In some situation this case could happen. Now payments and bank transactions are reconciliable even if both are from another company. It works only for companies with the same main company, branches which are sisters or parent-children relation. task-5081684
This fixes a rounding mismatch in Mexican electronic invoicing where totals could be validated differently by Odoo and the official XML rules. It helps prevent valid CFDI invoices from being rejected or showing incorrect totals due to tiny decimal differences.
Original PR description
The validation in the XML are made based on values rounded to 6 digits. However in Odoo, we do the computation without any rounding. 352.2413793103448 + 876.7435344827586 + 162.92327586206898 + 198.73706896551727 + 526.0383620689655 + 17.241379310344826 = 2133.925 ~= 2133.93 352.241379 + 876.743534 + 162.923276 + 198.737069 + 526.038362 + 17.241379 = 2133.924999 ~= 2133.92 != 2133.93 opw-5096249 Forward-Port-Of: odoo/enterprise#95555 Forward-Port-Of: odoo/enterprise#95413
Creating a related monetary field in Studio now also creates the correct linked currency field. This prevents unusable monetary values and helps ensure amounts display and calculate with the right currency.
Original PR description
Before this commit, when creating a related field to a monetary, the created currency field was not stored and not related either, so the monetary was unusable. This was because of 5cf5a35a0a8f78655989009d0eddcf39f8430965 , b177b058be1531c3d2af2b591c22591c19240d33 and in general the changes in read_group that largely improve the situation. After this commit, we create a currency field related to the currency field of the related monetary to ensure that the monetary's value is coherent. This is made possible by the above mentionned improvements in read_group opw-5094619 Forward-Port-Of: odoo/enterprise#95407
Invoices from Point of Sale can now be printed through connected IoT printers again instead of only being downloaded. This restores expected in-store printing workflows and reuses the printer selection flow to make future printing paths more consistent.
Original PR description
This PR contains two commits, the first is a refactoring, and the second is the invoice printing itself. - **[REF] iot: extract printer select into separate function** Before this commit, the printer…
This PR contains two commits, the first is a refactoring, and the second is the invoice printing itself.
- **[REF] iot: extract printer select into separate function**
Before this commit, the printer selection wizard was tightly coupled to
the IoT report handler, and the call to send to the printer was
duplicated in the wizard and the handler.
After this commit, the printer selection wizard is contained in a
function that will always return the selected printers directly to the
caller, whether the dialog needs to be opened or not. The wizard is
simplified as a result and the print call always occurs in the handler.
This refactoring will allow other places to use the printer selection
wizard, namely for invoice printing.
- **[FIX] pos_iot: print invoices via IoT**
In the commit https://github.com/odoo/enterprise/commit/07418d7544ceecfef38257db8f59bf845a0b0769, the invoice PDF downloading was refactored to
bypass the `ir.actions.report` model, instead working directly via an
action on the invoice model. A side effect of this is that it broke
printing invoices via the IoT, as it relies on the report printing
action to function.
To fix this, this commit introduces an override in `pos_iot` for the
`account_move_service`, which will print the invoice PDF via the IoT
instead of downloading it directly (if a printer is associated with the
report).
task-5109814
Forward-Port-Of: odoo/enterprise#95689
Forward-Port-Of: odoo/enterprise#95586Fixes an issue where customers using a mobile checkout could not see the PayPal payment button. This restores the ability to complete purchases with PayPal on mobile devices, reducing checkout friction and potential lost sales.
Original PR description
## Version saas-18.4+ ## Issue *Use mobile device or mobile view* - Configure Paypal as a Payment Provider; - Go to the shop and buy an article; - Move to checkout and select PayPal; - No PayPal…
## Version saas-18.4+ ## Issue *Use mobile device or mobile view* - Configure Paypal as a Payment Provider; - Go to the shop and buy an article; - Move to checkout and select PayPal; - No PayPal button is displayed. ## Cause In saas-18.4, a refactoring of the checkout layout (7a564237579603bcaef46efd6ffaaaffefb54b11) introduced the `o_mobile_summary` block which results in the full payment form being duplicated in the DOM: - One copy for desktop: - https://github.com/odoo/odoo/blob/de3d09ab8592c87b9d747a33cded93a90387b797/addons/website_sale/views/templates.xml#L3524-L3529 - One copy inside `.o_mobile_summary` for mobile: - https://github.com/odoo/odoo/blob/de3d09ab8592c87b9d747a33cded93a90387b797/addons/website_sale/views/templates.xml#L3557-L3560 This causes the `payment.submit_button` template (and its extension by PayPal) to be injected twice. As a result, the DOM ends up with two elements sharing the same IDs (`o_paypal_button_container`) which breaks PayPal’s SDK rendering logic. ## Fix JavaScript logic based on cca908741c7fdd701a4539e5d43c71248b73b14f has been added to detect and rename the duplicated DOM structure: The PayPal button can be rendered everywhere based on unique IDs. opw-4942831 Forward-Port-Of: odoo/odoo#220516
This fix prevents users from creating or keeping ESG emission factor assignments on account types that are not eligible, such as non-expense or non-fixed-asset accounts. When an account type is changed to an ineligible type, the system warns the user and cleans related ESG assignments and journal emission factors to protect reporting accuracy.
Original PR description
Before this PR, it was possible to create on the fly an account from the assignation lines list view of another type than "Expense" or "Fixed Assets". This is not desired, as this type of account is not part of the domain of the `account_id` field of the `esg.emission.factor.line` model. We prevent creation of such accounts from ESG in general, to avoid confusion and ensure data integrity. Moreover, when changing the account type of an existing account, if this one is changed to a type other than "Expense" or "Fixed Assets", we verify if there are some assignation lines linked to this account and/or journal items linked to that account. If so, we raise a warning to the user and if he wants to proceed, we remove the assignation lines linked to this account and remove the emission factors of journal entries linked to that account. task-4859806 Forward-Port-Of: odoo/enterprise#87295
The EC Sales List report no longer creates duplicate VAT number verification checks when the Verify VAT Numbers option is enabled. This prevents an error that could block users from generating tax return checks for non-empty reports.
Original PR description
Create tax return checks for a non-empty EC Sales List report when the option "Verify VAT Numbers" (vat_check_vies) is enabled implies to create 2 checks with the same code (check_partner_vies). This is forbidden and raises a traceback. opw-5079474 opw-5090602 opw-5094853 opw-5103611 Forward-Port-Of: odoo/enterprise#95551
This update prevents Swiss payroll records from being reverted in cases where that action could create incorrect payroll handling. It helps businesses avoid accidental changes to finalized payroll data and supports more reliable payroll operations.
This fix ensures packaging details are properly kept on products that have only one variant. It prevents missing packaging information while preserving the earlier fix that avoided duplicate packaging entries.
Original PR description
e158730ba16e898a13dd9a98ed96fa30fa95ab6f recently fixed a situation where one-variant products had duplicated packagings. In the aforementioned commit, we concluded that the logic to write (again) the templates values for variant-stored fields was useless because already applied to the generated variants. Nevertheless, while trying to remove in master this logic, we noticed that those varlues are only applied to variants of templates having at least one attribute line, whose creation will trigger the variants creation. This commit therefore partially reverts the previous commit, bringing back the first solution that is still the best approach in the end. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#229080
This fixes an issue where sale orders linked to projects could become difficult to update after their related analytic account was deleted. Sales users can now change the project on affected orders without encountering a blocking error.
Original PR description
# Issue: In a sale order, if any of the so lines contains the ID of a deleted analytic account in its analytic_distribution field, then updating the project_id field is impossible as it raises an…
# Issue: In a sale order, if any of the so lines contains the ID of a deleted analytic account in its analytic_distribution field, then updating the project_id field is impossible as it raises an error. # Cause This is caused because _compute_analytic_distribution() tries to retrieve 'root_plan_id' from all ids without checking if records exists. # Fix This commit add an exists() check on analytic.accounts retrieved from analytic_distribution field and clear the non-existing records ids from the field. # Steps to reproduce - Install sale_project and accountant modules - Check "Analytic Accounting" in the Accounting settings - Create a new project "Test P", set it up "Billable", with a new Analytic account "Test AC" (field "Project" tab "Analytic") - Create a new sale order "Test SO", add a few products and set up the Project field to "Test P". Save the sale order. - Delete the analytic.account "Test AC" - Go back on "Test SO", try to change the field "Project" - a Missing error is thrown --- Current behavior before PR: When creating a sale order and binding it to a project with an analytic account, then deleting the analytic account, the field "Project" on the sale order can't be updated anymore. Desired behavior after PR is merged: When creating a sale order and binding it to a project with an analytic account, then deleting the analytic account, the field "Project" on the sale order can be updated. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#224895
This fix stops loyalty points or coupon counts from being applied more than once when an order confirmation is retried, such as after an internet interruption. It helps keep customer rewards accurate and prevents incorrect loyalty balances in Point of Sale.
Original PR description
Before this commit, if the `confirm_coupon_programs` method was called twice (e.g., due to an internet issue), the loyalty points were calculated incorrectly. This commit fixes the issue by checking the existing loyalty history to prevent duplicate point calculations. To enable this, the creation of oyalty history records has been moved into the `confirm_coupon_programs` function. opw-4877599 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#224694 Forward-Port-Of: odoo/odoo#222372
Partially refunded point-of-sale orders now recalculate the amount due based on the remaining items. This prevents customers from being charged the original full total when only a remaining balance should be paid.
Original PR description
Before this commit, refunding a partially refunded order did not update the total price based on the remaining lines. As a result, it was possible to pay the original total amount instead of the correct remaining amount. opw-5100790 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#228312 Forward-Port-Of: odoo/odoo#228186
When a shopper adds either a kit product or one of its components to the cart, the website now updates the available quantity shown for related products. This prevents customers from seeing misleading stock information and helps avoid orders for items that can no longer be fulfilled.
Original PR description
### Steps to reproduce: - In the settings website > Shop: - Disable `Out-of-Stock: Continue Selling`. - Enable `Show Available Qty` if below 5 units. - Create 2 storable products published on the…
### Steps to reproduce:
- In the settings website > Shop:
- Disable `Out-of-Stock: Continue Selling`.
- Enable `Show Available Qty` if below 5 units.
- Create 2 storable products published on the website:
- COMP, put 1 unit in stock.
- KIT with bom of type Kit using 1 x COMP.
- With a private window go to the shop.
- Add 1 x COMP or KIT to the chart.
#### > This is not reflected on the available quantity in stock of the other product
### Cause of the issue:
The availability on the website is computed from the product availability using the `free_qty` fetched because of this override: https://github.com/odoo/odoo/blob/d358542c9159f325b4e2ff184ed1f5cdb6b8c5a9/addons/website_sale_stock/controllers/variant.py#L10-L13 from which the cart quantity of the product itself is deduced before re-render:
https://github.com/odoo/odoo/blob/d358542c9159f325b4e2ff184ed1f5cdb6b8c5a9/addons/website_sale_stock/static/src/js/variant_mixin.js#L49-L51 https://github.com/odoo/odoo/blob/d358542c9159f325b4e2ff184ed1f5cdb6b8c5a9/addons/website_sale_stock/static/src/js/variant_mixin.js#L83-L86 While the `free_qty` is correctly computed from kit products based on the component availability:
https://github.com/odoo/odoo/blob/d358542c9159f325b4e2ff184ed1f5cdb6b8c5a9/addons/mrp/models/product.py#L211-L221 The qties in the virtual cart quantities are not recomputed base on kits.
opw-4889956
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#228881
Forward-Port-Of: odoo/odoo#222945Timesheet filters such as Today, This Week, and Last Week now use the user's local date instead of UTC. This prevents entries from appearing under the wrong day or week for employees in different time zones.
Original PR description
This commit fixes issues with the timesheet Date filters, in which the `date` field of account.analytic.line records, which is stored as the local timezone's date, is being compared to a UTC DateTime value. This leads to off-by-one errors. For example, if you are in Berlin and try to filter for all timesheet entries from "Today", you will only find entries from the previous day. Similarly, for the "This Week" and "Last Week" filters, which would be shifted by one day. The filter domains have been changed to compare the `date` to the local timezone's "today". opw-5003310 Forward-Port-Of: odoo/odoo#225753
Shop floor barcode actions now clear the manufacturing order filter after they run, preventing teams from staying on a narrowed work order view by mistake. This makes scanner-based operations more reliable and reduces confusion on the production floor.
Original PR description
To reproduce: - Create multiple WOs in assembly line 1 - Open shop floor, assembly line 1 - Scan one of the MO barcodes to filter - Scan OBTPAUS/OBTCLMO/OBTCLWO Current behaviour: The expected action gets executed, but the MO filter set in the search bar remains. Expected behaviour: The expected action gets executed and the filter is removed. Task: 5107223
Fixes an error that could occur when users clicked Tickets Closed on the Helpdesk dashboard or applied Closed On date filters. This restores reliable access to recent closed-ticket views and prevents disruption from server error messages.
Original PR description
Steps to reproduce: - 1. Install the helpdesk module. 2. Navigate to the Helpdesk Overview dashboard. 3. On any team card (e.g., VIP Support), click the 'Tickets Closed'. 4. (Alternative): Go to the 'All Tickets' list view, open the search filters, and select a 'Closed On' date filter like 'Last 7 Days'. Issue: - Clicking the 'Tickets Closed' button or applying a 'Closed On' date filter results in a server traceback (ValueError). Cause: - The search filters used an invalid date syntax with multiple operators like `today -7d + 1d` (introduced in commit https://github.com/odoo/enterprise/commit/3db2ad2424f5d40b51bedfba4475fa6b0602c955). Fix: - Corrected the syntax like `today -7d +1d`. task-5069003
Odoo now prevents users from validating a stock transfer when there is no quantity to process. Instead of opening a backorder prompt that cannot do anything, the system shows a clear user error, reducing confusion during delivery validation.
Original PR description
### Steps to reproduce: - Create and confirm a delivery with 2 moves: - 1 x product 1 - 1 x product 2 - Set the quantity of product 2 to 0 and mark it as picked - Validate the transfer #### > The…
### Steps to reproduce:
- Create and confirm a delivery with 2 moves:
- 1 x product 1
- 1 x product 2
- Set the quantity of product 2 to 0 and mark it as picked
- Validate the transfer
#### > The backorder wizard open's even though there is nothing to validate. Creating a backorder does nothing.
#### Cause of the issue:
Since there is a picked move, the picking validation does not pick every moves in the `pre_action_done` hook keeping only moves with empty qty as picked:
https://github.com/odoo/odoo/blob/9b41eb38403e64091b74e1ae53c79488aa48b499/addons/stock/models/stock_picking.py#L1208-L1209 Then, only the picked moves are processed in there `_action_done`: https://github.com/odoo/odoo/blob/9b41eb38403e64091b74e1ae53c79488aa48b499/addons/stock/models/stock_move.py#L1914 https://github.com/odoo/odoo/blob/9b41eb38403e64091b74e1ae53c79488aa48b499/addons/stock/models/stock_move.py#L1929-L1937 Which leads to an empty picking validation.
opw-5076640
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#228490
Forward-Port-Of: odoo/odoo#227995This fixes a checkout issue where customers who selected a free product from a coupon reward could not add it to their cart. Coupon-based promotions with multiple eligible free products now work as intended, reducing checkout friction and support cases.
Original PR description
Versions -------- - 18.0+ Steps ----- 1. Have a coupon program with a free product reward using a product tag; 2. generate coupons & copy a coupon code; 3. have 2 or more products with the tag; 4. go to /shop & add any product to your cart; 5. go to checkout; 6. apply coupon code; 7. select a free product; 8. click "Use". Issue ----- Product isn't added to the cart. Cause ----- On forward porting a fix for a similar issue in bb92ba5fbba94, it accidentally checks for the `product_id` in `request.env` instead of `request.env.context`. As no `product_id` is found, no product is added. Solution -------- Check `request.env.context` instead of `request.env`. opw-4979939 Forward-Port-Of: odoo/odoo#229157 Forward-Port-Of: odoo/odoo#224166
Calendar views can now correctly filter records linked to multiple people or items, such as tasks assigned to several users. This helps teams see complete and accurate results when selecting one or more filter values in the calendar.
Original PR description
This commit add support for Many2many filters in the calendar arch. This PR follows the PR #215790 Example: Add `<field name="user_ids" filters="1" invisible="1"/>` in the calendar arch with: Tasks: - T1 assigned to A - T2 assigned to A and B - T3 assigned to B and C Giving: - A => show T1 and T2 - B => show T2 and T3 - A and B => show T1, T2 and T3 task-5005992 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The rental schedule now correctly lists every rental order for products tracked by serial number, even when the same serial number is rented again. This prevents missing bookings and gives rental teams an accurate view of product usage and availability.
Original PR description
**Current Behavior:** With rental transfers enabled, renting a product with a serial number multiple times will result in the rental schedule only showing one of multiple rental orders for that SN.…
**Current Behavior:** With rental transfers enabled, renting a product with a serial number multiple times will result in the rental schedule only showing one of multiple rental orders for that SN. **Expected Behavior:** All rentals for the same SN should appear in the rental schedule. **Steps to Reproduce:** - Go to Rental > Configuration > Settings and enable Rental Transfers - Create a new product that is storable, can be rented, and is tracked by unique serial number - Receive 25 of the product with assigned serial numbers - Create and confirm a rental order for 25 units of product - Validate both OUT and IN transfers - Duplicate the rental order and confirm it - Check Rental > Schedule -> Odoo says 25 total units across the original and duplicate orders, but they each have 25 **Cause of the Issue:** Previously, commit ed5fd2693fc fixed a bug where all serial numbers would display regardless of whether they were involved in a rental. This introduced this bug, where only the first stock move line with a distinct serial number would be shown in the rental schedule. **Fix:** Change the "SELECT DISTINCT ON" to "sml". We can get all distinct stock move lines as we can expect SNs to appear multiple times. opw-5003247 Forward-Port-Of: odoo/enterprise#95315
Point of Sale now waits until a blackbox discount has finished applying before allowing payment to proceed. This prevents payments from being created with an outdated amount, reducing cashier confusion and terminal payment errors.
Original PR description
Before this commit, if a discount was applied with the blackbox, it was applied after communication with blackbox which could be slow. If the user was clicking payment before this disound was applied and had only one payment method, a payment line with the old amount was added which could lead to confusion and errors when this payment line was sent to a terminal. This is fixed by waiting for the discount to be applied before being able to click on payment. Community PR: https://github.com/odoo/odoo/pull/221020 Forward-Port-Of: odoo/enterprise#93809 Forward-Port-Of: odoo/enterprise#91256
The point of sale flow now waits for a discount to finish applying before allowing payment to continue. This helps prevent incorrect payment amounts being sent to terminals, reducing cashier confusion and transaction errors.
Original PR description
pos*: point_of_sale, pos_restaurant Before this commit, if a discount was applied with the blackbox, it was applied after communication with blackbox which could be slow. If the user was clicking payment before this disound was applied and had only one payment method, a payment line with the old amount was added which could lead to confusion and errors when this payment line was sent to a terminal. This is fixed by waiting for the discount to be applied before being able to click on payment. Enterprise PR: https://github.com/odoo/enterprise/pull/91256 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#225358 Forward-Port-Of: odoo/odoo#221020
17 changes
Resolved issues and error corrections
Customers can now choose in-store pickup for products that are out of stock when the product is configured to keep selling anyway. This prevents valid checkout options from being blocked and keeps pickup behavior aligned with store inventory settings.
Original PR description
Versions -------- - 18.0+ Steps ----- 1. Publish the "Pickup in store" delivery method; 2. have an out-of-stock product with "Continue selling" enabled; 3. go to the product's shop page; 4. add to cart; 5. try to check out using "Pickup in store" delivery method. Issue ----- Delivery method cannot be selected. Cause ----- The `website_sale_collect` module currently only checks whether the product is in stock, and not whether the product is allowed to sell when it's out of stock. Solution -------- Check the `allow_out_of_stock_order` in `_get_unavailable_order_lines` and `format_product_stock_values`, so that the `in_stock` value used to check availability is `True` iff the products are in stock or have `allow_out_of_stock_order` enabled. opw-5080295
The point of sale preparation display now shows free-text details entered on order line attributes. This helps kitchen or preparation staff see customer-specific instructions directly on the order line, reducing missed customizations.
Original PR description
draft to be updated
Customers and site editors can now press Enter while choosing or editing a product size on the shop page without triggering an error. This prevents an unexpected checkout browsing interruption and makes product option selection more reliable.
Original PR description
Before this commit: Pressing the Enter key while selecting a product size option on the /shop page crashed. After this commit: This fix ensures the Enter key is properly handled and prevents unexpected crashes during product option selection. task-4795501
Spanish Facturae electronic invoices now preserve the correct number of decimals for product unit prices instead of rounding only to the currency precision. This prevents rounding differences and incomplete or incorrect invoice XML values when products use more detailed pricing.
Original PR description
It is possible for a product to have more decimals than the currency, but the facturae always rounded according to the currency. This would sometimes lead to both rounding errors and incomplete or incorrect values on the generated XML. This commit rounds product prices according to the unit price decimal while leaving the other computed field untouched as to not disturb the correct computation elsewhere. As this file was changed in 18.0 another PR was needed: https://github.com/odoo/odoo/pull/209623 task-4650439
Product image galleries now keep the selected thumbnail centered when shoppers zoom and browse through many images. This prevents thumbnails from being cut off at the screen edge and adds smoother mobile swiping, making product browsing easier.
Original PR description
Versions -------- - 18.0+ Steps ----- 1. Add a bunch of extra images to a published product; 2. enable zoom-on-click via editor; 3. click on an image to zoom it; 4. scroll through images. Issue ----- With too many images added, the thumbnails on the bottom are cut off on the edges of the screen, making it impossible to click on them. Cause ----- The thumbnail row element doesn't get updated when selecting a new image. Solution -------- Define a `_updateCarousel` method which adds a `transform: translate` operation to the thumbnails, moving them such that the currently selected image's thumbnail gets centered on the screen. Call this method on mounting, and again on any render (image change). Bonus: add `touchstart` & `touchmove` hooks to enable easy swiping through the carousel on mobile. opw-4937009 opw-4908881
This fix prevents small rounding differences from building up during inventory revaluation calculations. It helps avoid incorrect negative valuation amounts, improving the reliability of stock accounting figures.
Original PR description
Before this commit, the remaining_value_unit_cost was rounded before any computation. In the case where the numer of layers with remaining value and remaining quantity increase, the rounding error introduced by that rounding quickly explodes, leading to a negative remaining_value during revaluation computation. After this commit, the remaining value is rounded at the end, after the computations and the checks. This ensures that the rounding error remains constant and does not accumulate over the execution of the method. opw-4901966 Forward-Port-Of: odoo/odoo#222690
Uploaded file fields on Field Service worksheets are now shown when customers or users open the worksheet report for signing. This prevents missing attachment information during the signing process and keeps worksheet records complete and visible.
Original PR description
Steps to reproduce: ------- - Install industry_fsm_report module - Open FSM app - Select worksheets from settings in the configuration - Go to worksheet templates in the configuration - Create a worksheet template - Click the design template button. You arrive in the studio - Add file field and close it - Create a new task and select a newly created template in the worksheet template - Click the worksheet button in the control panel - Upload a file and save it - Click on the sign report button - Here file field is not visible Issue: ------- The file field is not visible in the worksheet portal. Cause: ------ The view of the file field is not created for the worksheet portal. Solution: ------- Created the view of the file field to display in the worksheet portal. task-3691529 Forward-Port-Of: odoo/enterprise#56035
Fixes an issue where editing budget amounts after changing report date ranges could trigger an error. Budget records are now matched consistently by month, preventing duplicate incomplete entries and keeping budget updates reliable.
Original PR description
Currently, an error occurs when user editing the budget report items. Steps to Reproduce [Video](https://drive.google.com/file/d/1bz0GEQjwxQrckzcEHdYPfvaA5M43lmFF/view): - Install the `Accounting`…
Currently, an error occurs when user editing the budget report items. Steps to Reproduce [Video](https://drive.google.com/file/d/1bz0GEQjwxQrckzcEHdYPfvaA5M43lmFF/view): - Install the `Accounting` module. - Go to `Profit and Loss` > `Budget` and `create a budget`. - Select `custom dates (e.g., start: 01/01/2025, end: 12/10/2025)` and change the amount of a budget line. - Change the `date range (e.g., start: 01/10/2025, end: 12/10/2025)` and change the amount again. - `Switch back to the first date range` (start: 01/01/2025, end: 12/10/2025) and try changing the amount once more. `TypeError: unsupported operand type(s) for +: 'float' and 'NoneType'` This error occurs when a user editing the budget report items. When user enters a date period, the system creates budget items for the first date of every month within that range. If the user then changes the date period to the next date of the same month, the system attempts to fetch the existing budget item `[1]` for that range. However, due to the start date alignment, it fails to fetch the correct budget item and instead creates an extra one `[2]`. Later, when the system checks again from the first date of the same month as the start date, it finds this extra budget item, for that the amount is None, which raises the error `[3]`. This commit ensures that when fetching existing items and generating the start month dates `[4]`, the system always uses the first day of the month as the `start date` so that the flow is maintained.. [1]- https://github.com/odoo/enterprise/blob/1df83837a2aec4801b34a9a7ab0cd68f640b4fd6/account_reports/models/budget.py#L44-L49 [2]- https://github.com/odoo/enterprise/blob/1df83837a2aec4801b34a9a7ab0cd68f640b4fd6/account_reports/models/budget.py#L75-L79 [3]- https://github.com/odoo/enterprise/blob/1df83837a2aec4801b34a9a7ab0cd68f640b4fd6/account_reports/models/budget.py#L72 [4]- https://github.com/odoo/enterprise/blob/1df83837a2aec4801b34a9a7ab0cd68f640b4fd6/account_reports/models/budget.py#L58-L61 sentry-6883207225
Fixes several issues that could hide or break comments in Knowledge articles, including after reloading, switching between locked articles, or commenting near the top of a page. This helps users keep discussion context visible and avoids crashes when using comments around code blocks.
Original PR description
### Issue 1: Summary: When a user adds a comment inside a baseContainer element, the comment beacons created during the comment insertion can be discarded during the document normalization step. How…
### Issue 1: Summary: When a user adds a comment inside a baseContainer element, the comment beacons created during the comment insertion can be discarded during the document normalization step. How to reproduce: - Open an article in Knowledge. - Select text and change the block style from "Paragraph" to "Normal" using the powerbox. - Add a comment on the selected text using the powerbox. - Write a message in the comment thread. - Save and reload the article. Issue: - The comment beacons disappears from the editor and the user can't see it anymore. Resolution: When the editor is initialized, `div` are not yet categorized as paragraph related elements. The `comments_plugin` logic to identify valid positions for comments beacons should take that into account and allow elements which are candidates to be a paragraph related element. ### Issue 2: Summary: There was an issue where comments were not displayed when switching from a locked article to another (read-only). How to reproduce: - Create two articles and add a comment on each. - Lock both articles (so that they are effectively read-only). - Switch from one article to the other. Issue: - Comments are not displayed to the user. Resolution: When switching between read-only articles, `KnowledgeHtmlViewer` is not fully reloaded and continues using the same `CommentBeaconManager` instance for the newly opened article. As a result, comment beacons are not displayed when switching article. The simplest solution to this issue is to re-instantiate a new `CommentBeaconManager` whenever the HTML value changes to ensure comments are correctly displayed. ### Issue 3: There is an issue in the logic of `computeVerticalDimensions` to display comments. If the `top` value of a thread in the article is `0`, it will be filtered out and not displayed because `top` was used as a boolean value. Instead, it should properly consider `top` as a finite number to display the comment or not. Note: This issue is not easily reproducible because there are few configuration where a comment would have a top value equal to 0. ### Issue 4: There is a crash when inserting a knowledge comment in a `/code` block: In this previous [task], insertion in `pre` elements was filtered to prevent non-phrasing content from being inserted (as it is invalid per the html specification). To prevent a crash, knowledge comments will be disabled in `<pre>` elements, as they rely on `anchor` elements for the comment position in the article body. [task]: 216e9eb task-4984152
Corrects how discounts are rounded when creating Mexican global invoices, preventing rejected invoices caused by small rounding differences. This helps users successfully validate invoices with discounts that previously triggered CFDI total mismatch errors.
Original PR description
Steps to reproduce: ------------------- * Create an invoice with the following line: * Unit price: 47.25, Qty: 1, Taxes: 16%, Discount 50% * Confirm, create a global invoice > Observation: Error ```…
Steps to reproduce: ------------------- * Create an invoice with the following line: * Unit price: 47.25, Qty: 1, Taxes: 16%, Discount 50% * Confirm, create a global invoice > Observation: Error ``` Code : CFDI40108 Message : El TipoDeComprobante es I,E o N, el importe registrado en el campo no es igual al redondeo de la suma de los importes de los conceptos registrados. ``` Why the fix: ------------ The issue occurs because the `descuento` value, originally 23.625, is now being corrected to 23.615 which leads to `importe` having a value of 23.635 which round up to 23.64 and not 23.63. https://github.com/odoo/enterprise/blob/08564f3312c255f2f3ab95cef5a9bfc57727bd1f/l10n_mx_edi/models/l10n_mx_edi_document.py#L1111 https://github.com/odoo/enterprise/blob/08564f3312c255f2f3ab95cef5a9bfc57727bd1f/l10n_mx_edi/models/l10n_mx_edi_document.py#L1336 Before this commit https://github.com/odoo/enterprise/commit/39759babddc732a312ec5cd6a60a2f1819abc62c the discount value was being rounded when corrected. It would end up being evaluated to 23.62. To not bring back the issue the fixed by the mentioned commit we round the discount when generating the global invoice cfdi values. Now `importe` will have a value of 23.63 as `descuento` is rounded to 23.62. opw-5023597
This fix helps appointment bookings work correctly when a staff member has a flexible work schedule. It ensures the booking process is clearly identified internally, so related scheduling logic only applies when an appointment is actually being booked.
Original PR description
In the community branch, resource.calendar has a method, `_attendance_intervals_batch`, that can cause a bug if someone attempts to book an appointment with a staff member that has a flexible schedule. But it is used for many things besides booking appointments, and it works correctly for those other things. So, conditional logic was introduced there with a block you should only enter into if an appointment is currently being booked. To facilitate that, a flag signaling that an appointment is being booked, `booking_apt=True`, gets passed down through many of the methods that get called in the process of booking an appointment. Solves ticket 5094795
This change fixes a booking issue where appointments with staff on flexible hours could only be confirmed when the selected time happened to match a hard-coded midday window. Customers can now book valid appointment slots as expected while preserving the existing scheduling behavior used by other business processes.
Original PR description
calendar.resource has a method, `_attendance_interval_batch`, that can cause a bug if someone is trying to book an appointment with a staff with flexible hours.There's an elif block that you enter if…
calendar.resource has a method, `_attendance_interval_batch`, that can cause a bug if someone is trying to book an appointment with a staff with flexible hours.There's an elif block that you enter if the calendar.resource has flexible hours. In that block, we determine how much time is allocated for the appointment. For instance, 1 hour if the appointment is meant to be 1 hour long and the staff still has at least 1 hour left to work that week. Then, a work interval gets centered around 12 noon. 12 noon is hard-coded in. If there's one hour allocated for the appointment, that work interval will always be from 11:30 to 12:30, no matter what appointment time slot was selected. So, unless by lucky coincidence, the person selected an 11:30 appointment, they won't be able to schedule an appointment at all. The hard coding with 12 noon was implemented 4 months ago. It's meant to "solve issues in various apps such as work entry generation, attendance overtime calculation and time off calculations." Since the hard coding around 12 noon serves useful purposes, I didn't remove it. Instead, I added a flag `booking_apt=True` to signal that an appointment is currently being booking. And I added conditional logic so the work interval won't be centered around noon iff an appointment is being booked. I introduced the flag in the appointment.type method `is_appointment_slot_valid`. I originally tried introducing it in a function further up the call stack, but that lead to the flag being true when the current process was getting all possible appointment slots, and it broke that process. It seemed clear from `_is_appointment_slot_valid`'s title and docstring that its sole purpose is to check whether an appointment being booked is at a valid time. Solves ticket 5094795 Description of the issue/feature this PR addresses: It solves ticket 5094795. Current behavior before PR: If you try to book an appointment with a staff with a flexible schedule, and the appointment type's `work_hours_activate` field is true, you'll get a 404 page missing error. (See ticket.) Desired behavior after PR is merged: You will not get a 404 page missing error anymore, and will be able to successfully book an appointment. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix prevents Point of Sale orders from failing when branch users sell products assigned to a parent company with real-time inventory valuation enabled. It ensures staff can complete sales without access errors related to product cost currency information.
Original PR description
Before this commit, if a product was assigned to company A and a user from one of its branches tried to create an order with real-time inventory valuation enabled, the system would raise an access error when reading the product's cost_currency_id field. opw-4969390 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#223951
The stock receipt screen now prevents users from editing a lot field that cannot correctly save lot information for lot-tracked products. This avoids a confusing situation where a lot appears selected but validation still fails because the system has not actually assigned it to the stock movement.
Original PR description
### Steps to reproduce: - In the setting enable lots and serial numbers - Create a product tracked by LOT - Create and confirm a receipt for 1 unit of that product - Create a new lot: LOT001 from the…
### Steps to reproduce: - In the setting enable lots and serial numbers - Create a product tracked by LOT - Create and confirm a receipt for 1 unit of that product - Create a new lot: LOT001 from the move in the picking form - Click Validate #### > Invalid operation: you need to provide Lot/Serial numbers of the product ### Cause of the issue: The set method of the `lot_ids` field of the `stock.move` model does nothing for product tracked by lots: https://github.com/odoo/odoo/blob/7a8f9b7fe4dded4cfa140103d51b52e08149cadb/addons/stock/models/stock_move.py#L575-L579 In particular, while the lot appears on the move in the view, none of the move lines refer to it and the transfer can not be validated as indeed no lots are provided to these reservations. ### Fix: The feature of writing `lot_ids` for lots has been introduced in https://github.com/odoo/odoo/commit/4bb4e08066449177f89382718ceadd840ce90d0e https://github.com/odoo/odoo/blob/1c52e2e9e8e00a19e2db00bf70d658496f9a0f29/addons/stock/models/stock_move.py#L596-L600 But this major refactoring can of course not be backported in 18.0. Therefore, it was decided put the field in readonly when its set method is inefficient. opw-5093217 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Active payment providers can no longer have their linked payment journal cleared from the journal settings. This prevents payment failures caused by missing journal information when customers try to pay.
Original PR description
Versions -------- - 17.0+ Steps ----- 1. Have an active payment provider; 2. create a branch company; 3. set payment provider's company to branch; 4. leave Payment Journal unchanged (parent company Bank); 5. go to Accounting / Configuration / Accounting / Journals; 6. open Bank journal; 7. open "Incoming Payments" tab; 8. enable the "Payment Provider" column; 9. unset the payment provider on the active provider's line & save; 10. attempt paying using the provider. Issue ----- > Error: psycopg2.errors.NotNullViolation: > null value in column "journal_id" of relation "account_payment" violates not-null constraint Cause ----- We shouldn't be able to change the related journal of active providers. Solution -------- Make the field read-only if the payment method is active. opw-5045000 Forward-Port-Of: odoo/odoo#225187
Fixed an issue where the rental schedule could hide later rental orders when the same serialized item was rented again. Businesses can now see all relevant rental bookings accurately, improving planning and availability visibility.
Original PR description
**Current Behavior:** With rental transfers enabled, renting a product with a serial number multiple times will result in the rental schedule only showing one of multiple rental orders for that SN.…
**Current Behavior:** With rental transfers enabled, renting a product with a serial number multiple times will result in the rental schedule only showing one of multiple rental orders for that SN. **Expected Behavior:** All rentals for the same SN should appear in the rental schedule. **Steps to Reproduce:** - Go to Rental > Configuration > Settings and enable Rental Transfers - Create a new product that is storable, can be rented, and is tracked by unique serial number - Receive 25 of the product with assigned serial numbers - Create and confirm a rental order for 25 units of product - Validate both OUT and IN transfers - Duplicate the rental order and confirm it - Check Rental > Schedule -> Odoo says 25 total units across the original and duplicate orders, but they each have 25 **Cause of the Issue:** Previously, commit ed5fd2693fc fixed a bug where all serial numbers would display regardless of whether they were involved in a rental. This introduced this bug, where only the first stock move line with a distinct serial number would be shown in the rental schedule. **Fix:** Change the "SELECT DISTINCT ON" to "sml". We can get all distinct stock move lines as we can expect SNs to appear multiple times. opw-5003247 Forward-Port-Of: odoo/enterprise#95315
Point-of-sale orders in Spain that fail to upload to TicketBAI will now be retried automatically instead of blocking later submissions. This helps prevent silent reporting gaps and reduces manual intervention for failed fiscal uploads.
Original PR description
Currently if any PoS order uploads to TicketBAI fail, all future uploads will also silently fail since the chain head was never posted. Steps to reproduce ----- 1. Send a PoS order to TicketBAI have the upload fail 2. Validate another PoS order 3. The upload for the second order is never attempted Cause ----- The first order creates a `l10n_es_tbai_post_document_id` and chain index it is uploaded, but the document's state will remain rejected if the upload is unsuccessful. Any subsequent orders will fail the `_check_can_post()` check since the chain head is not accepted. Solution ----- Create a cron to automatically retry uploading the chain head if it's not posted, and retry any other uploads that were not sent. opw-4669823
4 changes
Resolved issues and error corrections
Intrastat reports now take the region from the warehouse when it is defined, instead of always falling back to the company setting. This helps ensure cross-border goods reporting reflects the correct regional information and avoids inaccurate report lines.
Original PR description
## Issue: The Intrastat report currently uses the company region from settings instead of the warehouse region even when the warehouse has a region defined. ## Cause: The original…
## Issue: The Intrastat report currently uses the company region from settings instead of the warehouse region even when the warehouse has a region defined. ## Cause: The original 'stock.intrastat.report.handler' model defines a `_name` and implements `_fill_missing_values()` to override the company region with the warehouse region. However, this model does not appear to be called directly in the report and, in this particular case, its `_fill_missing_values()` method is not executed. For aggregated header lines, `_fill_missing_values()` cannot restore the region even if it were called, because these lines do not contain `invoice_ids` or `move_ids`. Without such identifiers, the warehouse cannot be determined post-query, so the company region was always used. https://github.com/odoo/enterprise/blob/03d9353d85ed80c6e44fd231e5340d2378af8c81/stock_intrastat/models/account_intrastat_report.py#L11-L37 ## Fix: Introduce a new model that _inherits from 'account.intrastat.report.handler' without a _name. The _fill_missing_values() method is kept in the model to preserve potential future usage, but in this case, the query changes already ensure that the region in the report is correct. ## Steps to reproduce: Note: Belgium localization is used here because it provides pre-defined regions that are easy to modify in the Settings App. - Install l10n_be_intrastat + sale_management + stock - Select a Belgium Company - In Settings, set Company Intrastat Region to "1 Flemish region" - Create a Product (Commodity Code: 01012100..., Weight: 10, Country of Origin: Belgium) - Set Warehouse > Intrastat region to "3 Brussels region" - Create and confirm a Sale Order for a French Customer (Tax ID: FR23334175221, Country: France) - Create and confirm the invoice - Open Accounting > Reporting > Intrastat Report - Select the Report: Intrastat (Goods) and This Month as date - Before the fix, the Region is 1 and it's the same for the details lines opw-5011272
This fixes a display issue where online shop prices could show unnecessary decimals for currencies configured to round to whole amounts. Customers now see prices consistently across product pages and configurator flows, matching the website's currency precision.
Original PR description
Versions -------- - 17.0+ Steps ----- 1. Set currency rounding of EUR to 1.0; 2. use the currency on a website pricelist; 3. go to a product page in /shop; 4. open the url in a new session. Issue ----- From the editor, the price gets displayed as expected, with no decimals. In the new session, the price gets displayed with two decimals. Cause ----- The `_priceToStr` method used, always uses a `precision` of 2, except in editor mode when it will retrieve a different value from a hidden `.decimal_precision` element. Solution -------- Add the website's currency precision to `combination_info` via the controller, and use this value in `_priceToStr`. For the product configurator, store the currency precision in the `.js_price_total` element's dataset. Also insert the precision in the `.oe_price` element's dataset, allowing it to be used as a fallback in case the configurator template isn't up to date. opw-4996878
This fix prevents users from removing the journal linked to an active payment provider. It helps avoid payment failures caused by incomplete journal settings, especially in multi-company or branch-company setups.
Original PR description
Versions -------- - 17.0+ Steps ----- 1. Have an active payment provider; 2. create a branch company; 3. set payment provider's company to branch; 4. leave Payment Journal unchanged (parent company Bank); 5. go to Accounting / Configuration / Accounting / Journals; 6. open Bank journal; 7. open "Incoming Payments" tab; 8. enable the "Payment Provider" column; 9. unset the payment provider on the active provider's line & save; 10. attempt paying using the provider. Issue ----- > Error: psycopg2.errors.NotNullViolation: > null value in column "journal_id" of relation "account_payment" violates not-null constraint Cause ----- We shouldn't be able to change the related journal of active providers. Solution -------- Make the field read-only if the payment method is active. opw-5045000
Future time off balances now account for leave that employees have already taken when accrual limits are applied. This prevents overstated or incorrect projected balances on future dates, helping HR teams plan and communicate available leave more accurately.
Original PR description
Computing the future accrued days/hours would become incorrect when using a cap when total lifetime accrued allocation was higher than the cap. This caused issues when looking at how much accrued time an employee would have on a certain date where the accrued time would be correct on today, but become incorrect on any other future day. This was due to the fake allocation being used to compute the remaining time not considering the taken leaves, thus the cap was the maximum being considered across lifetime accrued time. opw-5059276