Tuesday, September 23, 2025
67 changes · 18.0
New functionality added to Odoo
Odoo spreadsheets can now calculate account residual amounts for selected periods and partner balances directly with new formulas. This helps finance teams build more complete reports without manual exports, while related performance improvements make accounting spreadsheet calculations faster and more predictable.
Original PR description
Problem --------- There is currently no formula to get the residual amount of accounts in a given period of time in spreadsheets. Similarly, there is no formula to get the balance of a partner. Objective --------- Add the formula ODOO.RESIDUAL and ODOO.PARTNER.BALANCE that does just that. Furthermore, this PR contains a refactor of the addons/spreadsheet_account/models/account.py for easier management and faster computation of the functions. Check the relevant commits for more details. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Enhancements to existing features
Adds a download button for IR56B reports in Hong Kong Payroll, making it easier for users to export the required XML file. This supports smoother payroll reporting and reduces manual steps for preparing statutory submissions.
Original PR description
Add ir56b report download button for downloading .xml file in Hong Kong Payroll. task - 5081474
The web interface’s underlying OWL library has been updated to a newer version. This helps keep Odoo’s user interface foundation current and may bring small stability and maintainability improvements without introducing a direct business process change.
Original PR description
Update the OWL lib. Release notes: https://github.com/odoo/owl/releases/tag/v2.8.1 Forward-Port-Of: odoo/odoo#228092
Adds a dedicated option on the IoT Box homepage to resend connected device information to the Odoo server. This helps recover missing or reset IoT device records faster, avoiding unnecessary service restarts in lab, demo, or support situations.
Original PR description
In the context of the labodoo, database without IoT box are reseted which force to restart the IoT service to re-setup the IoT in the database. This does take some time and ressources that is not neccesary in this context as we would only need to retieve the IoT devices information. This PR propose the idea of having a dedicated route that would directly call the `send_alldevices` method which call `/iot/setup` route which will update the devices. I do think it can also be convenient in the context of the support in the case somehow a device was not synced (can likely happen if the odoo server was down when it was detected) or if the iot box record was removed from the odoo database and need to be recreated Preview: <img width="344" height="512" alt="image" src="https://github.com/user-attachments/assets/1b6c94b5-3f79-4d51-8e0e-f6a83f31bf46" /> task-5101536
Resolved issues and error corrections
Credit notes for Mexican public invoices can now keep the selected “Returns, discounts or bonuses” tax usage when allowed by SAT rules. This prevents the XML from being generated with the wrong default value, reducing compliance errors for companies using fiscal regime 616.
Original PR description
**Steps to reproduce:** 1. Install `l10n_mx` and `l10n_mx_edi`. 2. Create an invoice with: * Enable *CFDI to Public*. * Confirm, then send to SAT. 3. Create a credit note with: * *Usage* = `Returns,…
**Steps to reproduce:** 1. Install `l10n_mx` and `l10n_mx_edi`. 2. Create an invoice with: * Enable *CFDI to Public*. * Confirm, then send to SAT. 3. Create a credit note with: * *Usage* = `Returns, discounts or bonuses` (G02). 4. Download the generated XML for the credit note. **Observed behavior:** - The `<UsoCFDI>` tag in the XML shows `S01` (No fiscal effects). **Expected behavior:** - The `<UsoCFDI>` tag should show `G02` for credit notes under regime 616 when explicitly selected. **Root cause:** - For regime 616 (`Público en general`), the code always defaults to `S01`. - The condition only allowed `G02` when refunding a global invoice (`is_refund_gi`), not for normal credit notes. **Solution:** - Allow `G02` usage to be preserved for credit notes (tipo_de_comprobante = 'E') even when `CFDI to public` is active, as this is now permitted by SAT regulations for fiscal regime 616. **ref:** http://omawww.sat.gob.mx/tramitesyservicios/Paginas/documentos/catCFDI_V_4_20250820.xls opw-5012917
Fixed an issue where importing certain electronic invoice files could fail if the file contained a zero base quantity. This makes invoice imports more reliable for customers receiving UBL/CII documents with that value.
Original PR description
**Steps to reproduce:** - Install Accounting - Go to "Accounting / Customers / Invoices" - Import a UBL file having a value of 0 for a `<cbc:BaseQuantity>` element **Issue:** The import fails due to a division by 0 at: `price_unit = (net_price_unit + rebate) / basis_qty` **Cause:** "basis_qty" is retrieved as followed: `basis_qty = float(self._find_value(xpath_dict['basis_qty'], tree) or 1)` If the element is not defined, it will fall back on 1. But if the element exists with a value of 0, the "_find_value" method will retrieve the string "0" which is not False and will not fall back on 1. Then it will become `0.0` once converted to float. opw-5062985 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The website shop sitemap generation now uses less memory when handling very large product catalogs. This helps prevent server crashes caused by search engines or web crawlers requesting product sitemap pages.
Original PR description
### Issue Server crashes with MemoryErrors when a database has a large product catalogs. ### Solution This commit disables the prefetcher to avoid MemoryErrors when generating the sitemap for large product catalogs as web crawlers would continously crash the server when requesting the sitemap. ### References opw-5001680 opw-4955333 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Brazilian service invoices with installments now exclude taxes from the installment data sent for validation. This prevents rejection errors where installment totals do not match line totals, helping invoices process correctly.
Original PR description
Service invoices require us to send installments without taxes. If we include taxes we get an error: **Errors**: Rejection: Total Installments doesn’t match Total Lines ∑ installments[m]grossValue - ∑ (lines[n].lineAmount-line[n].lineTaxedDiscount) <> 0 This **PR** clears taxes before tax calculation to ensure the installments we send are correct. **task**-4761630
The Mexican e-invoicing flow now handles customer names entered with accents when matching them against official legal names that omit accents. This helps prevent invoice stamping errors for PoS customers using the self-invoicing portal.
Original PR description
Currently, the self-invoicing portal lets client request an invoice after making a purchase in PoS. A form allows them to enter their personal informations such as their name. Many of them enter their name with accents, however the government has all the names without any accents which causes errors when trying to match the requesting party with their legal name during the stamping process of the CFDI. task-4952174
This fixes an error that could appear when restaurant staff repeatedly edited a kitchen note and quantity before sending an order. The change helps keep point-of-sale order preparation workflows reliable and avoids unnecessary log errors during service.
Original PR description
Currently a `TypeError` is arising when user select a meal, add the 'Kitchen Note', change the quantity and hit 'Order'. Steps to reproduce this error: - Select a dish and add a 'Kitchen note', hit 'Order'. - Now edit the 'Kitchen note' and the quantity, hit 'Order'. - Again edit the 'Kitchen note' and the quantity, hit 'Order'. - The error appears in the logs. Error: `TypeError: 'NoneType' object is not subscriptable` This commit solves the above issue by checking if the `old_quantity` is not `None`. sentry-6013783573
The update prevents crashes when employee or working schedule timezone information is missing by safely using UTC as a fallback. This improves reliability in payroll and related workflows where missing timezone settings previously caused errors.
Original PR description
Currently a traceback occurrs from multiple places when there is no tz for employee and used in the `pytz.timezone` method.…
Currently a traceback occurrs from multiple places when there is no tz for employee and used in the `pytz.timezone` method.
https://github.com/odoo/enterprise/blob/517983ae9deec37795eb11522134a1f5ade31e9b/hr_payroll/wizard/hr_payroll_payslips_by_employees.py#L131
For instance, if there is no tz in resource_calendar_id, it leads to a traceback.
Error:
```
AttributeError: 'bool' object has no attribute 'upper'
File "odoo/http.py", line 2364, in __call__
response = request._serve_db()
File "odoo/http.py", line 1892, in _serve_db
return self._transactioning(
File "odoo/http.py", line 1955, in _transactioning
return service_model.retrying(func, env=self.env)
File "odoo/service/model.py", line 137, in retrying
result = func()
File "odoo/http.py", line 1922, in _serve_ir_http
response = self.dispatcher.dispatch(rule.endpoint, args)
File "odoo/http.py", line 2169, in dispatch
result = self.request.registry['ir.http']._dispatch(endpoint)
File "odoo/addons/base/models/ir_http.py", line 329, in _dispatch
result = endpoint(**request.params)
File "odoo/http.py", line 727, in route_wrapper
result = endpoint(self, *args, **params_ok)
File "addons/web/controllers/dataset.py", line 35, in call_kw
return call_kw(request.env[model], method, args, kwargs)
File "odoo/api.py", line 517, in call_kw
result = getattr(recs, name)(*args, **kwargs)
File "addons/web/models/models.py", line 70, in web_save
self.write(vals)
File "home/odoo/src/enterprise/18.0/hr_payroll/models/hr_contract.py", line 429, in write
res = super().write(vals)
File "addons/hr_work_entry_contract/models/hr_contract.py", line 453, in write
contract._recompute_work_entries(date_from, date_to)
File "home/odoo/src/enterprise/18.0/hr_payroll/models/hr_contract.py", line 441, in _recompute_work_entries
self._recompute_payslips(date_from, date_to)
File "home/odoo/src/enterprise/18.0/hr_payroll/models/hr_contract.py", line 453, in _recompute_payslips
all_payslips.action_refresh_from_work_entries()
File "home/odoo/src/enterprise/18.0/hr_payroll/models/hr_payslip.py", line 601, in action_refresh_from_work_entries
payslips._compute_worked_days_line_ids()
File "home/odoo/src/enterprise/18.0/hr_payroll/models/hr_payslip.py", line 1141, in _compute_worked_days_line_ids
slip_tz = pytz.timezone(slip.contract_id.resource_calendar_id.tz)
File "odoo/_monkeypatches/pytz.py", line 129, in timezone
return original_pytz_timezone(name)
File "__init__.py", line 183, in timezone
if zone.upper() == 'UTC':
```
To resolve this issue we can give a default value of `UTC` is there is no name. which makes the code more robust.
sentry-6134147853, 6119911834This fix prevents an error when users view or return to inventory quantity records that are missing location, lot, package, or owner details. The system now uses a default display name in those cases, helping users continue inventory updates without interruption.
Original PR description
Currently, an error occurs when computing a display name for stock quant. Step to produce: - Install the `stock` module(without demo data). - Go to inventory settings, enable Packages, Quality,…
Currently, an error occurs when computing a display name for stock quant. Step to produce: - Install the `stock` module(without demo data). - Go to inventory settings, enable Packages, Quality, Quality Worksheet, Reception Report, Variants, Units of Measure, Product Packagings, Lots & Serial Numbers, Display Lots & Serial Numbers on Delivery Slips, Expiration Dates, and Dropshipping. - Disable the Barcode Scanner. - After that, enable 'Display Lots & Serial Numbers on Invoices' in the Valuation section - Create a product and enable the 'Track Inventory' option. - In the product form view, click on On Hand in the breadcrumbs to navigate to the stock quantity list view - Create a new record to update the quantity. - Click on the 'View' button, remove the location, and try to come back to update quantity list view. `TypeError: sequence item 0: expected str instance, bool found` This error occurs because we compute the display name of stock quant and it is derived from location_id, lot_id, package_id, or owner_id. If none of these values are present in stock quant then the system tries to concate the False (bool) value with a string at [1] and an error occurs. Link [1]: https://github.com/odoo/odoo/blob/be6b327c17435947fc3f10d30fc8c4730c182aed/addons/stock/models/stock_quant.py#L585-L592 To resolve this issue, Assign a default display name of stock quant if none of the values of fields (location_id, lot_id, package_id, owner_id) are available. Sentry-6165002037 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Fixes an error that could stop users from printing and sending invoices when a related invoice report setting had been disabled. This helps ensure invoice delivery continues to work even when report options are customized.
Original PR description
Currently, An error occurs when the user print and send invoices and 'Invoice report' is disabled in reports 'report_invoice_with_payments'. Step to produce: - Install the `account` module. - Go to…
Currently, An error occurs when the user print and send invoices and 'Invoice report' is disabled in reports 'report_invoice_with_payments'. Step to produce: - Install the `account` module. - Go to Settings / Technical / Actions / Reports, Search 'report_invoice_with_payments', and disable the 'Invoice report'. - Go to Invoicing / Customers / Invoices, Create one invoice add a customer and invoice line, and Confirm it back to the list view of the invoice - Select this invoice and click on Print & Send. - After Opening a wizard, click the 'Print & Send' button. The issue occurs when the user tries to generate and send invoices and the system checks that 'is_invoice_report' is enabled for invoices at [1]. Link [1]: https://github.com/odoo/odoo/blob/658711aa1e1809b267006149ed6a547e548c1f90/addons/account/models/account_move_send.py#L658 To resolve this, we have to remove this comparison [1] as the user can disable 'is_invoice_report' from 'report_invoice_with_payments'. Sentry-6185986435 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Users can now update the resource on multiple planning entries at the same time from My Planning without triggering an error. This improves reliability for teams managing schedules in bulk and avoids interruptions when editing several planning slots together.
Original PR description
Currently, An error occurs when trying to change(update) all resources in planning slot at once from the 'My Planning' list view. Step to produce: - Install the `sale_planning` module (with demo data). - Open a list view of 'My Planning', Select all records, and try to change(update) all resources at one time. `ValueError: Expected singleton: planning.slot(5, 7)` The error occurs because the system attempts to access a single value of fields (allocated_hours, allocated_percentage) from multiple records at [1]. Link [1]: https://github.com/odoo/enterprise/blob/a3de64e02ea62da0ebb06c589ed122dad44243ca/planning/models/planning.py#L2043-L2044 To resolve this issue, Use an iteration(for loop) to iterate records one by one. Sentry-6217013028
This fixes an invoice sending issue where users could choose postal delivery even after the related postal mail feature was uninstalled, causing an error. The send invoice wizard now only shows delivery methods that are currently available, helping users complete invoice sending without interruption.
Original PR description
Currently, a traceback is occurring when the user tries to send a customer invoice with the sending method as `By Post`. To reproduce this issue: 1) Install Accounting and Unistall `snailmail` 3)…
Currently, a traceback is occurring when the user tries to send a customer invoice with the sending method as `By Post`. To reproduce this issue: 1) Install Accounting and Unistall `snailmail` 3) Create a posted `Customer Invoice` with a customer having no Invoice Sending (Remove the value in customer's accounting page if he has the value) 4) Click the `Send` button and select the sending method as `To Post` 5) Click the `Send` button in wizard Error:- ``` ValueError: Wrong value for res.partner.invoice_sending_method: 'snailmail' ``` The selection value `snailmail` for `invoice_sending_method` is defined in `snailmail_acount`. But it will be uninstalled when the `snailmail` module installed. https://github.com/odoo/odoo/blob/636d76d6dcbbe472b9d57cbe403d0758d94ad81d/addons/snailmail_account/models/res_partner.py#L7-L9 But in the `account.move.send.wizard`, the sending_method values are getting from the computed method `_compute_sending_method_checkboxes`. https://github.com/odoo/odoo/blob/636d76d6dcbbe472b9d57cbe403d0758d94ad81d/addons/account/wizard/account_move_send_wizard.py#L130 We get all the selection values(including the inactive) for the field `invoice_sending_method`. When the user selects the `snailmail` checkbox (By Post)to send the invoice, the value of `invoice_sending_method` for res.partner will be assigned from the below line. https://github.com/odoo/odoo/blob/636d76d6dcbbe472b9d57cbe403d0758d94ad81d/addons/account/wizard/account_move_send_wizard.py#L269 This will lead to the above traceback as the `snailmail` value for the selection field `invoice_sending_method` in the partner is not valid. We can resolve this issue by accessing only the active selection values for the field `invoice_sending_method`. So only the user can select the valid value for sending_method. sentry-6091298443
The Accounting report send wizard no longer crashes when users remove all recipients before sending or editing the email template. This prevents an unexpected error and lets users continue their workflow even when recipients are optional.
Original PR description
Currently, a traceback is occurring when the user tries to send a report by removing the partner in the wizard. To reproduce this issue: 1) install `Accounting` 2) Open the Partner Ledger report 3) Change the Report, Account to `Customer Statement` and `Payable` respectively 4) Click the `Send` button, and a send wizard will be opened 5) Remove the `Recipients` and navigate to the mail template from the wizard 6) In Email Configuration, enable the `Default Recipients` Error:- ``` KeyError: False ``` This traceback is occurring because the user removed the `mail_partner_ids` which is indeed not a required field. This leads to the traceback from the below line when accessing the `partner.id` from the mail_field_values. https://github.com/odoo/enterprise/blob/28b6a5d30274f4265c978433b8d02b758d9a032e/account_reports/wizard/account_report_send.py#L92-L96 sentry-6348424386
Users adding images by URL will no longer see a technical crash when the remote image cannot be reached or takes too long to respond. Instead, Odoo shows a user-friendly error while still logging details for support teams to investigate.
Original PR description
Currently, multiple tracebacks are occurring when the tries to add an image through URL. Types of exceptions occurring currently are ConnectionError and TimeoutError. https://github.com/odoo/odoo/blob/e0584a789b4bca0ab0d6691642440eec04433332/addons/html_editor/controllers/main.py#L255 We can resolve this issue by showing a user exception and a logger warning(for debugging) instead of a traceback. sentry-6093300975
CodaBox connection management now shows a clear user-facing error when the selected accounting firm has no VAT number. This prevents a confusing technical crash and helps users correct the missing company information before continuing.
Original PR description
The system fails to retrieve vat number of accounting firm when computing `l10n_be_codabox_fiduciary_vat` field value Steps to Produce: 1. Install the `l10n_be_codabox` module and switch to `BE Company CoA` company. 2. Set Accounting firm without vat for BE Company CoA 3. Goto setting > Accounting section > CodaBox & SODA 4. Click `Manage Connection` or refresh icon of CodaBox Connection Error: `TypeError: expected string or bytes-like object, got 'bool'` Solution: Raise `UserError` if value of `account_representative_id.vat` is False Sentry - 6499169614
Odoo Studio now avoids crashing when a user saves a report after removing all report content. The change checks that the expected report element exists before trying to update it, so the save action can complete without an index error.
Original PR description
The error occurs when `main_qweb.xpath("//*[@id='wrapwrap']")[0]` is accessed,
but the XPath query returns an empty list. This leads to an `IndexError: list
index out of range`.
-Steps to produce:
1. Open Odoo Studio
2. Create an empty new report using studio
3. Click on EDIT SOURCES
4. Select studio customization in uses to edit report
5. remove all elements from <t t-name="studio_main_report">
6. click on save
Error: "IndexError: list index out of range"
-Solution:
Wrapped the XPath query inside a conditional check before accessing `[0]`.
Now, the code verifies whether the list is non-empty before proceeding with
element replacement.
If the element is missing, the operation is skipped, preventing the crash.
sentry-6197314021Users installing modules now receive a clean, understandable error if they upload a file that is not a valid ZIP archive. This prevents a technical crash message and improves the module installation experience.
Original PR description
The error could occur when a user uploads a non-ZIP or malformed ZIP file during module installation. The `zipfile.ZipFile` call raises `BadZipFile` when the file is invalid, but this was not properly caught in all cases. `Error: 'BadZipFile: File is not a zip file'` Solution: -Wrapped the `zipfile.ZipFile(BytesIO(zip_data), 'r')` and similar elements inside a `try...except` block to catch `BadZipFile` and raise a clean `ValidationError`, preventing unhandled exceptions and improving UX. sentry-6066860008
The PDF Quote Builder now blocks empty files before they are uploaded. This prevents users from hitting an error when configuring quotation headers or footers and keeps the setup flow smoother.
Original PR description
Currently, a error is encountered on uploading an empty file in a `PDF Quote Builder` . **Steps to reproduce:** - Install `Sales` - `Sales>Configuration>Settings` - Under `Quotations & Orders>PDF Quote builder>Headers/Footers`, upload an empty file or try this [demo_file](https://drive.google.com/file/d/1NePURnYY3EK63vXM_uz8weJZwDbUbHfc/view?usp=sharing) **Error:** `EmptyFileError: Cannot read an empty file` **Root Cause:** The error occurred because the system attempts to read the uploaded file at [1] triggered by [2]. If the uploaded file is empty, it raises an `EmptyFileError`. [1] - https://github.com/py-pdf/pypdf/blob/5735cb742a45a503e8eb7e409067f7c3d4cb9158/PyPDF2/pdf.py#L1691 [2] - https://github.com/odoo/odoo/blob/9463bfeb58fb40176ecf1131bac6627a1627d02c/odoo/tools/pdf/_pypdf2_1.py#L18 This commit ensures that users cannot upload empty files. sentry-6519503224,6519471276
A live chat rule with certain special characters in the URL field could cause the website to fail when opened. This update safely handles those characters so the website remains available even if a rule contains problematic input.
Original PR description
Setting special regex characters for`regex_url` inside live chat rules throws unhandled regex error.
**Steps to reproduce:**
- Install `website` and `im_livechat`
- Go to `livechat>YourWebsite.com Dropdown Menu>configure channel`
- Go to `channel rules>Add a line`
- Inside URL Regex field enter any of the quantifier regex such as `+`, `*`, `
`{any number}`, `[]`,`{any number range start,any number range limit}` and save
the rule.
-Open `website`.
Error:
`re.error: nothing to repeat at position 0`
**Solution:**
- We use `re.escape()` to safely handle user input that may contain special regex characters.
**Sentry-6538643923**Purchase bills in the Indian GSTR-2B workflow now return to a clean reconciliation state when reset to Draft. This prevents old return-period links or exceptions from carrying over, helping teams reconcile the bill correctly from the beginning.
Original PR description
When a purchase invoice (bill) is reset to Draft: - Reset GSTR-2B reconciliation status to "pending" - Unlink from GST return period - Clear any existing exceptions This ensures that the bill returns to its initial stage for proper reconciliation. Task ID: 5095582 Forward-Port-Of: odoo/enterprise#95026
Email Marketing now handles incorrectly encoded pasted images more gracefully when editing an email template. Instead of failing with a technical crash, the system can inform the user that the image content is invalid, helping prevent corrupted images from being used in mass mailings.
Original PR description
When user edits mail template html and pastes an image tag with invalid encoding it throws an error. **Steps to reproduce:** * Install Email marketing and activate developer mode. * Email…
When user edits mail template html and pastes an image tag with invalid encoding it throws an error. **Steps to reproduce:** * Install Email marketing and activate developer mode. * Email marketing>New>Mail Body> Start From Scratch>click `</>` icon * Paste any improper image element which doesn't have proper base64 encoding, for example: `<img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU 5ErkJgg'/>` * Enter any Subject name and save. `binascii.Error: Invalid base64-encoded string: number of data characters (113) cannot be 1 more than a multiple of 4` **Solution:** * It would be better to let the user know about the error than to let them mass mail corrupted image element. * This can be done and handled by a try and except statement when the image element added is not proper. Sentry-6495526846 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix prevents an unexpected error when users customize reports in Studio. It makes report editing more reliable by safely handling missing internal comparison data instead of interrupting the user workflow.
Original PR description
Currently, `KeyError: None` might occur when customizing the `Reports ` in **studio**. - The `KeyError` can occur in the `diff` method when the `DIFF_ATTRIBUTE` is absent in the `new_tree`. - This happens because the code at [1] attempts to access `self.map_id_to_node_old[new_tree.get(DIFF_ATTRIBUTE)]` without verifying if `new_tree.get(DIFF_ATTRIBUTE)` is `None`. [1]- https://github.com/odoo/enterprise/blob/c6148cd50e7446e43b3f327a4c25e7c0ffa03446/web_studio/controllers/keyed_xml_differ.py#L239 - This commit ensures the code handles cases where `DIFF_ATTRIBUTE` is missing and preventing KeyError. sentry-6430937782
Field service sales orders with zero-priced service lines now correctly move to an invoiced status once their related invoice is posted. This prevents orders from incorrectly remaining marked as needing invoicing, giving teams a clearer view of completed billing work.
Original PR description
Steps: - Install sale and fsm module. - Enable anglo-saxon from the setting. - Create a service type product with fsm project as template. - Select that product on SO and set unit price to 0 on SOL. - Confirm that order and create and post invoice. Issue: - Sale order status still shows `To invoice` even though we create SOL related invoice. Cause: - In [PR] we made invoice status for anglo-saxon line `To Invoice` so it always say `To Invoice` even user create related invoice. Fix: - Make those lines `Invoiced` if there is related invoice by checking qty_invoiced is greater or equal to qty. [PR]: https://github.com/odoo/enterprise/pull/70132 opw-5055540 Forward-Port-Of: odoo/enterprise#94723
Fixes an issue where automated cleanup of old Ecuador withholding wizard records could fail when related withholding lines still existed. This prevents background terminal errors and keeps scheduled maintenance running smoothly without affecting users in the interface.
Original PR description
Foreign key error occurs when a cron job deletes a `withhold (transient model)` still linked to a `withhold.line`. The error appears in the terminal, not the UI. To reproduce, ensure withhold records…
Foreign key error occurs when a cron job deletes a `withhold (transient model)` still linked to a `withhold.line`. The error appears in the terminal, not the UI. To reproduce, ensure withhold records in `l10n_ec_wizard_account_withhold` are old enough to be removed by `Auto-vacuum`. Refer to [this](https://github.com/odoo/odoo/blob/e062c9b5773ed0710503c13627e60f8233fcd0a5/odoo/models.py#L7493C1-L7493C87) to understand how transient models are cleaned by the `Auto-vacuum` process. **Steps to reproduce:** * Install `l10n_ec_edi` and `accountant` * Change company to `EC company` * `Accounting>Customers>Invoices>New` * Confirm invoice with customer as `EC company` and `Payment method (SRI)` as Credit card * Add Withhold > Set document number to `001-001-123456789` > Add withhold lines * `Create and Post`(error will occur when cron tries to delete transient model transient model after couple of hours.) `psycopg2.errors.ForeignKeyViolation:update or delete on table 'l10n_ec_wizard_account_withhold' violates foreign key constraint 'l10n_ec_wizard_account_withhold_line_wizard_id_fkey' on table 'l10n_ec_wizard_account_withhold_line'` **Solution:** * Unlink withhold lines first and then let normal unlink take place. **Sentry-6253783256**
This update adjusts spreadsheet-related testing assets to correct an issue in the FRGI test setup. It helps keep spreadsheet functionality more reliable by ensuring the relevant tests run as expected.
Original PR description
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
Sales orders now better identify coupon and global discount lines, so related integrations can report the correct discounted amount. This also prevents discount line values from being accidentally reset when their quantity changes, improving accuracy for order totals and delivery/payment workflows.
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#223517
Shiprocket cash-on-delivery shipments now include coupon-based discounts in the amounts sent to Shiprocket. This prevents customers and merchants from seeing incorrect COD totals when promotional coupons are applied, including tax-inclusive discount handling.
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#92310This fixes company filtering by country, which previously did not work because the country field could not be searched. Businesses using country-specific localizations, such as Belgium or Switzerland, can now apply company restrictions by country as intended.
Original PR description
As the company country_id field was computed and not searcheable, it was not possible to restrict the company domain per country. This is needed in some l10n, like BE or CH. This commit implements the search method for the country_id field of the company. Done as part of task-5096037 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes an issue where the command palette could crash when a task status field had no available options, such as in some Field Service task workflows. Users can now open command search safely; unavailable status actions are simply hidden instead of causing an error.
Original PR description
**Steps to reproduce:** - Installed industry_fsm (Field Service) module - Navigate the menu Field Service -> Configuration -> Project - Create a new project - Then Navigate the menu My Tasks -> Tasks…
**Steps to reproduce:** - Installed industry_fsm (Field Service) module - Navigate the menu Field Service -> Configuration -> Project - Create a new project - Then Navigate the menu My Tasks -> Tasks - Create a new task with the new created project - Then using the keyboard shortcut ctrl + k for command search, an error occurs **Cause:** - When the `stage_id` statusbar had no possible values, `this.getAllItems()` returned an empty array. - The command `isAvailable` unconditionally accessed `this.getAllItems().at(-1).isSelected`, which is undefined, causing a crash.[see](https://github.com/odoo/odoo/blob/17.0/addons/web/static/src/views/fields/statusbar/statusbar_field.js#L147-L148) **Fix** - Add safe check in the command action so it does not attempt to select a non-existent "next" item. **Result** - The command palette no longer crashes when the `stage_id` field has no available items. Instead, the command is simply unavailable. opw-5084130 upg-3130405 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#227440
This fix prevents users from changing the amount in currency on posted journal items in ways that could leave invoice totals and related analytic entries inconsistent. The field remains editable only where appropriate, such as draft tax lines, helping preserve accurate accounting records.
Original PR description
- Create an invoice with some products and post it - Go to Accounting > Journal items and ser for the ones belonging to the invoice. - Set the checkbox for the product sales one and set whatever tax…
- Create an invoice with some products and post it - Go to Accounting > Journal items and ser for the ones belonging to the invoice. - Set the checkbox for the product sales one and set whatever tax grid (you'll have to reveal that column). - Accept the changes. - Now go back to the invoice. - You'll see a new tracking message. Something like Journal Item #1093 updated - It contains a link and from that link you can go to the journal item form. - In that form you can edit the *amount in currency* field. Issue: - If a user do so, it leaves inconsistent invoice amounts: totals aren't recomputed, analytic lines aren't recomputed either. How it should behave: - Amount in currency shouldn't be editable here. Mainly when the journal entry is already posted! opw-4951629 A vídeo showing the issue: 📹️ https://www.loom.com/share/f7cd1d8f4138458f9b6c190233b0b9df?sid=eec77c17-a4a6-4698-8604-10aaa7e33f47 MT-10887 cc @moduon --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#225346 Forward-Port-Of: odoo/odoo#223187
Merging timesheet entries linked to the same helpdesk ticket now keeps that ticket connection intact. This prevents support work records from becoming detached from the related customer issue, and blocks merges when selected entries belong to different tickets.
Original PR description
…helpdesk ticket **Steps to reproduce** - Register 2 timesheet lines on 1 helpdesk ticket - Go to the timesheets app and select these 2 lines - Go to Actions -> Merge timesheets Issue: the timesheets are merged but unlinked from the helpdesk ticket. **Change** Preserve the link to the helpdesk ticket when merging timesheets. An error is raised if attempting to merge timesheets not having all the same `helpdesk_ticket_id` value. opw-5086090
Sendcloud deliveries can now use customs HS codes up to 12 characters, matching Sendcloud's current API rules. This helps prevent international parcels, especially shipments to the US, from being delayed because their customs code was shortened or rejected.
Original PR description
**PROBLEM** We limit the `hs_code` length to 8 characters, but if we refer to the [sendcloud v2 api doc](https://api.sendcloud.dev/docs/sendcloud-public-api/branches/v2/parcels/schemas/parcel-item), we see that `hs_code` length can be up to 12 characters. Some clients have issue with parcels being held longer in custom when sending them to the US. [opw-5051585](https://www.odoo.com/odoo/project/49/tasks/5051585) Forward-Port-Of: odoo/enterprise#94894
This fixes an issue where changing the address of a Czech company with demo data could fail with a validation error. Demo accounting dates are now aligned so company details can be saved normally without disrupting document numbering checks.
Original PR description
## [FIX] l10n_cz: prevent error with misaligned accounting date and sequence number of demo moves #### Description of the issue/feature this PR addresses: Editing CZ Company address while having demo…
## [FIX] l10n_cz: prevent error with misaligned accounting date and sequence number of demo moves #### Description of the issue/feature this PR addresses: Editing CZ Company address while having demo data throws Validation Error #### Current behavior before PR: When trying to change address of CZ Company while l10n_cz with demo data is present an error popup is displayed and it's not possible to to save the changes. Steps to reproduce: - Install l10n_cz with demo data - Open CZ Company in form view - Change address (e.g. change city Praha -> Brno) - Click Save #### Desired behavior after PR is merged: The address changes are saved without any error. #### Solution: This change adds `taxable_supply_date` date values for CZ demo moves that are compatible with `invoice_date` values to make sure that accounting date values are the same on each recomputatation and do not lead to new sequence numbers that are not aligned with the previous ones which would cause errors being raised by sequence mixin. Related to: #226152 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The Belgian POS fiscal reporting screens no longer show the warning "THIS IS NOT A VALID VAT TICKET" on invoices and daily reports. This avoids confusion by keeping the warning only where it belongs: on POS receipts that are not final VAT tickets.
Original PR description
- Remove the message "THIS IS NOT A VALID VAT TICKET" from the invoices and POS daily reports views. This message is only necessary on POS receipts that are not final TVA tickets. task-id: 5013860
This fixes a problem where users with employees in multiple companies could hit a validation error when adding timesheets to Helpdesk tickets. Timesheets now keep the intended company instead of being overwritten when the linked project has no company set, reducing disruption during daily work and migrations.
Original PR description
Steps to Reproduce: ------------------ - Open Helpdesk. - Go to Configuration → Helpdesk Teams. - Create a new team. - Enable the Billing feature and assign a project to this team. - Set the…
Steps to Reproduce: ------------------ - Open Helpdesk. - Go to Configuration → Helpdesk Teams. - Create a new team. - Enable the Billing feature and assign a project to this team. - Set the project’s Company field to Null. - Create an employee for the current user in another company. - Ensure the user has employees in both companies. - Create a new ticket (or open an existing one) in the newly created team. - Try creating a new timesheet → a Validation Error is raised. Root Cause: ----------------- When a user has employees associated with multiple companies and tries to log a timesheet with multi-company enabled, a validation error occurs. **This happens because:** - The default company is derived from the project linked to the Helpdesk team. Since the company_id field on the project is no longer required, it may be Null, leading to an error when fetching the correct [employee for the company](https://github.com/odoo/odoo/blob/6a36015e2ee69aafe3880bf1fff38439af5cd673/addons/hr_timesheet/models/hr_timesheet.py#L214-L216 ). - Additionally, the [company check](https://github.com/odoo/enterprise/blob/83a1b88c8cae4db5c9b1bf82ee7ebb4e13c41b2a/helpdesk_timesheet/models/analytic.py#L81-L82) is incorrect. The code is checking whether the `company_id` key exists in a `list of vals`, whereas it should be checked directly on the vals dict itself. Issue Faced: ------------- In version 18.3, timesheets are created during migration [here](https://github.com/odoo/upgrade/blob/24f85bbc3408bf10b1cee93e4c395edf806beaa8/migrations/helpdesk_timesheet/saas~18.3.1.0/post-migrate.py#L44-L58 ). Even though the correct company_id is passed, it gets overridden during the process. and If the associated project does not have a company set, the company_id becomes False [here](https://github.com/odoo/enterprise/blob/83a1b88c8cae4db5c9b1bf82ee7ebb4e13c41b2a/helpdesk_timesheet/models/analytic.py#L81-L82), which results in a Validation Error because the [here](https://github.com/odoo/odoo/blob/6a36015e2ee69aafe3880bf1fff38439af5cd673/addons/hr_timesheet/models/hr_timesheet.py#L214-L216) unable to determine the correct employee linked to the company. OPW: 5004092 Forward-Port-Of: odoo/enterprise#92507
Creating a mail blacklist entry from a website form no longer fails with an unexpected error when the email field is missing. Instead, Odoo now shows a clear user-facing error, improving reliability for website form submissions.
Original PR description
Currently, an error occurs when creating a blacklist entry from the website. Steps to Reproduce: - Install the `website_crm_iap_reveal`, `website_mass_mailing` and `web studio`. - Go to `Website` > any page, click `Edit`, and drag and drop a `Form` onto the page. - Select the form, in `Action` dropdown, choose `More models` and select `Mail Blacklist`. Save the changes. - Click the Submit button. `KeyError: 'email'` This error occurs when creating a blacklist entry from the website and the email field is missing. When it tries to access the email key in value[1] while creating the record, it raises a KeyError. [1] https://github.com/odoo/odoo/blob/d83801027c9a88b6e4db8166b6e2aad41ed760b9/addons/mail/models/mail_blacklist.py#L31 This commit ensures that if the email is not present in the value, a UserError is raised. sentry-6708162583 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix prevents an error when users open sales order line details with invoice lines from a product form dialog. It ensures the accounting matching widget uses the current record context when a search context is unavailable, avoiding an unexpected crash in this workflow.
Original PR description
…in a dialog Steps to reproduce ================== Prerequisites: Having a product with an SO and an Invoice confirmed. Steps: - Open Product Variant Form - Open Studio - Add new O2M to SOL: Product (Sale Order Line) - Edit subview form - Add invoice_lines - Quit Studio - Click on SOL on Product view → It crashes => TypeError: can't access property "context", ctx.env.searchModel is undefined Cause of the issue ================== In form view dialogs, we don't have a search model Solution ======== We should use the context from the current record opw-4921186
Automation rule setup now avoids carrying an internal archived-record setting into later selection dialogs. This prevents archived contacts or users from appearing where they should not, making configuration cleaner and less confusing.
Original PR description
**Before** - the active_test context key is part of the main base_automation action (base_automation_act), but this context key stays in the context further, leading to unwanted filtering in i.e. the…
**Before** - the active_test context key is part of the main base_automation action (base_automation_act), but this context key stays in the context further, leading to unwanted filtering in i.e. the action_server_ids.resource_ref search view dialog. - Steps to reproduce: - have base_automation installed - create an automation rule targeting the res.users model - add an Update server action targeting the Partner field - in the resource_ref autocomplete, click on Search More... - the search view dialogs displays archived records **After** - we chose to instead have a default filter in the base_automation_act action to include archived records by default. As the context key to activate the default filter starts with 'search_default_', it is already cleared from the context when opening the form view (standard behavior). - when you reproduce the same steps as before, the archived records are no longer displayed in the search view dialog. **Additional Note** This fix requires to upgrade the base_automation module. opw-4886487
ENASARCO taxes are now correctly treated as both withholding and pension fund contributions in Italian electronic invoices. This ensures compliant XML reporting and correct default setup when installing the Italian localization modules.
Original PR description
* = l10n_it, l10n_it_edi, l10n_it_edi_withholding The ENASARCO tax works both as a Withholding (negative) tax and as a Pension Fund tax. It must appear in the XML in both sections DatiRitenuta and CassaPrevidenziale. - We modified the master data to amend this error. Now the correct Withholding type appears right after installing the module. - Since there was an explicit check on taxes being both, we removed it. - Removed an exception where ENASARCO taxes were allowed to have positive values Forward-Port-Of: odoo/odoo#226357
Fixes an issue where matching a purchase order to a vendor bill could fail when both used the same individual contact linked to a company. The matching process now treats the individual and its parent company consistently, preventing the error and allowing the workflow to complete.
Original PR description
**Issue** When both a Purchase Order and a Vendor Bill are created using the same individual contact linked to a company, Bill Matching fails with a traceback. **Steps to Reproduce** 1. Create an…
**Issue** When both a Purchase Order and a Vendor Bill are created using the same individual contact linked to a company, Bill Matching fails with a traceback. **Steps to Reproduce** 1. Create an individual contact and link it to a company. 2. Create a Purchase Order with the individual as a vendor. 3. Create a Vendor Bill with the same individual as the vendor. 4. Try to perform Bill Matching. 5. A `ValueError: Expected singleton: res.partner(...)` is raised. Video for reference: https://drive.google.com/file/d/1qVnPLpk8jyMTKz-6AVLSaN2nVVeWiF4y/view **Root Cause** Purchase Orders store the partner exactly as selected (the individual contact), while Vendor Bills are normalized internally to the parent company (`commercial_partner_id`). This creates a mismatch in the Bill Matching logic, where records reference both the individual and the company, leading to an invalid recordset and the singleton error. **Fix** Always normalize vendors to their `commercial_partner_id` during Bill Matching. This ensures that both Purchase Orders and Vendor Bills consistently reference the same partner, avoiding mismatches between individual contacts and their parent company. Opw-5050339 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Fixes an issue where confirming a batch transfer could lose barcode settings, causing location barcodes such as WH-Stock to be read incorrectly. Warehouse users can now confirm batch deliveries and continue scanning locations normally without failed scans caused by split characters.
Original PR description
### Steps to reproduce: - In the settings enable: "Batch, Wave & Cluster Transfers" - Create 2 deliveries - Barcode > operations > Delivery orders > Batches > New - Add your two deliveries and…
### Steps to reproduce: - In the settings enable: "Batch, Wave & Cluster Transfers" - Create 2 deliveries - Barcode > operations > Delivery orders > Batches > New - Add your two deliveries and confirm - Scan WH-Stock #### > The scan fails considering you scanned each letter independently. ### Cause of the issue: When the barcode is scanned a call of the split barcode will be launched to split the barcode in multiple barcodes according to the `barcode_separator_regex` present in the config: https://github.com/odoo/enterprise/blob/aeb9343f4b7dfab0fbc04bca4623ae85b3ea6030/stock_barcode/static/src/models/barcode_model.js#L613-L632 The issue lies in the fact that even thought the is `barcode_separator_regex` was conrrectly populated at the onWillStart of the mainComponent: https://github.com/odoo/enterprise/blob/aeb9343f4b7dfab0fbc04bca4623ae85b3ea6030/stock_barcode/static/src/components/main.js#L209-L213 https://github.com/odoo/enterprise/blob/aeb9343f4b7dfab0fbc04bca4623ae85b3ea6030/stock_barcode/controllers/stock_barcode.py#L97 https://github.com/odoo/enterprise/blob/aeb9343f4b7dfab0fbc04bca4623ae85b3ea6030/stock_barcode/static/src/components/main.js#L229 https://github.com/odoo/enterprise/blob/aeb9343f4b7dfab0fbc04bca4623ae85b3ea6030/stock_barcode/static/src/models/barcode_picking_model.js#L36-L38 It was reset by the batch confirmation here: https://github.com/odoo/enterprise/blob/aeb9343f4b7dfab0fbc04bca4623ae85b3ea6030/stock_barcode_picking_batch/static/src/models/barcode_picking_batch_model.js#L123-L135 because this part of the config is not meant to be returned by the private method `_get_barcode_data` but rather by public complete version `get_barcode_data`: https://github.com/odoo/enterprise/blob/aeb9343f4b7dfab0fbc04bca4623ae85b3ea6030/stock_barcode/controllers/stock_barcode.py#L91-L98 Now, since no `barcode_separator_regex` was provided to our new config, each character will be considered to be considered as an independent barcodes and the `WH-Stock` barcode will not match any location. opw-5062331
Resetting a user's Odoo Calendar no longer incorrectly triggers an error about changing events the user cannot edit. This makes calendar resets complete as expected and avoids unnecessary support issues for Google Calendar users.
Original PR description
Before this commit, when resetting the Odoo Calendar of an user, it would trigger a ValidationError for updating events that the current user wasn't able to update, even though it was not an updated per se, but just a deletion of it in Odoo. After this commit, we no longer trigger that ValidationError during resets of Odoo Calendars, fixing the error. task-5103918
Employees and managers can now enter a checkout time directly from the Attendance Gantt popup for open attendances. This fixes a display issue that hid the checkout field when it was empty, reducing extra navigation and manual correction steps.
Original PR description
The Gantt popup form explicitly set `check_out` invisible when it was empty, which prevented users from manually entering a checkout for an open attendance. This commit removes the overriding xpath so that the form simply inherits the standard `hr_attendance_view_form` behavior, where the `check_out` field is always visible and editable. Users can now set a manual checkout directly from the Gantt modal. task-5026978
Archived or trashed documents are now correctly hidden when users search for document values while setting up automation actions. This prevents users from accidentally selecting removed documents, while still allowing archived automation rules to remain visible where intended.
Original PR description
This PR addresses an issue where trashed files in documents would still appear when clicking on 'search more' when searching for documents.document in a scheduled action's action. The issue is that…
This PR addresses an issue where trashed files in documents would still appear when clicking on 'search more' when searching for documents.document in a scheduled action's action. The issue is that the base_automation_act view sets active_test context to False. This context is propagated to view_base_automation_form and results in the context for the field action_server_ids to be active_test = False. The fix for this issue will just be setting active_test to True for the action_server_ids field. This will make it such that the 'search more' action will no longer display anything archived but archived automation rules will still be displayed which was probably the original intention of setting active_test to False in base_automation_act. Steps to reproduce bug on empty DB: 1) Install base_automation and documents modules. 2) Create a new automation rule targeting the documents module. Make sure to add a trigger. 3) Click on 'Add an action' in the page 'Actions To Do'. 4) In the wizard under action details, set the targeted field to 'folder' (folder_id). Leave the action as 'Update'. 5) Click on the 'Choose a value' drop down. 6) Click on 'Search more'. 7) Notice the number of documents that show up. The numbers on the top right hand side of the wizard should be 1-y/x where x is the total number of documents. 8) Go to the documents module and select any document. 9) Move the document to the trash with the actions button. 10) Repeat steps 4-7. Notice how the number of documents did not change. Behavior after bug fix: Upon completing step 10 of steps to reproduce on empty DB, the number of documents will be one less than what it was originally since we trashed one of the documents. task-4886487 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update fixes an automated test that could fail when Czech localization was installed. It makes the test use the actual payment reference generated by the system, improving build reliability without changing business functionality.
Original PR description
test_document_data_for_bank_journal_with_show_payment_option was failing in builds with l10n_cz installed because - we set move_sales_2.payment_reference = '' in setUpClass and without l10n_cz it stays empty - but with l10n_cz installed it gets recomputed because of precompute=True on taxable_supply_date (which is a stored computed field that triggers an extra write on account.move when the company is in CZ, and that write causes the compute graph to run again, and _compute_payment_reference fills the value back in) this commit solves this issue by not making assumptions about the payment_reference value and would use it as is in the generated data validation build_error-231479
This fixes an issue where Ctrl+Backspace behaved differently in Firefox and Safari compared with Chrome when editing empty or adjacent paragraphs. Users now get consistent text deletion behavior across supported browsers, reducing editing surprises and accidental content changes.
Original PR description
**Current behavior before PR:**
In Firefox or Safari, `<p>abc def</p><p>[]<br></p>` => `ctrl + backspace` ends up with `<p>abc []</p>` which is different o/p than Chrome (`<p>abc def[]</p>`).
This happens because Firefox's Selection.modify("extend", "backward|forward", "word") behaves differently than Chrome when the cursor is at the start or end of a block (or in an empty block). This behavior breaks the output when pressing ctrl + backspace.
**Desired behavior after PR:**
This PR ensures that in such case deletion behavior is same across browsers as Chrome. In other words `<p>abc def</p><p>[]<br></p>` => `ctrl + backspace` should be `<p>abc def[]</p>` .
task-5055135
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prCustomer statement emails sent from child contacts now avoid sending empty statement attachments. The statement button is also hidden when there is no activity or no amount due, reducing confusion for accounting users.
Original PR description
**Steps to reproduce:** 1. Go to Accounting > Customers > create a company with child contact (invoice) (both having name and email). 2. Create an invoice with the child contact as customer and…
**Steps to reproduce:** 1. Go to Accounting > Customers > create a company with child contact (invoice) (both having name and email). 2. Create an invoice with the child contact as customer and confirm it. 3. Go to the child contact and open the Customer Statement smart button. 4. Download the PDF → data is shown correctly. 5. Send the statement → the attachment in the sent mail is empty. **Issue:** - When sending customer statements via email from a child contact, the generated PDF attachment contains no data, showing empty amounts and transactions. - Additionally, the "Customer Statement" button was still visible even when the total due was zero. **Cause:** - The button visibility condition checks for `total_due == 0.0 and not has_moves`, which didn’t properly cover all use cases. **Solution:** - Update button visibility condition to: `invisible="not has_moves or total_due == 0"` ensuring it is hidden when there are no moves or the total due is zero. **opw-5009182**
This fix prevents key details on confirmed and locked sales orders from being changed in another browser window. It helps avoid data corruption when multiple users or tabs interact with the same order at the same time.
Original PR description
Add _get_protected_fields() method and protection logic to prevent modification of critical fields when sale order is locked, matching the existing protection in sale.order.line. Problem Critical…
Add _get_protected_fields() method and protection logic to prevent modification of critical fields when sale order is locked, matching the existing protection in sale.order.line. Problem Critical vulnerability where multiple users could simultaneously edit the same sale order, causing data corruption when an order was confirmed (and locked) in one window while still being edited in another. Specific scenario: Sale order opened in 2 windows/tabs simultaneously User A confirms the order → automatically locked ([locked=True](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)) User B can still modify [partner_id](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) from the other window Result: Corrupted data in confirmed order --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix stops internal users from being assigned to a website in a way that could later break module installation, such as Helpdesk. Users are now warned earlier when the setup is invalid, reducing unexpected installation failures and improving reliability.
Original PR description
Scenario: - Install website and set a website on an internal user - Install helpdesk Result: installation fails with a traceback containing the message "Remove website on related partner before they…
Scenario: - Install website and set a website on an internal user - Install helpdesk Result: installation fails with a traceback containing the message "Remove website on related partner before they become internal user.". Cause: 479e8d0cae98f7e086e5fb4a0ca4e33ed24bfc12 added a constraint so when the groups are changed, we raise an error if the user is internal and as a website_id set. But if we do it the other way (setting a website_id on an internal user), no restraint prevent this, but if at any moment the groups of the user are changed (which helpdesk does by adding implied_ids groups) we get an unexpected error. Fix: change the constraint to be triggered by both website_id and groups_id change so the user is aware sooner than he should not do it. Note: the current code also prefetched all internal users and would not work with non-active user, so this code simplifies that by just prefetching the groups of the current users. opw-5077601 PR note: putting this in draft since this is breaking some tests that I need to check
Membership invoices now keep the right invoice context when opened, so membership products remain searchable on invoice lines even if they are not marked as purchasable. This prevents users from being blocked when editing draft membership invoices after changing product purchase settings.
Original PR description
**Steps to Reproduce:** 1. Create a new membership product from the Membership module. 2. Open any partner and go to the Membership page. 3. Click on Buy Membership and select the created product. 4.…
**Steps to Reproduce:**
1. Create a new membership product from the Membership module.
2. Open any partner and go to the Membership page.
3. Click on Buy Membership and select the created product.
4. Click on Invoice Membership.
5. Open the newly created draft invoice.
6. From the invoice line, open the product form (via the internal link).
7. Disable the Can be Purchased option and return to the invoice using breadcrumbs.
8. Add a new line in the invoice and search for the same product by its name.
**Observation:**
1. When Can be Purchased is enabled on the product, the product appears in the invoice line search.
2. When Can be Purchased is disabled, the product no longer appears in the search.
**Issue:**
In the product field domain defined in
https://github.com/odoo/odoo/blob/9ba5b41ef0252f4421ff6cdcd7c047b7c53706f4/addons/account/views/account_move_views.xml#L1022-L1029 the `default_move_type` context is `null`.
As a result, only the condition `[('purchase_ok', '=', True)]` is applied in the `name_search` domain.
**Solution:**
Pass the proper context value in the invoice action, ensuring the domain evaluates correctly and the product remains searchable.
**Note:**
The domain used in the following field
https://github.com/odoo/odoo/blob/9ba5b41ef0252f4421ff6cdcd7c047b7c53706f4/addons/account/views/account_move_views.xml#L1022-L1029
is evaluated by a following JavaScript function
https://github.com/odoo/odoo/blob/9ba5b41ef0252f4421ff6cdcd7c047b7c53706f4/addons/web/static/src/core/py_js/py_interpreter.js#L483-L489
rather than on the Python backend. Because the domain logic depends on dynamic
context evaluation performed client-side, there is no straightforward way to
retrieve or test the domain arguments dynamically within the `name_search`
method on the server. As a result, it is not feasible to write automated test
cases for this specific domain filtering scenario in the backend.
opw-5028789
Forward-Port-Of: odoo/odoo#225230This fix corrects a typo that affected how a lock-date warning message was displayed when editing report external values. The message now appears as a properly formatted list, making it easier for users to read and understand what is blocking the change.
Original PR description
[FIX] account_reports: typo in error message typo in generation of error message saying that lock dates are blocking the modification of a report external value See odoo/enterprise#92949
The analytic distribution widget now limits analytic account choices to the company on the document. This prevents users in multi-company environments from seeing or selecting accounts from other companies, helping enforce company data separation rules.
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
Public holiday timesheets now reflect each employee's flexible work schedule instead of defaulting to the company's standard 8-hour day. This prevents overstated time off entries for employees whose configured average day is shorter, improving accuracy in timesheets and leave reporting.
Original PR description
## Issue: For employees with flexible working hours, when a Public Holiday is added, the timesheet was filled with 8h based on the company’s default calendar instead of the employee’s flexible…
## Issue: For employees with flexible working hours, when a Public Holiday is added, the timesheet was filled with 8h based on the company’s default calendar instead of the employee’s flexible schedule ## Cause: When creating `resource.calendar.leaves`, timesheets call `_work_time_per_day()` This method uses `work_hours_data` containing half-day intervals (tmp_start/tmp_end) These data come from `_attendance_intervals_batch()`, but we were passing an empty resource, so the check for `flexible_hours` failed: https://github.com/odoo/odoo/blob/bd7d5fdf8df3a4d544de3e2493cd4b3966fa7d0b/addons/resource/models/resource_calendar.py#L382-L393 We want to use the calendar itself as the calendar resource to get the `work_hours_data` ## Steps to reproduce: - On an employee, in Work Information, set the Working Hours to Flexible 40 hours/week - Modify Flexible 40 hours/week (Hours per Week: 30, Average Hour per Day: 6) - In Time Off > Configuration > Public Holidays, add a New holiday (You can leave default values) - Go in Timesheets > All Timesheets, before the fix, the flexible employee have 8h in internal for Time Off opw-4881758
New customers created from Point of Sale now show the configured default pricelist instead of simply using the first available pricelist. This restores the expected behavior and helps cashiers avoid assigning the wrong pricing to new customers.
Original PR description
**Problem:** When creating a new partner from PoS, the suggested pricelist is not the default pricelist we defined in the configuration. It worked before 18.0, but now the suggested pricelist is the first one that we defined in the configuration, not the one we set as default. **Steps to reproduce:** - In the configuration, enable flexible pricelists and fill some available pricelists. - Set a default pricelist that is not the first one you defined in the available section. - Open a session, click on the customer and click on create. - Go to the Sales and Purchase tab. - The pricelist is not the default one. **Why the fix:** If we are in PoS, we now put the default pricelist as a default for the new partner. We only do that if it is available, otherwise we fall back to the default flow. This is how it worked before 18.0. opw-4876573
Invoices using multiple taxes included in the price now calculate taxable bases and tax amounts consistently when some taxes affect later tax calculations and others do not. This prevents incorrect tax report warnings and keeps financial reporting more reliable, with only minor rounding differences expected in related discount scenarios.
Original PR description
**Issue** When creating an invoice with two price-included taxes, one that affects the base of subsequent taxes (`include_base_amount=True`) and another that does not, the tax computation is…
**Issue** When creating an invoice with two price-included taxes, one that affects the base of subsequent taxes (`include_base_amount=True`) and another that does not, the tax computation is incorrect. This leads to inconsistent base amounts and triggers a warning in the tax report, particularly visible in the Tax Return Report. **Steps to Reproduce** 1. Create two taxes with `price_include=True`: Tax1 with "Affect Base of Subsequent Taxes" disabled Tax2 with it enabled 2. Add both taxes to the same invoice line and confirm the invoice 3. Open the Tax Report and filter by the invoice date 4. The report shows an inconsistency because the computed base is wrong **Root Cause** The batching logic separates taxes into groups when their properties differ. In this case, because the two taxes have different `include_base_amount` values, they are split into different batches. Since batching drives how price-included taxes are reversed to compute the base, splitting the batch leads to misinterpreted base amounts and incorrect tax calculations. **Fix** Adjusting batching conditions to allow taxes to be grouped together even if their `include_base_amount` flags differ. This ensures that price-included taxes are handled consistently and the base is computed correctly across all taxes in the group. Opw-4863100 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The Accounting follow-up report now stays usable when customers have many invoices and users load additional report lines. This prevents an error screen during collections or statement review workflows, helping finance teams continue their work without interruption.
Original PR description
**Steps to reproduce:** 1. Install the Accounting module. 2. For partner X, create minimum 90 invoices for `See more/Load more` option into page. 3. In the partner form view, click the Customer…
**Steps to reproduce:**
1. Install the Accounting module.
2. For partner X, create minimum 90 invoices for `See more/Load more` option into page.
3. In the partner form view, click the Customer Statement smart button.
4. Change the Report Type from Customer Statement to Follow-Up Report.
5. In the report, click `See more` in the dropdown → traceback occurs.
**NOTE**
- You can easily create invoices using this cron job to generate 90 invoices.
```py
for i in range(90):
invoice = env['account.move'].create({
'move_type': 'out_invoice',
'partner_id': 10,
'company_id': env.company.id,
'invoice_line_ids': [(0, 0, {
'product_id': 16,
'quantity': 1,
'price_unit': 100.0,
})],
})
invoice.action_post()
```
**Issue:**
`UncaughtPromiseError > OwlError
Uncaught Promise > Got duplicate key in t-foreach: ~account.report~17|~res.partner~42|Due~~
Occured`
- A traceback occurs due to a duplicate key error.
**Cause:** https://github.com/odoo/enterprise/blob/459e8ddaf6f67a556d35bf00e0fbb68eb1500a94/account_reports/static/src/components/account_report/account_report.xml#L72-L73
- In account_report.xml component uses line.id as a key.
<img width="781" height="176" alt="image" src="https://github.com/user-attachments/assets/57bf36ea-6890-45ef-8414-5522d71ece7b" />
- When expanding `See more` headings like `Overdue` are rendered again with the same ID causing a duplicate key error.
<img width="754" height="194" alt="image" src="https://github.com/user-attachments/assets/0eba65e0-0bf2-4f64-a997-27a25e5de5fe" />
**Solution:**
- Use the `line_index` instead of `line.id` as the key, ensuring a unique key for every line and preventing the traceback.
**opw - 5083894**Barcode database lookups now fill in product details only when those fields are empty, so existing eCommerce descriptions are preserved. This prevents manually curated online product content from being accidentally replaced by external barcode data.
Original PR description
Scenario: - enable "Barcode Database" in general settings - set an eCommerce description on a product - set a barcode in the database on that product (eg. 799439112766) Result: the eCommerce description has been overwritten by the barcode lookup result. Fix: do like other _update_product_by_barcodelookup methods and only update value that are not yet set. Note: also fixes the return of the overridden methods. opw-5061231
This fix prevents customers using a QR self-ordering menu on separate devices from being sent to another customer’s order confirmation page after online payment. It ensures each device only confirms the order that belongs to it, reducing confusion during mobile ordering.
Original PR description
Before this commit, if two devices were using the mobile menu, when one order was paid through online payment, the other device was redirected to the confirmation page, but the payment was not for its order. Steps to reproduce: 1. Enable self ordering QR menu + Ordering 2. Create an online PoS payment method with demo payment provider 3. Open the QR code menu on 2 devices 4. On one device, make an order and pay => the other device is redirected to the confirmation page opw-5046207 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Refund orders created from the back office now receive the required identifier, preventing problems when opening them in the Point of Sale screen. This helps staff continue draft refunds and complete payments without interruption.
Original PR description
Before this commit, refunded orders created from the backend were missing a UUID. This could cause issues when trying to load a draft refund order into the PoS UI and proceed with its payment. opw-5081385 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix ensures custom gift card codes entered in Point of Sale are kept even if the order is reloaded before payment. It prevents automatically generated or mixed-up codes from appearing on receipts, PDFs, and backend coupon records.
Original PR description
**Steps to reproduce:** - Go to PoS - Buy a gift card, click on the sell physical gift card - Set a custom code and price - Reload the page - Go through with the payment and check the downloaded pdf…
**Steps to reproduce:** - Go to PoS - Buy a gift card, click on the sell physical gift card - Set a custom code and price - Reload the page - Go through with the payment and check the downloaded pdf - The coupon code is an automatically generated one **Problem:** When reloading the coupons after reloading the order, the gift cards lose their custom codes if it was set before. This means that the coupon will have an automatically generated name in the backend as well as in the pdf that is downloaded once the payment is done. **Why the fix:** This happens because we are trying to access the order.get_selected_orderline()?.gift_code to get the coupon code. https://github.com/odoo/odoo/blob/f13ee41a4a62f7fedbddc4245e52ee8e9dce9e0e/addons/pos_loyalty/static/src/overrides/models/pos_store.js#L230 But when we leave the order to go back in afterwards, there is no selected line anymore, so the gift_code is undefined. We then fallback to the default code, which is to generate one for the user. The gift_code is still on the orderline, so all we need to do is to link the newly created coupon with the gift_code in the orderline. Another problem that arises her is that when purchasing a custom gift card AND a default gift card in the same order, then reloading, the gift codes will be mixed up in the pdf and in the backend as well. This happens because the custom code's name in the backend is 'code' and we use gift_code in the frontend, so we assign the gift_code to the code in the backend. opw-4964509
When a customer is selected in Point of Sale, the Quotation/Order action now shows only that customer’s quotations and orders. This prevents staff from seeing unrelated customer orders and helps them find the right sale faster.
Original PR description
Before this commit, when selecting a customer in the POS and clicking Actions → Quotation/Order, all quotations and orders were displayed instead of filtering by the selected customer. This commit ensures that only the quotations/orders of the selected customer are shown. opw-5074052 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Website page templates with highlight effects now keep the correct simplified highlight setup when selected from the preview. This prevents visual highlight issues from being carried into newly created pages, improving consistency 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
Partially refunded point-of-sale orders now recalculate the amount due using only the remaining order lines. This prevents customers or staff from paying the original full total again when processing a later refund.
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
Refreshing appointment time slots could fail when no resource was selected because the system tried to read an empty value as a number. This fix handles empty selections safely, so customers can refresh available appointment slots without errors.
Original PR description
When refreshing the slots, it's possible that the resource_selected_id is equal to None, False or just empty string. This was leading to some error when parsing it to an integer. This commit move the parsing into the method computing the max possible capacity after checking if we got a value. Related commit 3cca7e47ab58f8a7d4e9196dbf60f7068348216b task-5102895 Forward-Port-Of: odoo/enterprise#95144