Daily updates from Odoo
Monday, October 6, 2025
164 changes
13 changes
Resolved issues and error corrections
Field service project settings now show the correct label for the timesheet product when a customer is selected. This prevents confusion caused by the sales order line label appearing in the wrong place.
Original PR description
Steps to reproduce: - Install the `industry_fsm_sale` module. - Open the FSM app. - Go to Projects. - Open a project’s settings. - Select a customer. Issue: The label for the timesheet product is not displayed. Instead, the label for the sale order line appears on FSM projects. Cause: In the PR, https://github.com/odoo/odoo/pull/128967 changed the project settings form structure by wrapping `sale_line_id` in a `div` and separating its label, breaking the xpath for `timesheet_product_id`. Fix: - Update the XPath for `timesheet_product_id` to target the correct container. - Hide the `sale_line_id` label on FSM projects. task-4581748 Forward-Port-Of: odoo/enterprise#96022
The payroll document generation process now skips payslips when the related employee contact is missing. This prevents scheduled PDF generation from failing and keeps payroll document processing running smoothly for other employees.
Original PR description
Currently an error occurs when the **'Payroll: Generate pdfs'** scheduled action runs and tries to create a document for a payslip belonging to an employee who does not have a related partner.…
Currently an error occurs when the **'Payroll: Generate pdfs'** scheduled action runs and tries to create a document for a payslip belonging to an employee who does not have a related partner. **Prerequisites:** - Ensure HR is enabled in `settings>Documents` **Steps to Reproduce:** 1) Install `documents_hr_payroll` module.(with Demo) 2) Navigate to the Employees App. 3) Select any Employee(e.g Abigail Peterson) and open form view. >- click on **contacts** smart button. >- Delete that Record 4) Create a confirmed Payslip for the selected Employee(e.g Abigail Peterson). 5) Activate Developer mode and navigate to schedule Actions. >- Search for 'Payroll: Generate pdfs'. >- Run Manually. Error: `NotNullViolation: null value in column 'partner_id' of relation 'documents_access' violates not-null constraint` Root Cause: When the partner is deleted, the value received from `_get_document_partner` at [1] is `False`, which later on tries to create the `documents.access` record for the new document, it fails because no partner is available to assign access rights, resulting in the error. Solution: This commit prevent Error by ensuring `_check_create_documents` method doesn't allow document creation without valid partner. [1]: https://github.com/odoo/enterprise/blob/99a8d83edb42f172d0dd35c91743fa0c9653dcbb/documents_hr_payroll/models/hr_payslip.py#L20C1-L21 sentry-6814524392 Forward-Port-Of: odoo/enterprise#96191 Forward-Port-Of: odoo/enterprise#92865
Exporting a Belgian 325 PDF without any 281.50 forms now shows a helpful message instead of a server error. This prevents user confusion and explains that a transaction with a 281.50 tag is needed before generating the PDF.
Original PR description
### Problem When clicking **"Export PDF"** on a 325 form that has **no generated 281.50 forms**, Odoo raised a **server error**: This happened because the method assumed that at least one attachment…
### Problem When clicking **"Export PDF"** on a 325 form that has **no generated 281.50 forms**, Odoo raised a **server error**: This happened because the method assumed that at least one attachment would always be generated, even if no eligible transactions were present. --- ### Steps to Reproduce 1. Go to **Accounting → Reporting → 325 Form**. 2. Create a 325 form for a year without any transactions on accounts tagged with **281.50**. 3. Do not generate any 281.50 forms (`form_281_50_ids` is empty). 4. Click **Export PDF**. **Result before fix:** - Crash with `IndexError: list index out of range`. --- ### Solution - Added a safeguard check before accessing attachments. - If no attachments exist, raise a **UserError** instead of crashing. **New behavior:** > *“No 281.50 lines found to generate a PDF. Please record a transaction with a 281.50 tag first.”* This gives users a instruction on how to resolve the issue. --- ### Result After Fix - **User error message** replaces traceback. - **Normal behavior preserved** when attachments exist: - One file → direct download. - Multiple files → zipped download. --- task-5090120 Forward-Port-Of: odoo/enterprise#94877
Fixes an issue where highlight effects in website page templates could be carried over incorrectly when creating a new page from a preview. This ensures selected templates render their highlights consistently, reducing visual glitches for website editors.
Original PR description
Starting from [1], the code from the "Snippets Preview" and the "New Page Templates Preview" was adapted to be able to build a highlight using its simplified format when provided in XML. The goal of this PR is to fix the new page DOM when a template with highlights is selected. The DOM will be simply cloned and used for the created page, so we need to reset the inner highlights to their minimal format. [1]: https://github.com/odoo/odoo/commit/4a29fa66003ce1f42a7011bc56fc019f34a887f5 task-4215788 Forward-Port-Of: odoo/odoo#185820
This fixes an issue in the website builder where showing the header or footer from the Invisible Elements panel did not reliably persist after saving. Business users can now manage page header and footer visibility more confidently without extra steps or unexpected changes.
Original PR description
With the initial [website builder refactor], clicking on the eye of the entry of the footer or the header in the "Invisible Elements" panel only temporarily changed their visibility. Additional clicks in the options were needed for their visibility to persist. This commit restores the previous behavior where clicking on the eye in the "Invisible Elements" panel for the header and the footer would also change the option. Steps to reproduce: - Open website builder - Click on the footer - Disable "Page Visibility" - Click on the eye next to "Footer" in the "Invisible Elements" panel - Save - Bug: the footer is invisible, but it was just before save [website builder refactor]: 9fe45e2b7ddbbfd0445ffe25a859e67a316d02b2 task-4367641
Fixed an issue where Belgian EC Sales List XML exports could omit the month when opened from the VAT Return page without manually selecting a period. The export now uses the company’s tax period settings so the XML includes the correct month or quarter, helping businesses submit complete compliance files.
Original PR description
**Issue** When accessing the EC Sales List report via the smart button from the VAT Return page, downloading the XML without explicitly selecting a period omits the <Month> element—even though a…
**Issue** When accessing the EC Sales List report via the smart button from the VAT Return page, downloading the XML without explicitly selecting a period omits the <Month> element—even though a month is visibly preselected. **Steps to Reproduce** 1. Install the Accounting module and Belgium localization. 2. Go to the Accounting dashboard. 3. Open the VAT Return via the "Miscellaneous Operations" section. 4. Click the smart button to access the EC Sales List report. 5. Use the gear icon to export the XML. 6. Observe that the XML <Period> section only includes the <Year>—the <Month> is missing. **Root Cause** If no period is explicitly selected, the report uses a period_type of "tax_period". However, this value was not handled when generating the XML, so the logic to include the \<Month> or \<Quarter> elements skipped it. As a result, only the \<Year>, which is always included, was rendered. **Fix** Extend the handling of tax_period to derive the period from the company’s tax periodicity settings and adjust the filter accordingly. This ensures that the generated XML always includes the \<Month> or \<Quarter> element, in addition to \<Year>, whenever the report is based on a tax period. Opw-4702613 Forward-Port-Of: odoo/enterprise#93647 Forward-Port-Of: odoo/enterprise#89290
This fixes an issue where the ChatGPT chat window could appear behind a modal window, preventing users from interacting with it. The change ensures the chat window displays in the correct layer when opened from a dialog, improving usability without changing the feature itself.
Original PR description
This PR fixes an issue with the chatgpt plugin where the chat window was rendered beneath the modal, making it unusable. The fix modifies the z-index of modal windows when the `openDialog` function of the chatgpt plugin is called. Forward-Port-Of: odoo/enterprise#94909
The website builder now clearly disables the remove button when a carousel has only one slide left. This prevents confusion by showing users that at least one carousel slide must remain.
Original PR description
Steps to reproduce: - Drop a carousel snippet - In the builder options, click on the "-" button to remove all items except the last one. => The button is still displayed as working (not disabled), even though clicking on it won't remove the last slide. To clarify that this is the expected behavior, we disable the button if there is only one carousel item left.
Deleting an invoice that had been sent by post now also removes the related snail mail letter record. This prevents the scheduled mail processing job from failing later on deleted invoice references, improving reliability for accounting and postal invoice workflows.
Original PR description
When an account move linked to a snailmail letter is deleted, the cron ``Snailmail: process letters queue`` crashes with a traceback. Steps to reproduce the error: - Create a new invoice > Confirm > Send > Select ``By post`` > Send - Reset to Draft > Delete the invoice - Run the cron ``Snailmail: process letters queue`` Traceback: ``` MissingError Record does not exist or has been deleted. (Record: account.move(1,), User: 1) ``` Solution: Ensure that when a move is deleted, its related Snailmail letters are also deleted. sentry-6883768061 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#227823
Accounting dashboard upload areas and drag-and-drop buttons now use theme-aware backgrounds instead of fixed grey colors. This improves visual consistency and readability, especially for users working in dark mode.
Original PR description
Current behavior before PR: - Drag & drop buttons and upload drop zones of dashboard cards had hardcoded backgrounds (#F2EDF0 / grey), which did not adapt to dark mode. Desired behavior after PR is merged: - Removed hardcoded background colors from drag & drop button and upload drop zone cards on dashboard and updated their background to adapt in light & dark modes. Changes implemented: - Removed hardcoded background color (`#F2EDF0`) from `account_drag_drop_btn` & `drag_to_card` CSS classes. - Removed overriding background-color property from `o_drop_area` CSS class. - Updated background-color of `o_drop_area` in `o_account_dashboard_kanban_view` CSS class to `o-view-background-color`. task-5092460 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#227707
Cancelled manufacturing work orders in backorder situations no longer receive an expected duration as if the work had been performed. This helps keep manufacturing time tracking and related cost calculations accurate when orders are partially completed and split.
Original PR description
### Issue: In this bug, the workorder duration being set to duration_expected is causing issues in backorder. To reproduce: 1- Create a Bill of Materials with at least two operations at two work…
### Issue: In this bug, the workorder duration being set to duration_expected is causing issues in backorder. To reproduce: 1- Create a Bill of Materials with at least two operations at two work centers 2- Create a manufacturing order and confirm it. 3- Complete the first operation and edit the quantity on the second operation so there is a backorder for the remaining quantity. 4- In the second work order, the first operation is cancelled, Finish the 2nd operation 5- As you can see, the cancelled operation duration is set to expected duration which is wrong. ### Cause: This issue is caused because of: https://github.com/odoo/odoo/blob/8f0e40286da7b144bfa17880a257406dd8585e57/addons/mrp/models/mrp_production.py#L1774-L1779 Which if work.order.state is `cancel`, the duration will set to `duration_expected`. This will eventually cause issue here: https://github.com/odoo/odoo/pull/222075/commits/8f0e40286da7b144bfa17880a257406dd8585e57#diff-fac872ffb03b811c4976eb2e52991ec544265332df814d92cfda658a5b917423L348 which is fixed by not making the state into `progres` if the state is `cancel`. But that doesn't fix the fact that the cancelled workorder has duration set and it might cause inconsistencies in manufacturing costs. related: #222075 opw-4931653 Forward-Port-Of: odoo/odoo#229975 Forward-Port-Of: odoo/odoo#229742
The Chilean electronic invoicing test now handles cases where optional demo data is not installed. This prevents unnecessary test failures and helps keep validation stable across different installation setups.
Original PR description
The test `test_demo_certificate_serial_number` failed when running without demo data, since the XMLID `l10n_cl_edi.l10n_cl_demo_certificate` is only present in demo mode. This commit updates the test to use `raise_if_not_found=False` and skip gracefully when the demo certificate is not available. The assertion now only runs if the certificate exists, ensuring the test passes consistently both with and without demo data. [RB-231573](https://runbot.odoo.com/odoo/error/231573) Forward-Port-Of: odoo/enterprise#95917
This update fixes an issue that could block users from validating backordered delivery orders in warehouses using a 2-step delivery process. It ensures stock reservations are adjusted correctly for newly created lines, reducing disruption in package and lot-tracked delivery workflows.
Original PR description
# Problem Unreserve issue preventing users from validating a delivery order with 2-step delivery warehouse configuration. Introduced in the following commit:…
# Problem Unreserve issue preventing users from validating a delivery order with 2-step delivery warehouse configuration. Introduced in the following commit: https://github.com/odoo/odoo/commit/13567aa27250f5798bbe42648eeac82241dbb780 # Steps to reproduce on the runbot: - Activate packages - Edit the warehouse to deliver in 2-steps - Create a product tracked by lot - Create two lots with 5 qty each - Create a sale order with 10 qty and confirm - Check the delivery order and assign: => 2 units to lot1 and create a pkg for it => 1 units to lot1 without pkg => 3 to lot2 without package - Validate the delivery and create a backorder - go to pick backorder and try to validate - Unreserve issue pops up - For further details, check: [#225948](https://github.com/odoo/odoo/issues/225948) # Solution: Conditional subtracting limited to new lines only. Task ID: opw-5086289 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#229994 Forward-Port-Of: odoo/odoo#229420
8 changes
Resolved issues and error corrections
Exporting a Belgian 325 form to PDF no longer results in a server crash when there are no 281.50 forms to include. Users now receive a clear message explaining that they need to record a transaction with a 281.50 tag before generating the PDF.
Original PR description
### Problem When clicking **"Export PDF"** on a 325 form that has **no generated 281.50 forms**, Odoo raised a **server error**: This happened because the method assumed that at least one attachment…
### Problem When clicking **"Export PDF"** on a 325 form that has **no generated 281.50 forms**, Odoo raised a **server error**: This happened because the method assumed that at least one attachment would always be generated, even if no eligible transactions were present. --- ### Steps to Reproduce 1. Go to **Accounting → Reporting → 325 Form**. 2. Create a 325 form for a year without any transactions on accounts tagged with **281.50**. 3. Do not generate any 281.50 forms (`form_281_50_ids` is empty). 4. Click **Export PDF**. **Result before fix:** - Crash with `IndexError: list index out of range`. --- ### Solution - Added a safeguard check before accessing attachments. - If no attachments exist, raise a **UserError** instead of crashing. **New behavior:** > *“No 281.50 lines found to generate a PDF. Please record a transaction with a 281.50 tag first.”* This gives users a instruction on how to resolve the issue. --- ### Result After Fix - **User error message** replaces traceback. - **Normal behavior preserved** when attachments exist: - One file → direct download. - Multiple files → zipped download. --- task-5090120 Forward-Port-Of: odoo/enterprise#94877
The Gantt view now correctly treats the Quarter scale as its own grouping instead of handling it like a month view. This makes project timelines easier to read by showing quarter groups with the expected month-level precision.
Original PR description
**Steps to reproduce:** - Install Project app - Go to Tasks - Go to gantt view - Select Quarter scale in the top left menu - Filtering shows 3 full quarters (9 months) as expected - Precision is set to days, with no grouping by quarter **Issue:** Quarter filtering is treated in the same way as the month filtering after some refactoring. Its scale was removed as well. **Fix:** Added 'quarter' to the possible timedelta and modified the range to use quarter specific scale. opw-4916133 related : https://github.com/odoo/enterprise/commit/067c2b43ec3329d1ef59e0e8f6030f0ec5e43829
This fix restores proper quarter-based grouping in Gantt timeline views, such as project task planning. Users viewing work by quarter will now see the correct time range instead of month-style grouping.
Original PR description
**Issue:** In the gantt views, quarter filtering is treated in the same way as the month filtering after some refactoring. Its scale was removed as well. When using `gantt_scale` to view project tasks, the time range was not displayed properly in the interface (no quarter grouping). **Fix:** Added 'quarter' to the possible timedelta to keep `delta = get_timedelta(1, scale)`. We could also add a simpler check for 'quarter' scale and cast it in month quantity, but it seems worse. opw-4916133 related : https://github.com/odoo/enterprise/commit/1abfc20baae80a3e7e250019b09a7070e831eeac related : https://github.com/odoo/enterprise/commit/067c2b43ec3329d1ef59e0e8f6030f0ec5e43829 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Contacts in the Dominican Republic can now use valid 11-digit Cédula tax identification numbers, in addition to existing 9-digit RNC numbers. This prevents valid customers or vendors from being incorrectly blocked during VAT validation.
Original PR description
**Issue** When inputting a VAT number with a length different from 9 digits, the check fails, even if the number is a valid Dominican RNC. **Steps to Reproduce** 1. Install Dominican localization and the VAT check module (base_vat), along with Contacts. 2. Go to Contacts, create a new contact for the Dominican Republic. 3. Insert "152-0000706-8" as the VAT. **Root Cause** The `check_vat_do` method only validated 9-digit RNC numbers via `stdnum.do.rnc.validate()`. 11-digit Cédula numbers are not supported. **Fix** - Updated `check_vat_do` to: * Validate 9-digit RNC numbers using `stdnum.do.rnc.validate()`. * Validate 11-digit Cédula numbers using `stdnum.luhn.validate()`. Opw-5004221 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#224507
This fix stops users from accidentally pasting text into parts of the website editor that are meant to be locked from editing. It helps preserve page structure and prevents unintended content changes while using the website builder.
Original PR description
When the selection is on text inside an element which is not `contenteditable` and is a inside the editable root, the user could paste text that would get inserted. This commit prevents that by ignoring `paste` events when selection is in a `contenteditable=false`. Steps to reproduce: - On `form/help-1`, open website builder - Select the text of "Help" title - Paste text - Bug: text is inserted task-5109671
The accounting dashboard’s drag-and-drop buttons and upload areas now automatically match the selected theme instead of using fixed colors. This improves readability and visual consistency, especially for users working in dark mode.
Original PR description
Current behavior before PR: - Drag & drop buttons and upload drop zones of dashboard cards had hardcoded backgrounds (#F2EDF0 / grey), which did not adapt to dark mode. Desired behavior after PR is merged: - Removed hardcoded background colors from drag & drop button and upload drop zone cards on dashboard and updated their background to adapt in light & dark modes. Changes implemented: - Removed hardcoded background color (`#F2EDF0`) from `account_drag_drop_btn` & `drag_to_card` CSS classes. - Removed overriding background-color property from `o_drop_area` CSS class. - Updated background-color of `o_drop_area` in `o_account_dashboard_kanban_view` CSS class to `o-view-background-color`. task-5092460 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#227707
Cancelled Gelato orders can now be processed without causing an error in Odoo. Instead of using a removed email template, the cancellation update is recorded directly in the sales order history so teams can still see what happened.
Original PR description
After an order is canceled on Gelato, we receveive a webhook with an `fulfillmentStatus` of `cancel` and while processing it, it crash with: ``` ValueError: External ID not found in the system: sale.mail_template_sale_cancellation ``` The mail template used to notify the status change has been removed in odoo/odoo@2c858ed15e50, so instead we simplify log the information on the sale order chatter. opw-5110226 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Deleting an invoice that had been queued for postal delivery now also removes the related postal mail record. This prevents the scheduled mail processing job from failing on missing invoice data and keeps the queue running reliably.
Original PR description
When an account move linked to a snailmail letter is deleted, the cron ``Snailmail: process letters queue`` crashes with a traceback. Steps to reproduce the error: - Create a new invoice > Confirm > Send > Select ``By post`` > Send - Reset to Draft > Delete the invoice - Run the cron ``Snailmail: process letters queue`` Traceback: ``` MissingError Record does not exist or has been deleted. (Record: account.move(1,), User: 1) ``` Solution: Ensure that when a move is deleted, its related Snailmail letters are also deleted. sentry-6883768061 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#227823
1 change
Resolved issues and error corrections
The Belgian EC Sales List XML export now correctly includes the month or quarter when opened from a VAT Return without manually changing the period. This prevents incomplete XML files and helps businesses submit Belgian tax reporting data as expected.
Original PR description
**Issue** When accessing the EC Sales List report via the smart button from the VAT Return page, downloading the XML without explicitly selecting a period omits the <Month> element—even though a…
**Issue** When accessing the EC Sales List report via the smart button from the VAT Return page, downloading the XML without explicitly selecting a period omits the <Month> element—even though a month is visibly preselected. **Steps to Reproduce** 1. Install the Accounting module and Belgium localization. 2. Go to the Accounting dashboard. 3. Open the VAT Return via the "Miscellaneous Operations" section. 4. Click the smart button to access the EC Sales List report. 5. Use the gear icon to export the XML. 6. Observe that the XML <Period> section only includes the <Year>—the <Month> is missing. **Root Cause** If no period is explicitly selected, the report uses a period_type of "tax_period". However, this value was not handled when generating the XML, so the logic to include the \<Month> or \<Quarter> elements skipped it. As a result, only the \<Year>, which is always included, was rendered. **Fix** Extend the handling of tax_period to derive the period from the company’s tax periodicity settings and adjust the filter accordingly. This ensures that the generated XML always includes the \<Month> or \<Quarter> element, in addition to \<Year>, whenever the report is based on a tax period. Opw-4702613 Forward-Port-Of: odoo/enterprise#89290
21 changes
Resolved issues and error corrections
Chilean electronic delivery guide XML now shows the quantity actually delivered instead of the quantity originally requested. This prevents overstated quantities when partial deliveries are validated without a backorder, improving document accuracy and compliance.
Original PR description
**Issue** When the delivered quantity of a product is less than the originally demanded quantity, the generated Delivery Guide XML shows the demand (product_uom_qty) instead of the actual delivered…
**Issue** When the delivered quantity of a product is less than the originally demanded quantity, the generated Delivery Guide XML shows the demand (product_uom_qty) instead of the actual delivered quantity (quantity). This results in an incorrect quantity being displayed in the DTE. **Steps to Reproduce** 1. Install the Accounting module, Chilean localization, Sales module, and l10n_cl_edi_stock. 2. Create and confirm a new Sale Order. 3. Click on the Delivery smart button. 4. Adjust the delivered quantity to a value lower than the demand, save, and validate with no backorder. 5. Generate the Delivery Guide. 6. Open the generated DTE XML and observe that the quantity is incorrect. **Root Cause** The quantity displayed in the DTE is taken from product_uom_qty, which represents the planned quantity to be moved, not the actual delivered quantity. The correct field to use is quantity, which reflects the real delivered amount. **Fix** Change the XML output to use quantity instead of product_uom_qty to accurately reflect the actual delivered quantity in the DTE. Opw-4892276 Forward-Port-Of: odoo/enterprise#93260 Forward-Port-Of: odoo/enterprise#89633
When a subcontracted purchase receipt quantity is reduced, Odoo now keeps one manufacturing order open as long as the receipt process is still active. This prevents the workflow from getting stuck and allows later receipt quantity updates to continue correctly.
Original PR description
Steps to reproduce: - Unarchive subcontracting operation type - Create a storable product P1 with a BoM: - BoM type: Subcontracting - Subcontractor: Azure Interior - Component C1 (route: Resupply…
Steps to reproduce:
- Unarchive subcontracting operation type
- Create a storable product P1 with a BoM:
- BoM type: Subcontracting
- Subcontractor: Azure Interior
- Component C1 (route: Resupply Subcontractor on Order)
- Create a purchase order:
- Vendor: Azure Interior
- 10 units of P1
- Confirm the PO → 2 pickings are created:
- Resupply of 10 units of C1
- Receipt of 10 units of P1
- Confirm and validate the resupply of C1
- Components are reserved in the subcontracting MO
- Validate the consumption of 10 units in the receipt
- The MO is updated to 10
- Update the quantity of P1 to 0 in the receipt
Issue:
The manufacturing order is cancelled. As a result, subsequent updates on the receipt cannot recreate MOs.
Fix:
When reducing the receipt quantity, cancel only the extra MOs, but always keep at least one open MO if a subcontracting move is still ongoing.
opw-4792379
Forward-Port-Of: odoo/odoo#225236
Forward-Port-Of: odoo/odoo#223858Customers who quickly use the browser back button after starting an express checkout payment can now try paying again without hitting an error. This prevents a failed checkout flow when the cart has already been converted into an order, improving reliability during payment retries.
Original PR description
This error occurs when trying to make a payment again from the cart. Steps to reproduce: --- - Install the **website_sale** module (with demo) - Activate **Demo** payment provider - Go to Website > Shop > Add a **Warranty** product to Cart > View cart - Pay with Demo > Pay - Click the back button(chrome navbar)(Instantly) - Now again Pay with Demo > Pay Traceback: --- `ValueError: Expected singleton: sale.order()` At [1], this error occurs because **order_sudo** is empty. This happens when there is no product in the cart — typically because, upon clicking **Pay**, a sale order is created for the product, and when the user navigates back, the cart is empty. [1]- https://github.com/odoo/odoo/blob/125fc3028debb311e9f6ad25d8c46699b77525f0/addons/website_sale/controllers/main.py#L1307-L1312 sentry-5682671428 Forward-Port-Of: odoo/odoo#229858
Partner ledger initial balances now include reconciled accounting lines that do not have a partner assigned. This prevents mismatches between opening balances and totals when reviewing reports across different financial periods.
Original PR description
### Issue: The partner ledger does consider lines without partners when calculating the initial balance. ### Steps to reproduce: - Create an invoice in 2025 - Create an entry in 2025 without partner…
### Issue: The partner ledger does consider lines without partners when calculating the initial balance. ### Steps to reproduce: - Create an invoice in 2025 - Create an entry in 2025 without partner for the same amount - Reconcile the two - Open the partner ledger for 2025, everything is correct - Change the dates to 2026, the amount of the initial balance ignores the entry but not the totals ### Cause: The method `_get_sums_without_partner` is called for the totals, but not for the initial balance. Its purpose is to add the amounts of the lines without partners that were reconciled with lines with a partner. ### Solution: Call `_get_sums_without_partner()` in `_get_initial_balance_values()` add the results before returning the initial balances. As this is the same logic as `_query_partners()` we create a new method. This method needs to be called with the dates of the initial balance in the options. So we create a duplicate of the options and input the new dates options. opw-5068790 Forward-Port-Of: odoo/enterprise#96125 Forward-Port-Of: odoo/enterprise#95881
Exporting a Belgian 325 PDF without any generated 281.50 forms now shows a clear user message instead of a server error. This helps users understand they need to record a transaction with a 281.50 tag before generating the PDF, while keeping normal PDF and ZIP exports unchanged when data exists.
Original PR description
### Problem When clicking **"Export PDF"** on a 325 form that has **no generated 281.50 forms**, Odoo raised a **server error**: This happened because the method assumed that at least one attachment…
### Problem When clicking **"Export PDF"** on a 325 form that has **no generated 281.50 forms**, Odoo raised a **server error**: This happened because the method assumed that at least one attachment would always be generated, even if no eligible transactions were present. --- ### Steps to Reproduce 1. Go to **Accounting → Reporting → 325 Form**. 2. Create a 325 form for a year without any transactions on accounts tagged with **281.50**. 3. Do not generate any 281.50 forms (`form_281_50_ids` is empty). 4. Click **Export PDF**. **Result before fix:** - Crash with `IndexError: list index out of range`. --- ### Solution - Added a safeguard check before accessing attachments. - If no attachments exist, raise a **UserError** instead of crashing. **New behavior:** > *“No 281.50 lines found to generate a PDF. Please record a transaction with a 281.50 tag first.”* This gives users a instruction on how to resolve the issue. --- ### Result After Fix - **User error message** replaces traceback. - **Normal behavior preserved** when attachments exist: - One file → direct download. - Multiple files → zipped download. --- task-5090120 Forward-Port-Of: odoo/enterprise#94877
This fix ensures the cohort view's tests reflect updated behavior when users change languages. It helps confirm that actions and breadcrumbs reload correctly, keeping navigation labels consistent with the selected language.
Original PR description
This commit adapts a cohort test w.r.t. the changes done in odoo/odoo#230046.
Fixes an issue where exporting the Belgian EC Sales List XML from the VAT Return page could omit the month or quarter when no period was manually selected. The export now uses the company’s tax period settings, helping ensure Belgian tax reporting files are complete and consistent.
Original PR description
**Issue** When accessing the EC Sales List report via the smart button from the VAT Return page, downloading the XML without explicitly selecting a period omits the <Month> element—even though a…
**Issue** When accessing the EC Sales List report via the smart button from the VAT Return page, downloading the XML without explicitly selecting a period omits the <Month> element—even though a month is visibly preselected. **Steps to Reproduce** 1. Install the Accounting module and Belgium localization. 2. Go to the Accounting dashboard. 3. Open the VAT Return via the "Miscellaneous Operations" section. 4. Click the smart button to access the EC Sales List report. 5. Use the gear icon to export the XML. 6. Observe that the XML <Period> section only includes the <Year>—the <Month> is missing. **Root Cause** If no period is explicitly selected, the report uses a period_type of "tax_period". However, this value was not handled when generating the XML, so the logic to include the \<Month> or \<Quarter> elements skipped it. As a result, only the \<Year>, which is always included, was rendered. **Fix** Extend the handling of tax_period to derive the period from the company’s tax periodicity settings and adjust the filter accordingly. This ensures that the generated XML always includes the \<Month> or \<Quarter> element, in addition to \<Year>, whenever the report is based on a tax period. Opw-4702613 Forward-Port-Of: odoo/enterprise#93647 Forward-Port-Of: odoo/enterprise#89290
The AI live chat website block now behaves more consistently with website themes and during page editing. The update improves readability, accessibility, layout, and fullscreen behavior, creating a smoother experience for visitors and website editors.
Original PR description
Resolve theme options compatibility, editing behavior, accessibility and design problems affecting UX and standards compliance. Adherence to theme options: - Apply border-radius correctly to target…
Resolve theme options compatibility, editing behavior, accessibility and design problems affecting UX and standards compliance. Adherence to theme options: - Apply border-radius correctly to target elements - Fix bg-color applying to text-area instead of intended container Edition: - Remove resize/style options on the column since these are not retained on save - Fix the preview that mismatch with actual rendered result - Resolve title/form misalignment in edit mode - Ensure "OR" text readability across different background colors - Preserve container size when the "fullscreen" feature is activated Accessibility: - Add missing focus state for form fields - Add role="presentation" to icons - Add role="button" to anchor tags functioning as buttons Design: - Reduce oversized title font size - Adjust container width on xl and xxl breakpoints - Smooth fullscreen transition to prevent abrupt activation | 19.0 | this PR | |--------|--------| | <img width="1092" height="424" alt="image" src="https://github.com/user-attachments/assets/5cd85204-b9af-4810-9458-c4c96dad562d" /> | <img width="1083" height="409" alt="image" src="https://github.com/user-attachments/assets/b83f2d18-0135-4f5d-b420-11f58070c8a3" /> | task-5089787
This fix prevents rare crashes when users quickly interact with website builder options that reload the editor, such as product page image layout settings. It improves the reliability of editing product pages and strengthens automated tests so the issue is caught consistently.
Original PR description
*: website_sale __Current behavior before commit:__ Some builder actions (e.g `ProductPageImageLayoutAction`) reload the editor after being applied. If another button in the builder is pressed…
*: website_sale __Current behavior before commit:__ Some builder actions (e.g `ProductPageImageLayoutAction`) reload the editor after being applied. If another button in the builder is pressed rapidly, `refreshCurrentItem` might be called after the editor is destroyed leading to the following error in [`isApplied`]: `TypeError: Cannot read properties of undefined (reading 'getAction')`. The "Product page options" test fails in rare occasion due to this issue. __Description of the fix:__ - Add a safety guard to make sure the editor is not destroyed before calling `refreshCurrentItem`. - Add some checks at the end of the test in order for the crash to appear consistently (if the fix is not applied). - Make the test more robust (some code is backported from [this commit]). [this commit]: https://github.com/odoo/odoo/commit/670b1daa2254d76 [`isApplied`]: https://github.com/odoo/odoo/blob/f258b263136f606f7896/addons/html_builder/static/src/core/utils.js#L939 Runbot error: https://runbot.odoo.com/odoo/runbot.build.error/232649 Forward-Port-Of: odoo/odoo#227739
SEPA Direct Debit payments are now found correctly during processing after an earlier system change affected how transactions are searched. This helps prevent payment processing failures for customers using SEPA Direct Debit.
Original PR description
After commit 772d8a6f2e66b13f352b56621912e33e7edcccc2,transaction search was changed to rely only on `provider_code`, instead of `custom_mode`. However, the `sepa_direct_debit` logic was not updated accordingly, resulting in transactions no longer being found. This commit adapts the code to the new search logic by using `provider_code` for transaction lookup.
This fixes a display issue where the ChatGPT plugin chat window could appear behind a modal window, making it unusable. The chat dialog now appears in front as expected, so users can continue interacting with it without interruption.
Original PR description
This PR fixes an issue with the chatgpt plugin where the chat window was rendered beneath the modal, making it unusable. The fix modifies the z-index of modal windows when the `openDialog` function of the chatgpt plugin is called. Forward-Port-Of: odoo/enterprise#94909
This fix ensures highlighted text effects appear correctly when users preview and create new website pages from templates. It prevents preview-only highlight markup from being copied into the final page, helping published pages keep the intended visual design.
Original PR description
Starting from [1], the code from the "Snippets Preview" and the "New Page Templates Preview" was adapted to be able to build a highlight using its simplified format when provided in XML. The goal of this PR is to fix the new page DOM when a template with highlights is selected. The DOM will be simply cloned and used for the created page, so we need to reset the inner highlights to their minimal format. [1]: https://github.com/odoo/odoo/commit/4a29fa66003ce1f42a7011bc56fc019f34a887f5 task-4215788 Forward-Port-Of: odoo/odoo#185820
This change ensures the web tour testing tools are loaded automatically when unit tests run. It reduces test setup complexity and helps prevent avoidable test failures, with no expected impact on regular users.
Original PR description
In this commit, we add the appropriate bundles in assets_unit_test. These bundles will only be loaded if we run unit tests (i.e. in debug mode). As a result, we no longer need to run preloadbundle in unit tests. Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Cancelled manufacturing work orders in backorder flows no longer receive an expected duration as if work had been performed. This prevents inflated or inconsistent manufacturing cost calculations when production is split into backorders.
Original PR description
### Issue: In this bug, the workorder duration being set to duration_expected is causing issues in backorder. To reproduce: 1- Create a Bill of Materials with at least two operations at two work…
### Issue: In this bug, the workorder duration being set to duration_expected is causing issues in backorder. To reproduce: 1- Create a Bill of Materials with at least two operations at two work centers 2- Create a manufacturing order and confirm it. 3- Complete the first operation and edit the quantity on the second operation so there is a backorder for the remaining quantity. 4- In the second work order, the first operation is cancelled, Finish the 2nd operation 5- As you can see, the cancelled operation duration is set to expected duration which is wrong. ### Cause: This issue is caused because of: https://github.com/odoo/odoo/blob/8f0e40286da7b144bfa17880a257406dd8585e57/addons/mrp/models/mrp_production.py#L1774-L1779 Which if work.order.state is `cancel`, the duration will set to `duration_expected`. This will eventually cause issue here: https://github.com/odoo/odoo/pull/222075/commits/8f0e40286da7b144bfa17880a257406dd8585e57#diff-fac872ffb03b811c4976eb2e52991ec544265332df814d92cfda658a5b917423L348 which is fixed by not making the state into `progres` if the state is `cancel`. But that doesn't fix the fact that the cancelled workorder has duration set and it might cause inconsistencies in manufacturing costs. related: #222075 opw-4931653 Forward-Port-Of: odoo/odoo#229975 Forward-Port-Of: odoo/odoo#229742
Changing the interface language now refreshes saved navigation state so breadcrumbs and restored pages appear in the new language. This prevents users from seeing outdated translated labels after reloading, creating a more consistent multilingual experience.
Original PR description
Before this commit, when changing lang, the breacrumbs was still displayed in the former language after the reload (and it persisted even if the user reloaded again). This was due to the fact that we store in the session storage the current action and state, so we can restore it and avoid some rpcs at reload. This commit fixes the issue by detecting the lang change and clearing the session storage in that case. closes #230032 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The base module test for translation export was simplified so it no longer starts a full Odoo instance. This makes automated checks faster and more dependable, reducing false failures in the development pipeline.
Original PR description
Spawning an Odoo instance goes beyond testing the i18n command. We just need to see if given the right command, something gets actually exported. So, we got rid of all complexity, and just avoided subprocessing, wiring directly to the command itself, in the current process. This removes timeout problems and a lot of undeterminism. [link](https://runbot.odoo.com/odoo/error/227540) runbot-227540 Forward-Port-Of: odoo/odoo#229755
The reception report now keeps existing warehouse stock reservations intact when users unassign and reassign incoming items to an order. This prevents sales deliveries from showing missing availability even when stock is actually present.
Original PR description
### Issue: #### Steps to reproduce: 1- Activate routes & locations and enable Reception Report 2- Enable Show reception report at validation from operation type: receipts 3- Create a product with…
### Issue: #### Steps to reproduce: 1- Activate routes & locations and enable Reception Report 2- Enable Show reception report at validation from operation type: receipts 3- Create a product with vendor. Put 2 unit on `WH/Stock/Shelf1` 4- Create a Sales Order for 3 units. 5- Create a PO for 1 unit and validate/receive. 6- On the Reception Report, click Assign to link incoming to sales pick 7- Open the sales pick in a new tab, observe there are 2 moves which first one is 1 and 2nd one is 2 8- On the reception report, click Unassign, then Assign again Back on the Pick, only 1 move (the one with quantity of 2) is reserved; checking availability reserves nothing although stock exists. #### Cause: When unassigning from the Reception Report, the system incorrectly unreserves stock that was already in `Shelf1` instead of unreserving the incoming move which the location_id is `WH/Stock`: User clicks Unassign on the Reception Report. `report_stock_reception.action_unassign()` is invoked. That calls `stock_move._do_unreserve()`. `_do_unreserve()` unpicks quants referenced by the `move.move_line_ids`. At this moment one of the `move_line_ids` points to `WH/Stock/Shelf1`, so `_do_unreserve()` removes the reservation from that `shelf1` quant. Consequence: `shelf1` stock(which should have remained reserved) becomes free. The receipt quant at `WH/Stock` remains reserved/ unavailable. When the user clicks Assign again, the system cannot reserve because it is alreade reserved by another move and therefore it is unavailable. #### Root cause: Now we look earlier in the flow to see why the move had a move_line pointing to `WH/Stock/Shelf1` in the first place. Earlier, in `report_stock_reception.action_assign` in the first assign: We create a new move from current outgoing move: https://github.com/odoo/odoo/blob/35ea3dcb2eeb379c8b1127f0c7b42191853c0bd2/addons/stock/report/report_stock_reception.py#L224-L231 And we link current move_lines to the new move: https://github.com/odoo/odoo/blob/35ea3dcb2eeb379c8b1127f0c7b42191853c0bd2/addons/stock/report/report_stock_reception.py#L245-L259 new_out.move_line_ids now contains move lines for multiple source locations, here in our case `[WH/Stock/Shelf1, WH/Stock]` The loop in above code does not check `move_line_id.location_id` when selecting lines. The first matching line in the iteration can be the `shelf1` one, so the code links the `shelf1` move_line to out instead of the `WH/Stock` move_line, which is a mismatch and causes the out move having different location with its move_line, which later will going to cause problem is unassign as explained. ### Fix: We can sort move_line_ids in a way that which line have the same location as potential ins' dest locations come first as better candidates: ```diff - for move_line_id in new_out.move_line_ids: + matching_locations = potential_ins.location_dest_id + for move_line_id in new_out.move_line_ids.sorted(lambda ml: ml.location_id not in matching_locations): ``` opw-4944047 Forward-Port-Of: odoo/odoo#229954 Forward-Port-Of: odoo/odoo#226120
When an invoice sent by post is deleted, its related Snailmail letter is now removed too. This prevents the scheduled letter-processing task from crashing on missing invoice records, keeping postal invoice handling reliable.
Original PR description
When an account move linked to a snailmail letter is deleted, the cron ``Snailmail: process letters queue`` crashes with a traceback. Steps to reproduce the error: - Create a new invoice > Confirm > Send > Select ``By post`` > Send - Reset to Draft > Delete the invoice - Run the cron ``Snailmail: process letters queue`` Traceback: ``` MissingError Record does not exist or has been deleted. (Record: account.move(1,), User: 1) ``` Solution: Ensure that when a move is deleted, its related Snailmail letters are also deleted. sentry-6883768061 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#227823
Safari users editing WebP images will no longer see a quality slider that cannot actually change the image. The editor now disables that option when the browser does not support WebP compression and shows a clear message, reducing confusion during website content editing.
Original PR description
Scenario: - select a WebP image in the editor with safari - change the quality with the slider Result: - the size and the image quality don't change Cause: Safari doesn't support HTMLCanvasElement.toDataURL() with WebP, so the image is exported in PNG instead which is lossless and doesn't support compression. Fix: Disable the quality for WebP images if this is not supported (in safari + iOS webview) and display a message. opw-4979378 closes odoo/odoo#224342 X-original-commit: ecc89796f7344d49359b6c378676628d0de2bb80
A Chilean electronic invoicing test now safely skips a demo-only certificate check when demo data is not installed. This prevents avoidable test failures and helps keep validation runs consistent across different setups.
Original PR description
The test `test_demo_certificate_serial_number` failed when running without demo data, since the XMLID `l10n_cl_edi.l10n_cl_demo_certificate` is only present in demo mode. This commit updates the test to use `raise_if_not_found=False` and skip gracefully when the demo certificate is not available. The assertion now only runs if the certificate exists, ensuring the test passes consistently both with and without demo data. [RB-231573](https://runbot.odoo.com/odoo/error/231573) Forward-Port-Of: odoo/enterprise#95917
The analytic distribution widget now filters analytic accounts by the document's company. This prevents users from seeing or choosing accounts from other companies, supporting proper multi-company data separation.
Original PR description
**Description of the issue/feature this PR addresses:** When creating or editing an analytic distribution, the analytic account selection does not respect the company context. This allows users to…
**Description of the issue/feature this PR addresses:** When creating or editing an analytic distribution, the analytic account selection does not respect the company context. This allows users to see and select analytic accounts from other companies, which violates the multi-company record rules. <img width="669" height="333" alt="2025-09-08_09-28" src="https://github.com/user-attachments/assets/488eb4b1-fdfa-49ca-a57e-8f46a264107d" /> **Current behavior before PR:** The analytic account dropdown in the analytic distribution widget shows analytic accounts from all companies, instead of being restricted to the current company. **Desired behavior after PR is merged:** The analytic account selection in the analytic distribution widget is filtered by company. Only analytic accounts belonging to the document company will be displayed, ensuring compliance with multi-company record rules. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#228935 Forward-Port-Of: odoo/odoo#225835
18 changes
Resolved issues and error corrections
This fixes an issue where Point of Sale pricelists with start and end times on the same date were not applied correctly. Businesses can now rely on time-limited pricing, such as daily promotions or happy-hour pricing, to show the correct price in POS after refreshing when the time window changes.
Original PR description
Pricelist that have a start and end datetime that are the same day but with different hours were not correctly applied in the POS. Steps to reproduce: ------------------- * Create a pricelist with a start datetime of 2025-01-01 08:00:00 and an end datetime of 2025-01-01 18:00:00. * Create a product and assign it to the pricelist with a fixed price. * Add the pricelist to the PoS config. * Open a session and select the pricelist. * Add the product to the order > Observation: The price is not correctly applied. Note: ----------- To update the pricelist when the datetime has been crossed the user will need to refresh the PoS. opw-4934183
This fixes a checkout issue where Google address suggestions could fail or miss key address details because Google does not always list address types in the same order. The update selects recognized address information more reliably and adds support for postal towns used in some countries, improving address completion for online shoppers.
Original PR description
Versions -------- - 18.0+ Steps ----- 1. Enable Google address autocomplete; 2. go eCommerce checkout; 3. add an address during the delivery step; 4. autocomplete a bunch of addresses. > [!Note] > I…
Versions -------- - 18.0+ Steps ----- 1. Enable Google address autocomplete; 2. go eCommerce checkout; 3. add an address during the delivery step; 4. autocomplete a bunch of addresses. > [!Note] > I haven't been able to reproduce it myself, but others have. > It appears that the order Google provides place types isn't always the same. Issue ----- You may get a `KeyError`, trying to fetch `standard_data['country']`. Cause ----- The fields get sorted by type, and we try to sort `country` before `state`, so that the `country` key should be present when we get to `state`. The likely issue is that Google often provides multiple types per field, and we only keep the first one, assuming it to be the most relevant one, but the API documentation makes no guarantees about the array's order[^1]. For example, if a field were to have `political` in front of `country`, we would keep the `political` type, only to ignore it later on, as we have no mapping for it. [^1]: https://developers.google.com/maps/documentation/places/web-service/place-types#address-types Solution -------- 1. Iterate over the types, and get the first one that's part of `FIELDS_MAPPING` 2. Before searching for a `state`, ensure `country` has already been set, otherwise log a warning. 3. Extra: add `postal_town` as a type, which gets used instead of `locality` in some countries like Sweden. opw-4880651
The HTML editor now selects a table cell only when all of that cell's content is actually selected. This prevents accidental full-cell selection while users are dragging from text inside a table, making editing tables more predictable.
Original PR description
Current behavior before PR: - Create an m x n table. - Write some text in a cell. - Put cursor at the end of text. - Try to select cell by moving mouse rightwards. Notice that the cell is selected although the cell content is not fully selected. Desired behavior after PR: This PR backports commit [1] to ensure that single cell is selected only if the cell content is fully selected. [1]: https://github.com/odoo/odoo/commit/09d369e118f622f30149f46702f58c656a3cee04 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes a PDF formatting issue where worksheet row heights and alternating row styling were not applied in Field Service Reports. Reports should now be easier to read and more consistent when printed, including for worksheets created before the fix.
Original PR description
**Steps to reproduce:**
- Install `industry_fsm_report`
- Create a task and add a worksheet
- Print the Field Service Report
**Issue:**
The worksheet row height is not applied in the PDF
**Cause:**
The `bg-light` class does not work in wkhtmltopdf
**Fix:**
Added SCSS to set the background color and border for odd rows in the worksheet PDF
**Technical:**
**Why we didn’t add the style via Python:**
Worksheets created before this commit already have the old class applied, so adding the style through Python would not affect them.That’s why the fix done using SCSS.Gantt view group headers now keep the right size so they remain visible and aligned while users scroll. This prevents layout issues, especially on mobile screens where headers can otherwise become wider than the display.
Original PR description
Gantt group headers could stop being sticky because their width was fixed based on the number and size of columns. Even though they were set to position: sticky, oversized headers could no longer remain aligned when scrolling, as they extended beyond the viewport and were constrained by the document width. This was especially noticeable on mobile, where group headers are often wider than the screen. The fix applies a max-width style to these headers, capping their size to the available space so they remain sticky without overflowing the document. task-4970992
Payments using SEPA direct debit mandates now correctly verify whether a mandate is still valid. This prevents valid future-expiring mandates from being rejected due to an incorrect date comparison.
Original PR description
The check to ensure that the mandate used in a token payment is still valid had two issues: - It was comparing a date (the mandate's end date) with a datetime. - It was incorrectly rejecting mandates expiring in the future, while it should have done the opposite. Forward-Port-Of: odoo/enterprise#96143
This fix makes HR-related modules check whether certain menus still exist before trying to use them. It prevents upgrade or testing failures in databases where those menus were deleted, improving reliability without changing normal user workflows.
Original PR description
To Reproduce: 1) make a database in 16.0 and go to developer mode. 2) Delete the menus 3) I mocked the views with upgrade mockcrawler. it failed for these xmlids: ``` hr_attendance.menu_hr_attendance_attendances_overview hr_timesheet.timesheet_menu_activity_use hr.menu_hr_employee ``` but we should have a check anyways. Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#219926 Forward-Port-Of: odoo/odoo#215426
Contacts in the Dominican Republic can now use valid 11-digit Cédula tax numbers without being rejected. This fixes VAT validation so both standard business RNC numbers and personal Cédula numbers are accepted where appropriate.
Original PR description
**Issue** When inputting a VAT number with a length different from 9 digits, the check fails, even if the number is a valid Dominican RNC. **Steps to Reproduce** 1. Install Dominican localization and the VAT check module (base_vat), along with Contacts. 2. Go to Contacts, create a new contact for the Dominican Republic. 3. Insert "152-0000706-8" as the VAT. **Root Cause** The `check_vat_do` method only validated 9-digit RNC numbers via `stdnum.do.rnc.validate()`. 11-digit Cédula numbers are not supported. **Fix** - Updated `check_vat_do` to: * Validate 9-digit RNC numbers using `stdnum.do.rnc.validate()`. * Validate 11-digit Cédula numbers using `stdnum.luhn.validate()`. Opw-5004221 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#224507
Manufacturing orders for finished products now correctly include the operations defined on a selected kit variant. This prevents missing production steps when a kit component has variant-specific work instructions, helping teams follow the right process on the shop floor.
Original PR description
### Steps to reproduct: - Create 2 products: Final Product (FP), Kit Product (KP) - On KP add a Color attribute with 2 values: Blue, Red - Create a KIT bom for KP wtih 2 operations: - OP: paint it…
### Steps to reproduct:
- Create 2 products: Final Product (FP), Kit Product (KP)
- On KP add a Color attribute with 2 values: Blue, Red
- Create a KIT bom for KP wtih 2 operations:
- OP: paint it Blue, apply on Color: Blue
- OP: paint it Red, apply on Color: Red
- Create a bom for FP with only one component line:
- 1 x Red Kit Product
- Create a MO for 1 unit of FP
#### > The operation was not created using the kit bom
### Cause of the issue:
Even if the bom exploded to find the operations to add on the MO: https://github.com/odoo/odoo/blob/2dfcbe53c80d2d8fe5b6d9828eea90a1d214c2e4/addons/mrp/models/mrp_production.py#L579-L599 The `_skip_operation_line`:
https://github.com/odoo/odoo/blob/2dfcbe53c80d2d8fe5b6d9828eea90a1d214c2e4/addons/mrp/models/mrp_routing.py#L164-L174 is checking if the product of the main bom has the attributes of the operation rather than the kit product used as component.
opw-5080856
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#228032Spanish point-of-sale orders now keep the cashier’s selected tax setup when an order is validated. This prevents incorrect tax amounts from appearing as change on receipts when the default tax position was intentionally changed.
Original PR description
Currently, when you use a default fiscal position in the pos, if you switch to no fiscal position, upon order validation the tax amount is counted as change. Steps to reproduce: ------------------- *…
Currently, when you use a default fiscal position in the pos, if you switch to no fiscal position, upon order validation the tax amount is counted as change. Steps to reproduce: ------------------- * Install l10n_es_pos, switch to es company * In the config of a shop, use fiscal position, set some as available, one as default * Open shop session * Add a product that has taxes * Switch fiscal position to one that has 0% taxes * There should not be taxes in the cart at this point * Go to pay the order (cash or bank) > Observation: On the receipt the previous tax value is counted as change Why the fix: ------------ The issue happens because of the simplified invoice mechanism present in the ES localization. When you validate an order and that order can apply for simplified invoice, if there is no customer on the order the partner is set with the simplified partner. When setting a partner on the order we update the fiscal position and pricelist. https://github.com/odoo/odoo/blob/1358f93a4c73de5a28cda72ec78769625c863efd/addons/point_of_sale/static/src/app/models/pos_order.js#L929 The fiscal position is updated with the partner's fiscal position or the default one if none on the partner. https://github.com/odoo/odoo/blob/1358f93a4c73de5a28cda72ec78769625c863efd/addons/point_of_sale/static/src/app/models/pos_order.js#L986-L995 Instead of the fallback on the default fiscal position in the case it is not set on a partner we fallback on the order current fiscal position. If it is different than the default one is means that it was changed intentionally and there's a high chance we want to keep it, otherwise it will already be the default fp. opw-5051231
Early payment discount loss lines are now correctly created for each partner when reconciling batch payments. This prevents discounts from being grouped under only one partner, improving the accuracy of accounting entries.
Original PR description
Steps: - create two invoices with a different partner (epd + no tax on the lines) - register for each a payment (payment method with no outstanding account) - select the two payments and create a batch - create a transaction with an amount equal to two payments (discounted amount) - reconcile it with the batch payment Issue There is only one epd discount loss line for one partner Cause: in https://github.com/odoo/odoo/blob/ecb4de3fea463d6524bb2aab8d2388c679dc2ed7/addons/account/models/account_move.py#L4638 The two lines share a common grouping dict key with the same `account_id`. `setdefault` returns the value if the key is existing. opw-5057109
Belgian EC sales reports now handle VAT numbers even when users entered them without the BE country prefix. This prevents incorrect trimming of the VAT number and helps produce accurate Belgian reporting data.
Original PR description
It could happen that the user set his vat number without the country code before the number. In this case, we removed the two first digits of the vat number. Also changing other occurrence using the company_vat to get the country, since we are in the belgian ec sale list, the country_code should be 'BE' everytime task-5039969
This update adds automated test coverage for a batch payment bank reconciliation issue linked to a prior fix. It helps reduce the risk of the same accounting workflow problem returning in future releases.
Original PR description
Add test for PR opw-5057109
Users who can print and send SEPA direct debit mandates can now also generate, send, and later access the related PDF attachments. This resolves a permission issue that blocked some authorized users from emailing mandate documents or viewing attachments they had created.
Original PR description
Removing the groups restriction from the `mandate_pdf_file` field in model `sdd.mandate` because it was causing issues when using the `sdd.mandate.send` wizard. Any user who has access to the `sdd.mandate` model can use this wizard to print and send the record. During this process, the system generates a PDF and stores it in the `mandate_pdf_file` binary field, linking the resulting attachment to the record. The previous group restriction prevented users who were not part of the `account.group_account_readonly` group from sending the email with the attachment. Even if the email was somehow sent, those users still couldn’t access the attachments they themselves had generated and sent. With this change, any user who is allowed to send and print `sdd.mandate` records will also be able to generate and later access the corresponding attachments.
Fixes an issue where removing formatting from a colored table cell could trigger an error and interrupt editing. The editor now handles table-level colors correctly so users can clear formatting without the page becoming stuck.
Original PR description
Problem: When having a `table` with `color` and selecting a cell to remove format, we get a traceback: "Infinite Loop in removeAllColor()." Cause: The color is applied on `table`, but we only process `td` for color removal. As the color remains on `table`, each attempt to remove it keeps reapplying, leading to an infinite loop. Solution: When removing color, also remove it from the `table`. Then apply the color to all child `td`. This ensures `td` colors are later removed automatically if selected, avoiding the loop. Steps to reproduce: 1. Add a `color` property to a `table` and `td`. 2. Select the `td`. 3. Click "remove format" from the toolbar. 4. Observe traceback. opw-5112088 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Point of Sale loyalty orders now only earn points when they meet the program’s configured eligibility rules, such as minimum item quantities. This prevents customers from receiving unintended points or losing excessive points when redeeming rewards like free products.
Original PR description
Loyalty points were not being awarded correctly for some orders. The system granted points even when the minimum required quantity of items was not reached. In some cases, it also added negative…
Loyalty points were not being awarded correctly for some orders. The system granted points even when the minimum required quantity of items was not reached. In some cases, it also added negative loyalty points, which led to an excessive deduction for the customer —sometimes just for claiming a single free product. > Setup of the Loyalty Program (Discount & Loyalty): Program Type : Loyalty Card Rule : minimum 5 items => 10 Loyalty Points per $ Reward : Free product (Simple Pen) => in exchange of 5 Loyalty Points Steps to reproduce: ------------------- * Open the pos Shop * Select a customer with loyalty points * Add a Simple Pen * Click on * Reward > Free Product - Loyalty Program > Observation: Customer shouldn't 'win' points here New Total is mathematically correct but not logic Why the fix: ------------ We need to verify that the order is eligible to generate reward points based on the configured rules, before adding the won points. opw-4914774 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#221570
This fixes an unreliable automated test for bus notifications that could fail depending on how notifications were grouped. The change helps keep Odoo's quality checks stable and reduces false failures in development pipelines.
Original PR description
This commit fixes the `test_postcommit` that fails in a non deterministic fashion. This test ensures bus notifications created in the post commit hook result in only one batch. However, the listener only consider the first notification of the batch (`conn.notifies.pop()`) and ignore the rest. When the expected notifications come as part of a bigger batch, they can be ignored thus making the test fail. This commit ensures we read every notification received. fixes runbot-233185 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#230054
This fixes an intermittent failure in an automated test for signed document cleanup. It adds a small time buffer so test records are consistently old enough to be removed, improving reliability without changing user-facing behavior.
Original PR description
Steps to reproduce
==================
Launch the test `test_gc_clear_bin` a few times
It will eventually fail:
documents.document(544,) is not false :
trash document should be deleted after gc_clear_bin
Cause of the issue
==================
The domain for wether a record should be deleted contains `('write_date', '<=', fields.Datetime.now() - relativedelta(days=deletion_delay)`
The tests fails when the write_date is in the same second as the test run.
This is because fields.Datetime.now() replaces microseconds by 0.
https://github.com/odoo/odoo/blob/14073faf1fa272b8d3411b4fe6f42c279058459d/odoo/fields.py#L2378
Solution
========
Since records needs to be at least "deletion_delay" old, we add a margin of 30 seconds to make sure they match
runbot-2242073 changes
Resolved issues and error corrections
This update clears invalid saved device identifiers before sending UK tax report requests to HMRC. It helps prevent repeated submission failures caused by outdated or corrupted browser-stored values.
Original PR description
There are still Odoo requests that are sent to hmrc with invalid 'Gov-Client-Device-ID' header. They are showing this error: "Submit a UUID which is 128 bits or 32 hex characters long". A possible explanation, is that some users have some garbage value in the localStorage for 'hmrc_gov_client_device_id', that does not correspond to a uuid. This value would then be sent each time in the headers, and get rejected. The fix here is to clear the localStorage value if it is not a uuid. task-4627086
Delivery slip reports using the DIN 5008 layout now show ordered and delivered quantities in the correct column alignment. This makes printed or downloaded delivery documents easier to read and more professional for warehouse teams and customers.
Original PR description
**Steps to reproduce:** 1.Install Stock and l10n_din5008 modules. 2.Change the document layout to DIN 5008. 3.Create a Delivery/Picking with two stock moves: - First product without `Description for Delivery Orders` - Second product with `Description for Delivery Orders` 4.Download/Print the Delivery Slip. 5.Observe the quantity alignment in the report. **Issue:** - The Ordered and Delivered quantity columns are misaligned in the Delivery Slip report. **Solution:** - Add a CSS class to properly align the quantity columns in the Delivery Slip. --- **After Fix** <img width="735" height="290" alt="image" src="https://github.com/user-attachments/assets/69a941ff-a3a6-4e9a-993f-ad26af714b18" /> **Before Fix** <img width="757" height="274" alt="image" src="https://github.com/user-attachments/assets/7a4d0f78-112b-47ad-9037-da97e0399c8f" /> --- **opw- 4904727** --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Point of Sale now applies quantity-based pricelist rules correctly when the same lot-tracked product is split across multiple lots. This prevents customers from missing eligible pricing when their total purchased quantity meets the rule threshold, even if it appears on separate POS lines.
Original PR description
**PROBLEM** Pricelist rules based on a minimum quantity does not work well with lot tracked product, when the quantity is splitted between multiples lots. For example, if you take 2 product from lot…
**PROBLEM** Pricelist rules based on a minimum quantity does not work well with lot tracked product, when the quantity is splitted between multiples lots. For example, if you take 2 product from lot A, and 3 product from lot B, a rule defining the price for a minimum quantity of 5 will not trigger (it should). **STEP TO REPRODUCE** 1. install pos 2. create a lot tracked product 3. create a pricelist rule for the product, with a price based on min qty 4. from the pos, order the min qty but split it accross multiple lots 5. price will not takethe rule into account **CAUSE** Order line of lot tracked products are never merged. The quantity used to compute if a pricelist trigger is the quantity of each line individually. **FIX** For lot tracked product, to determine the price of a line, we parse find all corresponding lines and add their quantities together. Then we update all of their prices. To know if we should take into account a line, we verify if they would have been merged, if their product wasn't lot tracked. **REMARK** Ideally, their would be a way to merged order line of lot tracked product, while being able to edit the quantity taken from each lot directly from the pos. From now, order line doesn't work well with multiple lots, and it would require unstable change on the db. opw-4751920