Daily updates from Odoo
Tuesday, November 18, 2025
16 changes · master
Resolved issues and error corrections
This fixes a crash that could happen when certain accounting report screens used manually generated data models. The affected pages now include the required service, helping users access account return and report views reliably.
Original PR description
With this PR: https://github.com/odoo/odoo/pull/229492, comes a new service which is needed on models. Without this service on our manually generated models, this would crash because it was trying to access an undefined variable.
Approved late hours for Saudi employees are now included when generating payslips. This ensures payroll deductions or calculations tied to lateness are reflected correctly and consistently after module installation.
Original PR description
Reproduce 1. create an attencande for SA employee with latehours 2. approve latehours 3. create a payslip for this employee. you will not find the hours reflected to the payslip Issue the property input rule that take the late hours amount was missed Solution add the rule back and make sure it is added to the defention on the module installation Task: 5253150
The Ask AI action now handles cases where a user has multiple AI chat channels without crashing. It also starts a fresh AI chat from the main entry point and removes a duplicate search-view button, making the experience more reliable and less cluttered.
Original PR description
When multiple AI chat channels existed for the same agent/user, `_get_or_create_ai_chat` could return several records. This caused a singleton error when calling `action_ask_ai` because the code expected a single channel record. This commit filters a single record so that only one channel is returned, preventing the crash. And also 'action_ask_ai' will now always opens a new ai chat. Additionally, the redundant 'Ask AI' button in the search view has been removed, as the same functionality is already available from the systray. task-5107276 Forward-Port-Of: odoo/enterprise#95585
The OCR process will no longer automatically change a customer invoice into a sale receipt when the Sale Receipt option is not enabled. This prevents documents from being categorized into a disabled workflow and helps keep invoice processing aligned with company settings.
Original PR description
If the "Sale Receipt" setting isn't enabled, the OCR should never automatically switch a customer invoice to a sale receipt. task-[5265382](https://www.odoo.com/odoo/project.task/5265382) Forward-Port-Of: odoo/enterprise#99522
Payment reminder emails now send any files and dynamic reports configured on the selected email template. This ensures customers receive the complete follow-up information intended by the business, reducing missing-document issues and manual resend work.
Original PR description
### Issue: We can add attachments and dynamic report to the email templates, but they are not sent with follow-ups. ### Steps to reproduce: - Go to the "Payment reminder" email template - Under the…
### Issue: We can add attachments and dynamic report to the email templates, but they are not sent with follow-ups. ### Steps to reproduce: - Go to the "Payment reminder" email template - Under the page "Content", add an attachment by clicking the "Attachments" button - Under the page "Settings", add a dynamic report - Create an overdue invoice for a partner - Go on the form view of the partner, "Accounting" page - Click "Send", make sure the template used is the one with the attachments - Send - The attachments on the template and the dynamic report are not sent ### Cause: The mail template to send the follow-ups is only used to prefill the wizard. ### Solution: Add the template in `_get_wizard_options()` to add the template in the option and later use it to add/generate its attachments. This commit also refactors how the attachments are computed: The previous code was adding the invoices PDFs then removing them. The whole process was confusing. Now `options['attachment_ids']` is appended in `_get_followup_attachments()` with the desired attachments depending on the options. Also `_get_invoices_to_print()` had unnecessary lines. The options are always initiated before calling the method and the condition on "manual_followup" is useless as the invoices are already in options['attachment_ids'] when coming from the wizard. opw-5147736 Forward-Port-Of: odoo/enterprise#99458 Forward-Port-Of: odoo/enterprise#98454
Payroll PDF generation now handles certain report errors without stopping the scheduled process. If one employee declaration cannot be generated, the error is saved on that record and the system continues processing the remaining payroll documents.
Original PR description
When rendering PDF files, `_get_rendering_data` is expected to return a dict with the key `error` when needed. Some localizations respect this correctly, but others will raise an UserError instead. In particular, the `Payroll: Generate pdfs` cron will keep trying to generate the file and the `UserError` will never be caught, so the scheduled action will eventually be deactivated. With this fix, the exception is caught, the message is recorded on the sheet, and the PDF is skipped. The cron will then keep processing the other records. Source: investigation after the cron got disabled on our server Forward-Port-Of: odoo/enterprise#99490
When a cashier tries to sync orders while the Belgian blackbox connection is unavailable, affected orders are now returned to draft instead of remaining stuck. This lets staff retry the sync once the connection is restored, reducing checkout disruption.
Original PR description
When trying to sync orders while being offline, a `ConnectionLostError` is raised. This error was not handled in the pos_blackbox_be module. Now, if an order was not signed correctly by the blackbox, we put its state back to "draft", allowing the cashier to retry later (when the connection to bbox is re-established). Forward-Port-Of: odoo/enterprise#99202 Forward-Port-Of: odoo/enterprise#98778
This fix ensures automated tests properly finish drag-and-drop actions before ending. It helps prevent false test failures and supports more stable quality checks for scheduling-related features.
Original PR description
Since drag sequences are automatically canceled at the end of tests, 'cancel' or 'drop' calls should be properly awaited before the end of a test. This commit ensures that these actions are properly finished before a test ends. Community: https://github.com/odoo/odoo/pull/235359 Forward-Port-Of: odoo/enterprise#99634 Forward-Port-Of: odoo/enterprise#99369
This fix restores the ability to add reactions to messages when using Discuss on a mobile device. It improves day-to-day collaboration by making quick responses work consistently across desktop and mobile.
Original PR description
Task-4607436 Task-5261880 https://github.com/odoo/odoo/pull/235852 Forward-Port-Of: odoo/enterprise#99588
VoIP contact search now avoids checking mobile phone matches until at least three characters are entered. This prevents error messages from appearing while users type the first few digits or letters, making the search experience smoother.
Original PR description
`phone_mobile_search` doesn't allow you to search for less than 3 characters. This commit excludes `phone_mobile_search` from the search domain when there are less than 3 characters. This avoids triggering an UserError on the first characters typed. Forward-Port-Of: odoo/enterprise#99626 Forward-Port-Of: odoo/enterprise#99548
Fixes an issue where switching variants on subscription products in the online shop could trigger an error when no pricing was available. The system now handles missing pricing safely, helping customers browse subscription product options without interruption.
Original PR description
Step to reproduce: - install website_sale_subscription - create a product, add few variants and tick 'Subscriptions' option. - open that product from /shop - toggle between variants Cause: - In case the pricing is not present, 'False' is passed(not an iterable) - `_onChangeCombinationSubscription` expects a iterable, causing traceback Fix: - we pass empty list instead of False opw-5241612 Forward-Port-Of: odoo/enterprise#99160
Studio no longer crashes when users edit JSON-based fields such as analytic distribution. The update lets these fields handle placeholder settings correctly, improving reliability when customizing forms.
Original PR description
When trying to edit the `analytic_distribution` field using Studio, the following traceback occurred: `Caused by: TypeError: Cannot read properties of undefined (reading 'subOptions')` This happened because the new option `placeholder_field` was [introduced](https://github.com/odoo/odoo/commit/6620ebbd184de6f106fceb4427a081b61d97296a) for dynamic placeholders in widget. However, there was no support declared for `placeholder` inside the `FIELD_TYPE_ATTRIBUTES` definition for the `json` field type. This commit adds `EDITABLE_FIELD_ATTRIBUTES.placeholder` to the `json` field type, allowing widgets on JSON fields to correctly handle `placeholder_field` options without causing a Studio crash. opw - 5180896 upg - 3249816 Forward-Port-Of: odoo/enterprise#98526
This fix prevents Belgian tax return generation from crashing when a company’s fiscal year is configured to end on February 29. The date calculation now handles leap-year settings correctly, helping migrations and return generation complete reliably.
Original PR description
``` File "/tmp/tmpm_3a__2e/migrations/account_reports/saas~18.3.1.0/end-account-returns.py", line 340, in migrate generate_or_refresh_all_returns(company) File…
```
File "/tmp/tmpm_3a__2e/migrations/account_reports/saas~18.3.1.0/end-account-returns.py", line 340, in migrate
generate_or_refresh_all_returns(company)
File "/home/odoo/src/enterprise/19.0/account_reports/models/account_return.py", line 228, in _generate_or_refresh_all_returns
self._generate_all_returns(fiscal_country.code, company, domestic_tax_unit)
File "/home/odoo/src/enterprise/19.0/l10n_be_reports/models/account_return.py", line 24, in _generate_all_returns
super()._generate_all_returns(country_code, main_company, tax_unit=tax_unit)
File "/home/odoo/src/enterprise/19.0/account_reports/models/account_return.py", line 281, in _generate_all_returns
report_type._try_create_returns_for_fiscal_year(main_company, tax_unit=tax_unit)
File "/home/odoo/src/enterprise/19.0/account_reports/models/account_return.py", line 353, in _try_create_returns_for_fiscal_year
period_date_from, period_date_to = self._get_period_boundaries(main_company, date_pointer)
File "/home/odoo/src/enterprise/19.0/account_reports/models/account_return.py", line 530, in _get_period_boundaries
start_day, start_month = self._get_start_date_elements(company_id)
File "/home/odoo/src/enterprise/19.0/l10n_be_reports/models/account_return.py", line 16, in _get_start_date_elements
fiscal_year_date = date(2025, int(main_company.fiscalyear_last_month), main_company.fiscalyear_last_day)
ValueError: day is out of range for month
```
```
(Pdb) main_company
res.company(3,)
(Pdb) main_company.fiscalyear_last_month
'2'
(Pdb) main_company.fiscalyear_last_day
29
(Pdb) date_from
datetime.date(2025, 3, 1)
```
- During the migration process the system calls [_generate_or_refresh_all_returns](https://github.com/odoo/upgrade/blob/e20a9e2edec4441b2c7aa5858db2a53fb2e9b215/migrations/account_reports/saas~18.3.1.0/end-account-returns.py#L340) which internally uses [_get_start_date_elements](https://github.com/odoo/enterprise/blob/ebdc2fe2ade72b1505dac5490b7df2a1d06fcb4b/l10n_be_reports/models/account_return.py#L14) to compute the fiscal year start date.
- The customer has configured fiscalyear_last_month = February and fiscalyear_last_day = 29 Because of this configuration, the method attempts to construct 29th February 2025, which is invalid since 2025 is not a leap year. The issue occurs because the method uses a hardcoded year [(2025)](https://github.com/odoo/enterprise/blob/ebdc2fe2ade72b1505dac5490b7df2a1d06fcb4b/l10n_be_reports/models/account_return.py#L16) instead of determining the year dynamically.
- I reviewed implementations in other localizations and found that this logic has [1](https://github.com/odoo/enterprise/blob/ebdc2fe2ade72b1505dac5490b7df2a1d06fcb4b/l10n_uk_reports/models/account_return.py#L33), [2](https://github.com/odoo/enterprise/blob/ebdc2fe2ade72b1505dac5490b7df2a1d06fcb4b/l10n_nz_reports/models/account_return.py#L8) already been corrected there to compute the appropriate start date dynamically.
- I’ve updated this localization to follow the improved implementation used in other countries, so the start-date calculation now works correctly in all cases, including leap years and any fiscal year settings the customer may configure.
opw-5249243
Forward-Port-Of: odoo/enterprise#99353The VoIP keypad now keeps numbers inserted in the intended place when users tap digits after moving the cursor. This prevents dialing errors on Android when the phone keyboard is hidden and the input loses focus.
Original PR description
Keypad input now reads selection from the persisted model whenever the DOM selection isn't trustworthy, particularly on Android where the input blurs to hide the keyboard, so digits typed at any cursor location stay in place. task-5241464
The appointment booking error message now clearly includes the appointment type name when there are not enough seats available. This makes the issue easier for users to understand and resolve when saving appointments without resources.
Original PR description
Currently, when creating a new appointment with a specified number of people but no resources, saving the record triggers a UserError that does not display the appointment type name. Issue: 2 seats are missing to be able to book the appointment.type(1,): Table (30) <img width="1813" height="776" alt="image" src="https://github.com/user-attachments/assets/f87f45de-3552-47bb-b34c-fcc06cea425f" /> Solution: 2 seats are missing to be able to book the Table: Table (30) <img width="1769" height="905" alt="image" src="https://github.com/user-attachments/assets/04188071-be67-4500-b720-039ee7a27c2e" /> Forward-Port-Of: odoo/enterprise#99646
This fixes an issue where portal users could see an error when sending an attachment in a live chat with an agent. The change ensures the user availability field is properly set, helping chats continue smoothly without interruption.
Original PR description
Bug === As portal, open a live chat with an agent, and try to send an attachment. An error will be raised because of `offline_since` (which is not initialized in the compute). Task-4687269